结构中的scanf char * word仅显示最后一个输入

时间:2011-12-19 01:56:27

标签: c struct char scanf

我只允许使用以下标题

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

我将struct student定义如下:

struct dict
{
    char* word;
    struct dict* link;
};

有很多功能,但现在只有一个我有问题的功能。 此函数在链接的末尾插入具有特定名称的结构字典。

struct student *Linsert(struct dict *list, char *name)
{
    struct student *pnew;
    struct student *pn;
    int exist = 1;

    pnew = (struct dict *)malloc(sizeof(struct dict));
    pnew -> next = NULL;
    pnew -> name = name;

    if (list != NULL)
    {
        for (pn = list; pn -> next != NULL; pn = pn -> next) ;
        pn -> next = pnew;
    }
    else
        list = pnew;

    return list;
}

使用以下功能

//print all the values in the list
void printList(struct dict* list);

我这样做了:

int main(void)
{

    struct dict *list = NULL;

    char *name;

    while (1) {
        scanf("%s", name);
        if (name == 'Q')
            break;

        list = Linsert(list, name);
        printList(list);
    }
    return 0;
}

让我们说输入,我输了三个 apple bananaorange,我的结果显示了我上次输入的三个内容。

这里有什么问题?

5 个答案:

答案 0 :(得分:3)

我发现您的代码有两个问题:

  • 您需要传递scanf一个大小足以存储输入字符串的char数组,而不仅仅是一个字符指针。
  • 您需要复制传递到Linsert的字符串(使用strdup)。

答案 1 :(得分:2)

单独的main代码段存在一大堆问题:

  • name是一个未初始化的指针;它指向内存中未分配且允许使用的某个未知位置,因此导致未定义的行为。也许您希望char name[20]在堆栈上分配20 char的数组,并让scanf将输入存储在此缓冲区中。

  • 您正在将char*(指向字符串开头的指针)与单个char 'Q'进行比较 - 您正在比较指针和整数值正如您的编译器警告会告诉您的那样。您没有比较值'Q'的字符串内容,而是比较name的内存地址和'Q'的整数值。如果要将字符串name与字符串"Q"进行比较,请使用strcmp并检查返回值是否为0。

你也希望复制传递给Linsert的变量,否则,你已经注意到,你每次都会将指针传递给内存中的同一个位置,并对此进行更改内存块将改变你的每个项目。

如果你打开编译器警告,你会收到更多警告。

答案 2 :(得分:1)

您没有为名称分配任何内存,因此scanf正在写入某个随机位置,并在每次循环时覆盖它。

答案 3 :(得分:1)

一个问题是您没有为word成员分配存储空间来指向。您还没有为name指定空间。这是麻烦的主要原因。

您需要为name分配空间;最简单的方法是:

char name[128];

您需要分配空间来存储单词,并且需要将name的内容复制到word中,这样当下一行覆盖name时,它不会破坏已保存的word

调整代码,您可以使用:

struct student *Linsert(struct dict *list, char *name)
{
    struct student *pnew;
    struct student *pn;

    pnew = (struct dict *)malloc(sizeof(struct dict));
    if (pnew == 0)
        ...error...
    pnew->next = NULL;
    pnew->word = malloc(strlen(name) + 1);
    if (pnew->word == 0)
        ...error...
    strcpy(pnew->word, name);

    if (list != NULL)
    {
        for (pn = list; pn->next != NULL; pn = pn->next)
            ;
        pn->next = pnew;
    }
    else
        list = pnew;

    return list;
}

不要忽略内存分配的错误检查 - 尽管很痛苦。当你忘记时它会咬你。

从风格上讲,不要在->.周围使用空格;它们是非常紧密绑定的运算符,它们不应像其他二元运算符那样间隔开。

有一个方便的函数,strdup(),重复一个字符串,但它不是标准的C(它是标准的POSIX)。

答案 4 :(得分:0)

由于name是一个char指针,因此对每个dict结构字段的赋值将使用它指向的最新值。