【问题标题】:Retrieve value from linked list struct give wrong value从链表结构中检索值给出错误值
【发布时间】:2013-07-15 03:44:51
【问题描述】:

我有一个创建结构链表的函数。

struct words {
    char * word;
    words next;
};
typedef struct words s_words;
typedef words * Words;

我有一个函数可以使用此代码创建我的链表

Words w = NULL; // start of the list
Words t; // temp node

if (t = (Words) malloc(sizeof(s_words))) {

    t->word = a_string_created;
    t->next = w;
    w = t; // Adding at start of the list
}

如果我创建了 printf("%s",t->word)printf("%s",a_string_created),我得到了相同的值。

我的问题是当我尝试从另一个函数中检索 word 时。

int readWords(Words list, char * wordRead) {

    if (list != NULL) {
        //strcpy(wordRead,list->word);
        wordRead = list->word;
        return 1;
    }
    else {
        return 0;
    }   
}

我无法获得readWords 中的值。其中的printf("%s",list->word) 给了我一个奇怪的字符。并来自调用者函数

char rw[11]; //I've try char* rw too
readWords(aList,rw);

printf("%s",rw) 不打印任何内容。

我已经坚持了好几个小时了。肯定有一些我看不到/不理解的东西。

编辑:

我通过用strcpy(t->word, a_string_created); 替换t->word = a_string_created; 部分解决了我的问题现在在我的printfs 上,我打印字符串值。但是对于某些值,该值略有变化,例如:test 变为 uest !!

回答

t->word = a_string_created; 更改为t->word = strdup(a_string_created);

任何人都可以帮助并向我解释我在哪里以及为什么错了?

【问题讨论】:

  • 顺便说一句:你为​​什么不使用函数的返回值返回值,而不是愚蠢的1或0?
  • 这是学校作业,我无法更改 readWords 的签名。
  • 也许可以和你的老师讨论。在我看来,这显然是错误的。返回 NULL 似乎是 not found ) 的一个很好的指示

标签: c linked-list


【解决方案1】:

问题的发生是因为您的readWords 滥用了缓冲区:readWords 没有将字符串从列表复制到其中,而是将其分配为指针。由于rw 是按值传递的,因此缓冲区的内容保持未初始化,由于未定义的行为导致打印输出无效。

有几种方法可以解决这个问题:

  • 使用strcpylist->words 的内容复制到wordRead 缓冲区中,或者
  • 更改readWords 以获取指向wordRead 的指针,并将其分配给list->words

strcpy 方法不太安全,除非您也考虑缓冲区的大小。指向指针方法的指针如下所示:

int readWords(Words list, char **wordRead) {
    if (list != NULL) {
        *wordRead = list->word;
        return 1;
    } else {
        return 0;
    }
}

调用如下所示:

char *rw;
if (readWords(aList, &rw)) {
    printf("%s", rw)
}

【讨论】:

  • 这是学校作业,我无法更改 readWords 的签名。但我可以从“调用者函数”中改变一切。
  • @PatrickPellegrino 然后使用strcpy - 您已经沿着正确的轨道开始,但随后您注释掉了正确的呼叫。如果您使用strcpy,则必须执行分配。
  • 我必须评论它,因为我收到一个分段错误,认为这是我的问题。也许我的问题出在我的列表中,而 readWords 中的 printf("%s",list->word) 输出错误。
  • @PatrickPellegrino 当单词超过 10 个字符(计算空终止符时为 11 个字符)时,您可能会遇到段错误。另一种可能是列表元素可能是freed,或者列表元素内部的指针指向了无效的内存位置。
  • @PatrickPellegrino 那是因为您在复制之前没有为t->word 分配空间。指针指向内存中的随机位置,导致随机覆盖。您需要调用strdup(即t->word = strdup(a_string_created); 或将word 的声明从char *word 更改为char word[11]
【解决方案2】:

您正在为 struct 分配内存,但未能为您的字符串分配内存。

不仅如此,您的函数还尝试将char * 变量wordRead 设置为存储字符串的开头。但它永远不会在函数之外返回这个值——这似乎是函数的意图。你的第二个函数应该是:


int readWords(Words list, char **wordRead) {
    if (list != NULL) {
        *wordRead = list->word;
        return 1;
    } else {
        return 0;
    }   
}

【讨论】:

  • 这是学校作业,我无法更改 readWords 的签名。但我可以从“调用者函数”中改变一切。
【解决方案3】:

问题是您需要为 wordRead 传递一个双指针。你这样做的方式,你只是修改一个本地值。

所以正确的原型是int readWords(Words list, char ** wordRead)

【讨论】:

  • 这是学校作业,我无法更改 readWords 的签名。但我可以从“调用者函数”中改变一切。
  • @PatrickPellegrino 在这种情况下,您必须由调用者提供内存并将值复制到传递给 readWords 的缓冲区。 - 顺便说一句:如果调用者传递这样一个缓冲区,最好将缓冲区的大小与指针一起传递以避免溢出。
【解决方案4】:

在您的struct 中,您需要为char* 分配。如果没有为您的 char 数据分配空间,则您的指针已经指向垃圾。

其次,strcpy 并不总是安全的,除非您明确检查您尝试复制的数据的大小并确保您的字符串最后有一个 '\0'strncpystrcpy 更安全。

【讨论】:

  • 顺便说一句:strncpy() is **not** safer than strcpy()`。它只有不同的问题。 (例如不以 null 结尾的结果字符串(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多