Coredump when parsing chapters
I am doing a homework assignment that reads in a book. First, a line is read in and a pointer made to point at that line. Then a paragraph function reads in lines and stores their address into a array of pointers. Now, I am on reading a chapter (a paragraph recognized by the next line being broke). It should call get_paragraph()
and store the address of paragraphs until it comes to a new chapter.
A new chapter is the only time in the book where the first character in the line is not a space. I think this is were I am having problems in my code. All functions up to this point work. I hope I have provided enough information. The code compiles but core dumps when started.
I am a student and learning so please be kind. Thanks.
char*** get_chapter(FILE * infile){
int i=0;
char **chapter[10000];//an array of pointers
// Populate the array
while(chapter[i]=get_paragraph(infile)) { //get address store into array
if(!isspace(**chapter[0])){ //check to see if it is a new chapter<---problem line?
// save paragraph not used in chapter using static to put into next chapter
break;
}
i++;//increment array
}
//add the null
chapter[++i]='\0';//put a null at the end to signify end of array
//Malloc the pointer
char**(*chap) = malloc(i * sizeof(*chap));//malloc space
//Copy the array to the pointer
i=0;//reset address
while(chapter[i]){//while there are addresses in chapter
chap[i] = chapter[i++];//change addresses into chap
}
chap[i]='\0';//null to signify end of chapter
//Return the pointer
return(chap);//return pointer to array
}
For those who would rather see without comments:
char*** get_chapter(FILE * infile){
int i=0;
char **chapter[10000];
while(chapter[i]=get_paragraph(infile)) {
if(!isspace(**chapter[0])){
break;
开发者_C百科 }
i++;
}
chapter[++i]='\0';
char**(*chap) = malloc(i * sizeof(*chap));//malloc space
i=0;
while(chapter[i]){
chap[i] = chapter[i++];
}
chap[i]='\0';
return(chap);
}
Comments inline.
char*** get_chapter(FILE * infile) {
int i=0;
// This is a zero length array!
// (The comma operator returns its right-hand value.)
// Trying to modify any element here can cause havoc.
char **chapter[10,000];
while(chapter[i]=get_paragraph(infile)) {
// Do I read this right? I translate it as "if the first character of
// the first line of the first paragraph is not whitespace, we're done."
// Not the paragraph just read in -- the first paragraph. So this will exit
// immediately or else loop forever and walk off the end of the array
// of paragraphs. I think you mean **chapter[i] here.
if(!isspace(**chapter[0])){
break;
}
i++;
}
// Using pre-increment here means you leave one item in the array uninitialized
// which can also cause a fault later on. Use post-increment instead.
// Also '\0' here is the wrong sort of zero; I think you need NULL instead.
chapter[++i]='\0';
char**(*chap) = malloc(i * sizeof(*chap));
i=0;
while(chapter[i]) {
// This statement looks ambiguous to me. Referencing a variable twice and
// incrementing it in the same statement? You may end up with an off-by-one error.
chap[i] = chapter[i++];
}
// Wrong flavor of zero again.
chap[i]='\0';
return(chap);
}
Can I suggest that you use for
loops instead of while
s? You need to stop if you run out of space, so you might as well use the appropriate construct.
I suspect you have a bug in this code:
while(chapter[i]=get_paragraph(infile)) {
if(!isspace(**chapter[0])){
break;
}
i++;
}
chapter[++i]='\0';
Firstly, shouldn't it be chapter[i]
instead of chapter[0]
? You want to know if the pointer at chapter[i]
points to a space, not the first pointer in chapter
. So this will probably loop indefinitely - hence the need for a for
loop, so you don't just loop forever accidentally.
Secondly, you increment i
at the end of the while block, and then again in the chapter[++i]
assignment. i
has already been incremented by the final loop execution before the while condition breaks, so it is already the correct position to use. ++i
increments before yielding the value, so presumably you meant to have i++
here, so that it would increment after yielding the current value of i
. Either way, it's confusing one of us as to what you mean, so maybe just put the increment on a separate line for clarity. The compiler will sort out any available optimisation.
Finally (and I might well be wrong here) why are you setting the value to '\0'
? That's a null character, isn't it? But your array is of pointers. The null pointer would be 0
, rather than '\0'
, I think. If I'm right, you might have still got away with it if '\0'
yields the same set of zeroes as the null pointer.
Have you tried single stepping though it in gdb, and occasionally dumping the local variables to see the current state? It's a good way to learn. You may want to add a few extra intermediate variables that "info locals" will automatically dump as well (pointers to the current XXX, where XXX is various items in your hierarchy)
I assume a GNU environment:
% gcc -g homework.c -o hw
% gdb hw
(gdb) b 10
(gdb) r
(gdb) info locals
(gdb) n
(gdb) info locals
...
Replace "10" with a suitable line number near the beginning of the function.
Shouldn't it be:
if(!isspace(**chapter[i])){
Each chapter[i]
is a pointer to a pointer to a char
, this char
is the first character in each chapter. So **chapter[i]
represents the first character in chapter i
. Using chapter[0]
will only look at the first chapter.
精彩评论