繁体   English   中英

链表C程序导致分段错误:11

[英]Linked List C program results in segmentation fault:11

我有一个正在做作业的程序。 这必须是一个链表,该链表从文件中逐个字符地读取字符,然后创建单词,然后将其写入输出文件。 我能够只使用警告而没有错误地编译代码。 当我尝试使用input.txtoutput.txt运行程序时,程序运行,然后终端生成第一行,该行被file opened随后出现segmentation fault:11我不知道如何解决此问题或解决该问题它固定。

#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;
}

任何帮助将不胜感激

编辑这是更新的代码: CODE

现在的新输出是:这是文件test.txt results.txt文件已打开,hihihihihihihihihihihihihihihiprinting列表文件未打开中止陷阱:6

word结构中分配字符串的方式不正确:

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

您必须为'\\0'终止符再分配一个字节:

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

您可以通过一次调用strdup()来简化此strdup()

        newWord->str = strdup(word);

此外,您调用strcmp(temp, word)将该单词与当前条目的字符串进行比较,这是不正确的,并且编译器必须针对此错误发出警告。 您应该改写:

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

main() ,您错误地调用了add_word()

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

您应该写:

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

在打印循环中,将currword传递给printf%s而不是currword->str 您也不需要额外的temp变量:

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

编辑 :您的函数add_word并不总是将值返回给调用者,并且它不能正确地将newWord插入列表的开头。

这是修改后的版本:

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;
}

最后,出现段错误的原因可能是,当您从输入文件中读取字符时,未在向其添加字符时检查数组大小。 您可能想知道为什么,由于输入文件中可能包含小的单词...但是您没有读取作为第一个命令行参数传递的输入文件,因此您正在读取可执行文件本身:

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

argv[0]是执行程序的名称。

您还应该更改另一个fopen ,否则将覆盖input.txt文件:

myFile = fopen(argv[1], "r");  //first parameter is input file
...
outputFile = fopen(argv[2], "w"); // second parameter is output file

学习调试自己很重要。 您应该利用一些调试工具。

使用-g标志编译程序,然后使用其中之一运行它以探究您的问题。 在修正警告时,也请听取评论者的建议。

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

瓦尔格朗德http://valgrind.org/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM