In my program I am getting a seg fault and I’m not sure the cause or how to find out the cause. Any help would be greatly appreciated!
In the code I am trying to read word by word, but I need to keep track of the line numbers. Then I am trying to create a linked list where the data is the word and line number.
(there are two files compiled together)
void main(int argc, char **argv){
file = fopen(argv[1],"r");
struct fileIndex *fIndex = NULL;
delimiters = " .,;:!-";/*strtok chars to seperate*/
int wCount = wordcount(file);/*number of words in file*/
char **str[wCount+1];/*where the lines are being stored*/
int j=0;
while(!feof(file)){/*inserting lines*/
fscanf(file, "%s", &str[j]);
j++;
}
char *token, *cp;
int i;
int len;
for(i = 0; str[i]; i++){/*checking to insert words*/
len = strlen(*str[i]);
cp = xerox(*str[i]);
token = strtok(cp, delimiters);
if(!present(fIndex, token)){
insert(fIndex, i+1,token);
}
while(token!=NULL){
token = strtok(NULL, delimiters);
if(!present(fIndex, token)){
insert(fIndex, i+1,token);
}
}
i++;
}
fclose(file);
}
int strcmpigncase(char *s1, char *s2){/*checks words*/
for(;*s1==*s2;s1++,s2++){
if(*s1=='\0')
return 0;
}
return tolower(*s2)-tolower(*s2);
}
present(struct fileIndex* fIndex, char *findIt){/*finds if word is in structure*/
struct fileIndex* current = fIndex;
while(current!=NULL){
current = current -> next;
if(strcmpigncase(current -> str, findIt)==0){
return current -> lineNum;
}
}
return 0;
}
void insert(struct fileIndex *head, int num, char *insert){/*inserts word into structure*/
struct fileIndex* node = malloc(sizeof(struct fileIndex));
node -> str = insert;
node -> lineNum = num;
node -> next = head;
head = node;
}
#define IN_WORD 1
#define OUT_WORD 0
int wordcount(FILE *input)/*number of words in file*/
{
FILE *open = input;
int cur; /* current character */
int lc=0; /* line count */
int state=OUT_WORD;
while ((cur=fgetc(open))!=EOF) {
if (cur=='\n')
lc++;
if (!isspace(cur) && state == OUT_WORD) {
state=IN_WORD;
}
else if (state==IN_WORD && isspace(cur)) {
state=OUT_WORD;
}
}
return lc;
}
char *xerox(char *s){
int i = strlen(s);
char *buffer = (char *)(malloc(i+1));
if(buffer == NULL)
return NULL;
char *t = buffer;
while(*s!='\0'){
*t=*s;
s++; t++;
}
*t = '\0';
return buffer;
}
This code has a fairly high rate of problems. I’ll dissect just the first few lines to give an idea:
mainshould returnint, notvoid. Probably not causing your problem, but not right either.You really need to check the value of
argcbefore trying to useargv[1]. Invoking the program without an argument may well lead to a problem. Depending on how you’ve invoked it, this could be the cause of your problem.Unless you’ve included some headers you haven’t shown, this shouldn’t compile —
struct fileIndexdoesn’t seem to have been defined (nor does it seem to be defined anywhere I can see in the code you’e posted).This (
wordcount) reads to the end of the file, but does not rewind the file afterward.From your description, you don’t really have any need to store lines (plural) at all. What you probably want is to read one line, then tokenize it and insert the individual tokens (along with the line number) into your index, then read the next line. From what you’ve said, however, there’s no real reason to store more than one raw line at a time though.
As noted above, you’ve previously read to the end of the file, and never rewound the file. Therefore, nothing inside this loop should ever execute, because as soon as you get here,
feof(file)should returntrue. When/if you take care of that, this loop won’t work correctly — in fact, a loop of the formwhile (!feof(file))is essentially always wrong. Under the circumstances, you want to check the result of yourfscanf, with something like:…so you exit the loop when attempting to read fails.
What you have here is basically equivalent to the notorious
gets— you’ve done nothing to limit the input to the size of the buffer. As shown above, you normally want to use%[some_number]s, wheresome_numberis one smaller than the size of the buffer you’re using (though, of course, to do that you do need a buffer, which you don’t have either).You’ve also done nothing to limit the number of lines to the amount of space you’ve allocated (but, as with the individual lines, you haven’t allocated any). I almost hesitate to mention this, however, because (as mentioned above) from your description you don’t seem to have any reason to store more than one line anyway.
Your code also leaks all the memory it allocates — you have calls to
malloc, but not a single call tofreeanywhere.Actually, some of the advice above is (at last more or less) wrong. It’s looking at how to fix an individual line of code, but in reality you probably want to structure the code a bit differently in general. Rather than read the file twice, once to count the words, then read it again to index the words, you probably want to read a line at a time (probably with
fgets, then break the line into words, and count each word as you insert it into your index. Oh, and you almost certainly do not want to use a linked-list for your index either. A tree or a hash-table would make a great deal more sense for the job.I also disagree with the suggestion(s) in the direction of using a debugger on this code. A debugger is not likely to lead toward significantly better code — it may help you find a few of the localized problems, but is unlikely to lead toward a significantly better program. Instead, I’d suggest a pencil and a piece of paper as the tools you really need to use. I believe your current problems stem primarily for not having thought about the problem enough to really understand what steps are needed to accomplish the goal, and a debugger isn’t likely to help much in finding an answer to that question.