c语言 - 使用 linkedlist 存储 txt 的句子



对不起我的代码差,但是当我在Mac终端运行时,我不明白为什么此代码会导致segmentation fault 11。我想通过使用链接列表来使程序读取完整的句子完整,但行不通。我猜some.txt中的句子未插入linkNode中。我该如何修复?

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_NUMBER 1024 
typedef struct linkNode {
    char *element;
    struct linkNode *link;
} linkNode;
typedef struct {
    linkNode *top;
    int element_number;
} linkType;
void error(char* message) {
    fprintf(stderr, "%s", message);
}
void init(linkType *L) {
    L->top = NULL;
    L->element_number = 0;
}
linkNode *createStack() {
    linkNode *temp = (linkNode *) malloc(sizeof(linkNode));
    temp->element = (char *) malloc(sizeof(char) * MAX_NUMBER + 1);
    return temp;
}
void insert(linkType *L, char* new_data) {
    linkNode *temp = createStack();
    //temp->element = new_data;
    strcpy(temp->element, new_data);
    temp->link = L->top;
    L->element_number++;
    L->top = temp->link;    
}
char *delete(linkType *L) {
    if (L->element_number == 0) {
        error("list emptyn");
    }
    linkNode *temp = L->top;
    char * temp_element;
    //temp->element = L->top->element;
    strcpy(temp_element, L->top->element);
    L->top = L->top->link;
    L->element_number--;
    free(temp);
    return temp_element;
}
char *buffer_making() {
    char *buffer = (char *) malloc(sizeof(char) * MAX_NUMBER + 1);
    return buffer;
}
char *buffer_erase(char *buffer) {
    free(buffer);
    return NULL;
}
int main() {
    linkType *q = (linkType *) malloc(sizeof(linkType));
    init(q);
    FILE *file_pointer; 
    char *file1;
    file1 = (char *) malloc(sizeof(file1) + 1); 
    char *file2;
    file2 = (char *) malloc(sizeof(file2) + 1);
    printf("input file names:n");
    scanf("%s", file1);
    getchar();
    file_pointer = fopen(file1, "r");
    while (!feof(file_pointer)) {
        char *buffer1 = buffer_making();
        fscanf(file_pointer,"%s",buffer1);
        ///////////
        printf("%sn",buffer1);
        insert(q,buffer1);
        buffer_erase(buffer1);
    }
    printf("point3n");
    while (!(q->element_number == 0)) {
        printf("%sn", delete(q));
    }
    free(file1);
    free(file2);
    return 0;
}
//printf("point1n");

您的代码有很多不同的问题。让我们一对一地通过它们:

  • 如果您跟踪列表的最后一个节点,则将新元素添加到链接列表中会更容易。因此,您应该将另一个称为bottomlinkNode指针添加到您的linkType结构中:
    typedef struct {
        linkNode *top;
        linkNode *bottom;
        int element_number;
    } linkType;
    

    init功能中的bottom初始化:

    void init(linkType *L) {
        L->top = NULL;
        L->bottom = NULL;
        L->element_number = 0;
    }
    

  • insert函数中,temp是要附加到列表末尾的新节点(如果我正确理解您的问题(,因此您需要将其link指向NULL而不是top。另外,您不应将top指向temp->link。如果这是您插入的第一个节点,则topbottom都应指向temp,否则top将继续指向第一个节点,并且需要更新bottom,以便它指向temp: >
    void insert(linkType *L, char *new_data) {
        linkNode *temp = createStack();
        strcpy(temp->element, new_data);
        temp->link = NULL;
        L->element_number++;
        if (L->top == NULL) {
            L->top = temp;
            L->bottom = temp;
        } else {
            L->bottom->link = temp;
            L->bottom = temp;
        }
    }
    

  • delete功能中,您无需将整个字符串从element复制到temp_element;您可以将temp_element指向element。另外,您无法正确降低element_numberdelete功能应该看起来像:
    char *delete(linkType *L) {
        if (L->element_number == 0) {
            error("list emptyn");
        }
        linkNode *temp = L->top;
        char *temp_element;
        temp->element = L->top->element;
        L->top = L->top->link;
        (L->element_number)--;
        free(temp);
        return temp_element;
    }
    

  • main功能中,您没有正确读取输入文件。fscanf扫描单词,但是由于您想提取句子而不是单词,因此fgetc将是一种更好的方法。while读取的循环应该看起来像:
    int isEof = 0;
    int isEndOfSentence = 0;
    int index = 0;
    while (!isEof) {
        char *buffer1 = buffer_making();
        isEndOfSentence = 0;
        index = 0;
        while (!isEndOfSentence) {
            char c = fgetc(file_pointer);
            if (c == EOF) {
                isEndOfSentence = 1;
                isEof = 1;
            } else if (c == '.') {
                isEndOfSentence = 1;
            }
            // Skip leading whitespace
            if ((isEof || c == ' ' || c == 'n') && index == 0) {
              continue;
            }
            buffer1[index++] = c;
        }
        // Skip empty sentence
        if (index == 0) {
            continue;
        }
        buffer1[index] = '';
        printf("%sn", buffer1);
        insert(q, buffer1);
        buffer_erase(buffer1);
    }
    

    这不是实现阅读句子的最佳方法,但它有效。另外,此代码假定句子以.结束。您可以更新此代码以使其适用于?!等结尾的句子

  • 最后,您删除和打印每个节点的elementwhile循环似乎存在一些问题。您可以使用以下while循环:
    while (!(q->element_number == 0)) {
        printf("%sn", q->top->element);
        delete(q);
    }
    

    希望这会有所帮助。我已经测试了这些更改,它们对我有用。

  • 来自 valgrind

    ==18918== Conditional jump or move depends on uninitialised value(s)
    ==18918==    at 0x4C2E119: strlen (vg_replace_strmem.c:458)
    ==18918==    by 0x4EA4E81: puts (in /lib64/libc-2.25.so)
    ==18918==    by 0x108BE8: main (ll.c:74)
    ==18918== 
    ==18918== Conditional jump or move depends on uninitialised value(s)
    ==18918==    at 0x4C2E1FB: strcpy (vg_replace_strmem.c:510)
    ==18918==    by 0x108A49: insert (ll.c:31)
    ==18918==    by 0x108BFB: main (ll.c:75)
    ==18918== 
    ==18918== Invalid read of size 8
    ==18918==    at 0x108AB1: delete (ll.c:44)
    ==18918==    by 0x108C31: main (ll.c:82)
    ==18918==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
    

    GCC还报告了-Wall的问题:

    ll.c: In function ‘delete’:
    ll.c:44:5: warning: ‘temp_element’ is used uninitialized in this function [-Wuninitialized]
         strcpy(temp_element,L->top->element);
    

    一个问题是您正在调用strcpy而不为目的地分配内存。另一个问题是您在不验证其非NULL的情况下取消L->top

    与我的朋友的帮助,我可以在终端中正确打印出来!特别感谢那些回答我问题的人!谢谢你!

    实际上我真正想要的只是链接列表,仅由linkNode *top表示,我编辑了我的预期。:)

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define MAX_NUMBER 1024 
    typedef struct linkNode{
        char * element;
        struct linkNode * link;
    }linkNode;
    typedef struct{
        linkNode *top;
        int element_number;
    }linkType;
    void error(char* message){
        fprintf(stderr,"%s", message);
    }
    void init(linkType *L){
        L->top=NULL;
        L->element_number = 0;
    }
    linkNode * createStack(){
        linkNode * temp = (linkNode *)malloc(sizeof(linkNode));
        temp->element = (char *)malloc(sizeof(char)*MAX_NUMBER+1);
        return temp;
    }
    void insert(linkType *L,char* new_data){
        linkNode *temp = createStack();
        //temp->element = new_data;
        strcpy(temp->element,new_data);
        temp -> link = NULL;
        L->element_number++;
        if(L->top ==NULL){
            L->top =temp;
        }
        else{
        temp->link = L->top;
        L->top = temp;  
        }
    }
    char * delete(linkType *L){
        if(L->element_number ==0)
        {
            error("list emptyn");
        }
        linkNode *temp = NULL;
        temp = L->top;
        char * temp_element;
        temp->element = L->top->element;
        L->top = L->top->link;
        (L->element_number)--;
        free(temp);
        return temp_element;
    }
    char * buffer_making(){
        char* buffer = (char *)malloc(sizeof(char)*MAX_NUMBER+1);
        return buffer;
    }
    char * buffer_erase(char * buffer){
        free(buffer);
        return NULL;
    }
    int main(){
        linkType q ;
        init(&q);
        FILE *file_pointer; 
        char * file1;
        file1 = (char*)malloc(sizeof(file1)+1); 
        char * file2;
        file2 = (char*)malloc(sizeof(file2)+1);
        printf("input file names:n");
        scanf("%s",file1);
        getchar();
        file_pointer=fopen(file1,"r");
        while(1){
        char * buffer1 = buffer_making();
        if(fscanf(file_pointer,"%s",buffer1)==EOF) break;
        ///////////
        printf("%sn",buffer1);
        insert(&q,buffer1);
        buffer_erase(buffer1);
        }
        printf("point3n");
        while(!(q.element_number==0))
        {
            printf("%sn", q.top->element);
            delete(&q);
        }
        free(file1);
        free(file2);
        return 0;
    }
    

    相关内容

    最新更新