C 从文件中逐个读取字符串并将其添加到链接列表中

C 从文件中逐个读取字符串并将其添加到链接列表中,c,string,file,text,C,String,File,Text,我试图从文本文件中逐个读取字符串,并将其添加到链接列表中。节点包含字符串本身以及该字符串在文件中的出现次数。因此,每个字符串只会被添加到链表中一次,如果链表中已有该字符串,则节点中的int num变量应增加1禁止使用数组。 typedef struct node { char *word; int num; struct node *next; } node; node* addToHead(node *head, char word[]) { if(Conta

我试图从文本文件中逐个读取字符串,并将其添加到链接列表中。节点包含字符串本身以及该字符串在文件中的出现次数。因此,每个字符串只会被添加到链表中一次,如果链表中已有该字符串,则节点中的int num变量应增加1禁止使用数组。

typedef struct node
{
    char *word;
    int num;
    struct node *next;
} node;

node* addToHead(node *head, char word[])
{
    if(Contains(head, word) == 0)
    {
        node *tmp = (node*)malloc(sizeof(node));
        tmp->word = (char)malloc((sizeof(char)* strlen(word) + sizeof(char)));
        tmp->word = word;
        tmp->num = 1;

        if(head == NULL)
        {
            tmp->next = NULL;
            head = tmp;
        }
    }
    return head;
}
node* add(node *head, char word[])
{
    if(Contains(head, word) == 0)
    {
        node *iter = head;
        node *tmp = (node*)malloc(sizeof(node));
        tmp->word = (char)malloc((sizeof(char)* strlen(word) + sizeof(char)));
        tmp->word = word;
        tmp->num = 1;
        if(head != NULL)
        {
            while(iter->next != NULL)
                iter = iter->next;

            iter->next = tmp;
            tmp->next = NULL;
            return head;

        }
        else if(head == NULL)
        {
            head = addToHead(head, word);
            return head;
        }

    }
 return head;
}
int Contains(node *head, char word[])
{
    node *iter = head;
    while(iter!= NULL)
    {
        if(strcmp(iter->word, word) == 0)
        {
            iter->num++;
            return 1;
        }
        iter = iter->next;
    }
    return 0;
}
void printList(node *head)
{
    node *iter = head;
     while(iter!=NULL)
    {
        printf("word: %s || number of word: %d\n", iter->word, iter->num);
        iter=iter->next;
    }
}
   int main()
   {
        node *head=NULL;


    FILE* file= fopen("text.txt", "r");
    char word[500];

    for(int i = 0; fscanf(file, "%s", word) != EOF; i++)
    {

        head = add(head, word);

        printList(head);

    }
    printList(head);




    return 0;
}
在这段代码中,每次向链表添加新字符串时,我都会重写链表。据我所知,它不会生成新节点,而是在先前添加的单词上重写单词。COMMA和dots不是问题。我写了3次相同的Lorem Ipsum段落。输出如下所示:


从文件中读取单词时,如何为每个单词创建单个节点?

使用6个字符串的固定大小数组进行测试,您的代码工作正常,打印输出如预期:

int main()
{
    node *head=NULL;
    char * word[6] = {"Alpha", "Beta", "Alpha", "Teta", "Alpha", "Beta"};

    for(int i = 0; i<6; i++)
    {
        head = add(head, word[i]);
    }
    printList(head);
    return 0;
}

因此,正如在注释中所解释的,问题似乎在于您分配这些字符串和/或从文件中读取它们的方式。

如上所述,您的代码有几个问题:

  • tmp->word=(char)malloc((sizeof(char)*strlen(word)+sizeof(char))。Malloc返回一个指向已分配地址的指针,因此您应该写入:
    
    tmp->word=(char*)malloc((sizeof(char)*strlen(word)+sizeof(char))

  • 这就是您无法获得预期输出的原因:
    tmp->word=word
    ,即使您分配了一个新节点,它的单词字段也会指向当前单词。因此,当你在循环中阅读一个单词时,你是在意外地改变
    head->word
    。所以你应该这样做
    strcpy(tmp->word,word)

  • 我已经添加了正确的代码供您参考

    #include<stdio.h>
    typedef struct node
    {
        char *word;
        int num;
        struct node *next;
    } node;
    
    node* addToHead(node *head, char word[])
    {
        if(Contains(head, word) == 0)
        {
            node *tmp = (node*)malloc(sizeof(node));
            //tmp->word = (char)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            //tmp->word = word;
            tmp->word = (char *)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            strcpy(tmp->word, word);
            tmp->num = 1;
    
            if(head == NULL)
            {
                tmp->next = NULL;
                head = tmp;
            }
        }
        return head;
    }
    node* add(node *head, char word[])
    {
        if(Contains(head, word) == 0)
        {
            node *iter = head;
            node *tmp = (node*)malloc(sizeof(node));
            //tmp->word = (char)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            //tmp->word = word;
            tmp->word = (char *)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            strcpy(tmp->word, word);
            tmp->num = 1;
            if(head != NULL)
            {
                while(iter->next != NULL)
                    iter = iter->next;
    
                iter->next = tmp;
                tmp->next = NULL;
                return head;
    
            }
            else if(head == NULL)
            {
                head = addToHead(head, word);
                return head;
            }
    
        }
     return head;
    }
    int Contains(node *head, char word[])
    {
        node *iter = head;
        while(iter!= NULL)
        {
            if(strcmp(iter->word, word) == 0)
            {
                iter->num++;
                return 1;
            }
            iter = iter->next;
        }
        return 0;
    }
    void printList(node *head)
    {
        node *iter = head;
         while(iter!=NULL)
        {
            printf("word: %s || number of word: %d\n", iter->word, iter->num);
            iter=iter->next;
        }
    }
       int main()
       {
            node *head=NULL;
    
    
        FILE* file= fopen("text.txt", "r");
        char word[500];
    
        for(int i = 0; fscanf(file, "%s", word) != EOF; i++)
        {
    
            head = add(head, word);
    
            printList(head);
    
    
        }
        printList(head);
    
    
    
    
        return 0;
    }
    
    #包括
    类型定义结构节点
    {
    字符*字;
    int-num;
    结构节点*下一步;
    }节点;
    node*addToHead(node*head,char-word[])
    {
    if(包含(头、字)==0)
    {
    node*tmp=(node*)malloc(sizeof(node));
    //tmp->word=(char)malloc((sizeof(char)*strlen(word)+sizeof(char));
    //tmp->word=word;
    tmp->word=(char*)malloc((sizeof(char)*strlen(word)+sizeof(char));
    strcpy(tmp->word,word);
    tmp->num=1;
    if(head==NULL)
    {
    tmp->next=NULL;
    水头=tmp;
    }
    }
    回流头;
    }
    节点*添加(节点*头,字符字[])
    {
    if(包含(头、字)==0)
    {
    节点*iter=头部;
    node*tmp=(node*)malloc(sizeof(node));
    //tmp->word=(char)malloc((sizeof(char)*strlen(word)+sizeof(char));
    //tmp->word=word;
    tmp->word=(char*)malloc((sizeof(char)*strlen(word)+sizeof(char));
    strcpy(tmp->word,word);
    tmp->num=1;
    if(head!=NULL)
    {
    while(iter->next!=NULL)
    iter=iter->next;
    iter->next=tmp;
    tmp->next=NULL;
    回流头;
    }
    else if(head==NULL)
    {
    head=addToHead(head,word);
    回流头;
    }
    }
    回流头;
    }
    int包含(节点*头,字符字[])
    {
    节点*iter=头部;
    while(iter!=NULL)
    {
    if(strcmp(iter->word,word)==0)
    {
    iter->num++;
    返回1;
    }
    iter=iter->next;
    }
    返回0;
    }
    无效打印列表(节点*头)
    {
    节点*iter=头部;
    while(iter!=NULL)
    {
    printf(“单词:%s | |单词数:%d\n”,iter->word,iter->num);
    iter=iter->next;
    }
    }
    int main()
    {
    node*head=NULL;
    FILE*FILE=fopen(“text.txt”、“r”);
    字符字[500];
    对于(int i=0;fscanf(文件“%s”,word)!=EOF;i++)
    {
    head=添加(head,word);
    印刷品清单(标题);
    }
    印刷品清单(标题);
    返回0;
    }
    
    Hm。您的问题在于分配字符串的位置。使用
    malloc
    分配内存,在下一条指令中,将保存分配内存的指针分配给
    word
    。这意味着(a)您不再有权访问分配的内存,这是内存泄漏;(b)所有数据都具有相同的数据,只要行缓冲区中写入的数据仍然“活动”。C是非常明确的,在为字符串长度和终止符分配足够的字节后,您应该
    strcpy
    将字符串放入该内存中。您可能听说过在C中,您不应该强制转换
    malloc
    的结果。C++需要演员,所以有些人还是这样做。但您肯定不想做的是将指针投射到
    char
    ——您将尝试将64位值存储在8位中,这会导致灾难。丢失该演员阵容,同时将
    sizeof(char)
    也替换为1。你会很好,有一个漂亮的,简短的
    malloc(strlen(word)+1)天哪,非常感谢。strcpy()解决了我的所有问题。禁止使用数组。那么,存储字符串会有问题。字符串只不过是一个
    字符的数组,其中最后一个
    字符的值为
    '\0'
    @AndrewHenle分配内存并在其中存储数据(形成字符串)并不真正构成数组。OTOH,
    printf(“单词数:%s | |单词数:%d\n”
    确实使用了数组。在任何情况下,“使用数组是禁止的。”是对强调错误想法的弱赋值的反映。
    #include<stdio.h>
    typedef struct node
    {
        char *word;
        int num;
        struct node *next;
    } node;
    
    node* addToHead(node *head, char word[])
    {
        if(Contains(head, word) == 0)
        {
            node *tmp = (node*)malloc(sizeof(node));
            //tmp->word = (char)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            //tmp->word = word;
            tmp->word = (char *)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            strcpy(tmp->word, word);
            tmp->num = 1;
    
            if(head == NULL)
            {
                tmp->next = NULL;
                head = tmp;
            }
        }
        return head;
    }
    node* add(node *head, char word[])
    {
        if(Contains(head, word) == 0)
        {
            node *iter = head;
            node *tmp = (node*)malloc(sizeof(node));
            //tmp->word = (char)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            //tmp->word = word;
            tmp->word = (char *)malloc((sizeof(char)* strlen(word) + sizeof(char)));
            strcpy(tmp->word, word);
            tmp->num = 1;
            if(head != NULL)
            {
                while(iter->next != NULL)
                    iter = iter->next;
    
                iter->next = tmp;
                tmp->next = NULL;
                return head;
    
            }
            else if(head == NULL)
            {
                head = addToHead(head, word);
                return head;
            }
    
        }
     return head;
    }
    int Contains(node *head, char word[])
    {
        node *iter = head;
        while(iter!= NULL)
        {
            if(strcmp(iter->word, word) == 0)
            {
                iter->num++;
                return 1;
            }
            iter = iter->next;
        }
        return 0;
    }
    void printList(node *head)
    {
        node *iter = head;
         while(iter!=NULL)
        {
            printf("word: %s || number of word: %d\n", iter->word, iter->num);
            iter=iter->next;
        }
    }
       int main()
       {
            node *head=NULL;
    
    
        FILE* file= fopen("text.txt", "r");
        char word[500];
    
        for(int i = 0; fscanf(file, "%s", word) != EOF; i++)
        {
    
            head = add(head, word);
    
            printList(head);
    
    
        }
        printList(head);
    
    
    
    
        return 0;
    }