1

I have a program which I am working on for an assignment. This has to be a linked list which reads character by character from a file and then creates words which then get written to the output file. I am able to compile the code with just warnings and no errors. When I try to run the program with an input.txt and output.txt the program runs and then terminal produces the first line which is file opened followed by segmentation fault:11 I have no idea how to fix this or work around it to get it fixed.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct s_words {
    char *str;
    int count;
    struct s_words* next;  
}
words;

words *create_words(char *word) {
    //allocate space for the structure
    words *newWord = malloc(15);
    if (NULL != newWord) {
        //allocate space for storing the new word in "str"
        //if str was array of fixed size, storage would be wasted
        newWord->str = (char *)malloc(strlen(word));
        strcpy(newWord->str, word); //copy word into newWord->str
        newWord->str[strlen(word)] = '\0';
        newWord->count = 1;   //initialize count to 1;
        newWord->next = NULL; //initialize next;
    }
    return newWord;
}

words *add_word(words *wordList, char *word) {
    int found = 0;
    words *temp = wordList;
    // search if word exists in the list; if so, make found=1
    while (temp != NULL) {
        if (strcmp(temp, word)) {  //use strcmp command
            found = 1;
            wordList->count++; //increment count;
            return wordList;
        } else {
            temp = temp->next;  //update temp
        }
    }
    if (found == 0) {  //new word
        words *newWord = create_words(word); 
        if (NULL != newWord) {
            wordList = newWord;
            newWord->next = temp;
            //??  Insert new word at the head of the list
        }
        return newWord;
    }
}

int main(int argc, char *argv[]) {
    words *mywords;  //head of linked list containing words
    mywords = NULL;

    FILE *myFile;
    myFile = fopen(argv[0], "r");  //first parameter is input file
    if (myFile == 0) {
        printf("file not opened\n");
        return 1;
    } else {
        printf("file opened \n");
    }

    //start reading file character by character;
    //when word has been detected; call the add_word function
    int ch, word = 0, k = 0;
    char thisword[100];
    while ((ch = fgetc(myFile)) != EOF) {
        if (ch == ' ') { //detect new word? Check if ch is a delimiter
            if (word == 1) { //make sure previous character was not delimiter
                printf("hi");
                word = 0;
                thisword[k] = '\0'; //make the kth character of thisword as \0

                add_word(mywords, thisword);   //now call add_word to add thisword into the list
                mywords = NULL;
                k = 0;
            }
        } else {
            word = 1;
            thisword[k] = ch; //make the kth character of thisword equal to ch
            k++;
        }
    }
    fclose(myFile); 

    words *currword;
    printf("printing list\n");

    words *temp;
    //Traverse list and print each word and its count to outputfile
    //output file is second parameter being passed

    FILE *outputFile;
    outputFile = fopen(argv[1], "w");
    if (outputFile == 0) {
        printf("file not opened\n");
        return 1;
    } else {
        printf("file opened \n");
    }

    currword = mywords;

    while (currword != NULL) {
        fprintf(outputFile, "HI");
        fprintf(outputFile, "%s %d" , currword, currword->count);
        temp = currword;
        currword = temp->next;
    }
    return 0;
}

Any help would be greatly appreciated

EDIT Here is the updated code: CODE

The new output is now this: here are the files test.txt results.txt file opened hihihihihihihihihihihihihihihiprinting list file not opened Abort trap: 6

3
  • 4
    You realize that compiler warnings should be taken seriously? It's not "just warnings", it's decades of experience with the language telling you you're doing something stupid. You'd do well to listen. Commented Mar 7, 2016 at 21:26
  • Just 3 warnings, only two of which will cause seg faults, lol. The third one is telling you that it's silly to have a variable called found when the function returns immediately after setting found to 1. Commented Mar 7, 2016 at 21:33
  • argv[0] contains the pathname to your executable. argv[1] contains the pathname to your input file. Finally argv[2] contains the pathname to your output file. In your current code you are attempting to read the executable one character at a time and that causes segfault. Commented Mar 7, 2016 at 22:17

2 Answers 2

1

The way you allocate the string in the word structure is incorrect:

        newWord->str = (char *)malloc(strlen(word));
        strcpy(newWord->str, word); //copy word into newWord->str
        newWord->str[strlen(word)]='\0';

You must allocate one more byte for the '\0' terminator:

        newWord->str = malloc(strlen(word) + 1);
        strcpy(newWord->str, word);

You can simplify this with a single call to strdup():

        newWord->str = strdup(word);

Furthermore, you call strcmp(temp, word) to compare the word with the string of the current entry, this is incorrect, and the compiler must have issued a warning for this error. You should instead write:

    if (strcmp(temp->str, word)) {

In main(), you call add_word() incorrectly:

    add_word(mywords, thisword);   //now call add_word to add thisword into the list
    mywords = NULL;

You should write:

    mywords = add_word(mywords, thisword);   //now call add_word to add thisword into the list

In the print loop, you pass currword to printf for %s instead of currword->str. You do not need an extra temp variable either:

while (currword != NULL) {
    fprintf(outputFile, "HI");
    fprintf(outputFile, "%s %d" , currword->str, currword->count);
    currword = currword->next;
}

EDIT: your function add_word does not always return a value to the caller, and it does not correctly insert the newWord at the head of the list.

Here is a modified version:

words *add_word(words *wordList, char *word) {
    // search if word exists in the list; if update count and return
    for (words *temp = wordList; temp != NULL; temp = temp->next) {
        if (strcmp(temp, word)) {  //use strcmp command
            wordList->count++; //increment count;
            return wordList;
        }
    }
    words *newWord = create_words(word); 
    if (newWord != NULL) {
        // Insert new word at the head of the list
        newWord->next = wordList;
        wordList = newWord;
    }
    return newWord;
}

Finally, the reason you get a segfault might be that you do not check the array size when adding characters to it as you read from the input file. You may wonder why, since the input file probably has small words in it... but you are not reading the input file passed as the first command line argument, you are reading the executable file itself as you do this:

myFile = fopen(argv[0], "r");  //first parameter is input file

argv[0] is the name of the executing program.

You should also change the other fopen, otherwise you will overwrite your input.txt file:

myFile = fopen(argv[1], "r");  //first parameter is input file
...
outputFile = fopen(argv[2], "w"); // second parameter is output file
Sign up to request clarification or add additional context in comments.

10 Comments

I changed the things that you suggested. When compiling I get this warning: assignment2.c:49:1: warning: control may reach end of non-void function [-Wreturn-type] } ^ and when attempting to run the program I still get a segmentation fault:11
@bestnymfan: yes, I forgot to give you the fix for that warning. The reason you get a segmentation fault is subtile, I added that too.
Yeah I just saw that I had the wrong argv in both of my fopen's. I changed them to the correct values and then tested with a printf to make sure the file names are correct. I also changed everything to your suggestions. The program now compiles with no errors or warnings but still has a segfault. Could it be anything else, I am super confused at this point
@bestnymfan: post the updated code to a pastebin and share it.
Here is the pastebin: link I now run the code and the output from the terminal is: here are the files test.txt results.txt file opened hihihihihihihihihihihihihihihiprinting list file not opened Abort trap: 6 I am now reading the first file thats why theres a hi overtime a new word was read. Storing some words but when it gets to the writing part it shoots out the Abort trap:6 error
|
0

Learning to debug yourself is important. There are some debugging tools available that you should take advantage of.

Compile your program with the -g flag, then run it with one of these to explore your problem. Also take your commenter's advice in fixing your warnings.

GDB https://www.gnu.org/software/gdb/

Valgrind http://valgrind.org/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.