链接的字符串列表对于每个节点具有相同的字符串

问题描述 投票:0回答:3

我正在尝试创建一个链表,每个节点都存储一个字符串,但我遇到的问题是每个节点最终在每个节点中存储相同的字符串。在main()的末尾,我打印出存储在每个节点中的单词,它总是只重复为整个列表输入的最后一个字符串。

我不知道发生了什么,因为如果我把它变成一串字符就可以很好地工作,每个字符都存储在正确的节点中。

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

struct wordnode {
    char *word;
    struct wordnode *next;
};

struct wordnode *link = NULL;

void addword(char *aword);

int main(void) {


    char *aword;
    int i;

    for(i = 0; i < 10; i++) {
        scanf(" %s", aword);
        addword(aword);
    }
    printf("\n");
    for(; link != NULL; link = link->next) {
        printf("|%s ", link->word);
    }

    printf("|\n");
    return 0;
}

void addword(char *aword) {
    struct wordnode *cur, *prev, *new_node;

    new_node = malloc(sizeof(struct wordnode));

    new_node->word = aword;

    for(cur = link, prev = NULL; cur != NULL; prev = cur, cur = cur->next) {
        ;
    }

    new_node->next = cur;

    if(prev == NULL) {
        link = new_node;
    } else {
        prev->next = new_node;
    }
}
c string linked-list
3个回答
1
投票

代码中存在许多问题。其中一些已被提及。代码将是这样的。代码末尾的解释。

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

#define STR2(x) #x
#define STR(X) STR2(X)
#define MAXWORD 10
#define MAXWORDLEN 20

struct wordnode {
    char *word;
    struct wordnode *next;
};


struct wordnode* addword(char *aword, struct wordnode *link);
void printList(struct wordnode*link);
void freeList(struct wordnode *link);

int main(void) {
    char aword[MAXWORDLEN+1];

    struct wordnode *link = NULL;
    for(size_t i = 0; i < MAXWORD; i++) {
        if( scanf("%" STR(MAXWORDLEN) "s", aword[i]) == 1 ){
           link = addword(aword, link);
        }
        else{
            fprintf(stderr, "%s\n","Error in input" );
            exit(1);
        }
    }

    printList(link);  

    freeList(link);
    return 0;
}
void printList(struct wordnode*link){
    while(link){
        printf("%s \n", link->word);
        link  = link->next;
    }
}
void freeList(struct wordnode *link){
    struct wordnode *temp;
    while(link){
        temp = link;
        link = link->next;
        free(temp);
    }
}

struct wordnode* addword(char *aword, struct wordnode *link) {

    struct wordnode *new_node = malloc(sizeof(struct wordnode));

    if( new_node == NULL){
        fprintf(stderr, "%s\n", "Error in malloc");
        exit(1);
    }
    new_node->word = strdup( aword );
    if( new_node->word == NULL){
        fprintf(stderr, "%s\n", "Error in strdup" );
        exit(1);
    }
    new_node->next = NULL;

    if( link == NULL){
        return new_node;
    }
    struct wordnode *cur = link;
    while( cur->next != NULL ){
        cur = cur -> next;
    }
    cur->next = new_node;
    return link;
}

您想存储一些字符串(空终止的char数组),然后您想在列表中添加它们。同样从您的示例实现中,您尝试将其添加到尾部的列表中。

总结一下 -

  • scanf需要一个指向某个存储器的指针,它可以存储输入的数据。但你的未初始化。
  • 其次,你复制字符串的方式,它只是一个浅的副本(你让它指向一些已经存在的内存)。你需要使用strdupmalloc - memcpymalloc-strcpy复制它。
  • 如果POSIX strdup()不可用,您可以使用Jonathan Leffler提到的内容。
  • 在这里你可以看到我们已经使用freeList()函数释放了已分配的内存。当您完成使用已分配的内存时 - 释放内存。
  • 不要强制转换malloc的返回值。
  • 还要检查malloc是否成功检查它的返回值。
  • 您已将列表头用作全局变量。这里不需要它。

0
投票

char * aword未初始化和定位。它应该是:

char aword[100];

(100只是一个数字,大小的数组。你可以用你想要的任何数字替换它)


0
投票

您尚未为字符串分配内存。因此,aword将包含垃圾值并将其传递给scanf是一种未定义的行为。让我们说aword0x7fffe4e0cdf0和你的scanf将字符串存储在地址0x7fffe4e0cdf0并将此地址传递给addword函数,你的结构成员word也更新了相同的值。下一个scanf还将新值存储在aword指向的相同内存中并传递给该函数。因此,所有链表中的word指向相同的内存位置。理想的解决方案是为每个被扫描的字符串分配内存,并将其传递给“addword”函数。

© www.soinside.com 2019 - 2024. All rights reserved.