【问题标题】:string input in linked list [C]链表中的字符串输入 [C]
【发布时间】:2016-06-10 21:20:45
【问题描述】:

我只是在学习链表。我为自己编写了一个小程序来练习有关链表的机制。这是我第一次尝试做一个小的 pokedex(实际上没有保存任何东西)。所以我正在尝试正确设置输入。目前一切正常,没有错误,我可以执行它。

问题是第二次输入pokemon名字时没有读入任何数据,而是跳过读入直接进入scanf函数,为什么会这样?

void addPokemon(void){

    pokemonPtr firstPtr;
    pokemonPtr thisPokemon;
    firstPtr = NULL;

    firstPtr =(pokemon *) malloc(sizeof(pokemon));
    firstPtr->name = malloc(sizeof(char) * POKEMON_LENGTH);

    printf ("Enter the name of the Pokemon.\n");
    fgets(firstPtr->name, POKEMON_LENGTH, stdin);

问题就在这里,这个fgets并没有真正被执行,所以基本不会提示用户输入字符串。

    printf ("Enter the number of the Pokemon.\n");
    scanf("%d",&firstPtr->number);

    firstPtr->next =(pokemon *) malloc(sizeof(pokemon));

    thisPokemon = firstPtr->next;

    int i = 0;

    while (i < 10){

        thisPokemon->name = malloc(sizeof(char) * POKEMON_LENGTH);

        printf ("Enter the name of the Pokemon.\n");
        fgets(thisPokemon->name, POKEMON_LENGTH, stdin);
        printf ("Enter the number of the Pokemon.\n");
        scanf("%d",&thisPokemon->number);

        thisPokemon->next =(pokemon *) malloc (sizeof(pokemon));
        thisPokemon = thisPokemon->next;

        i++;

    }

【问题讨论】:

  • scanf("%d",&amp;firstPtr-&gt;number);之后写入getchar();(用于消耗换行符)
  • 我不太确定这是否真的有帮助,因为它会提示我输入一些内容,但问题仍然存在。我将在问题所在的主要帖子中进行编辑。
  • 尝试使用scanf("%d%*c", &amp;firstPtr-&gt;number); 而不是scanf("%d",&amp;firstPtr-&gt;number);
  • 所有神奇宝贝的POKEMON_LENGTH 都固定了吗?
  • 好吧,我想引入一个字符串限制,因为我读了很多,出于安全原因这样做是好的。所以我将 POKEMON_LENGTH 定义为只有一些字符长(我认为可能是 15 个)

标签: c string list input fgets


【解决方案1】:

fgets 在读取换行符时停止读取。在您的示例中, stdin 中已经有一个 '\n' ,因此 fgets 接受它并完成了。这是因为 scanf 不会读取您输入数字时获得的换行符,而是将其留在标准输入中。

两种解决方案:

使用 scanf("%s", name); 代替 fgets。这是有效的,因为%s 将忽略它所采用的字符串之前的空格和换行符。

用户 getchar() 读取换行符。

【讨论】:

  • 太棒了!好吧,我以前使用过 scanf ,但不知何故,考虑到字符串,我总是收到警告。好的,我想我需要在结构中使用 char *name 这确实有效。但我不明白 getchar() 的事情
  • 注意,scanf 只适用于 1 个单词的口袋妖怪名称...但所有口袋妖怪的名字都是一个单词,我 99% 确定
  • 你在那里有一些很好的口袋妖怪知识 :) 我需要改变什么才能使两个或多个单词成为可能?
  • 要解释多个单词,请使用scanf("%[^\n]s",stringname)
  • @CherubimAnand 使用scanf("%[^\n]%*c", stringname) 代替。或scanf(" %[^\n]%*c", stringname)
【解决方案2】:

您的代码有很多问题,扫描语句正在扫描从以前的扫描语句返回的 \n 字符...您可以通过多种方式避免它,但所有这些方式最终都会消耗 \n 字符

一些方法是:

  • scanf(" ");这个空间消耗了\n字符

  • getch();类似

    我在下面的代码中使用了第一个。


注意:始终确保输入下面指定POKEMON_LENGTH 的口袋妖怪的name。如果不是,它将被下一个扫描语句接收。

如果 #define POKEMON_LENGTH 15 那么,请始终输入口袋妖怪名称 14 或更少的字符,因为第 15 个空格代表 \0,任何高于此的内容都会引发未定义的行为...


我已经对你的 addPokemon() 函数进行了更改:(我已经在 cmets 中解释过)

void addPokemon(void)
{

    pokemonPtr firstPtr;
    pokemonPtr thisPokemon;
    firstPtr = NULL;

    firstPtr =(pokemon *) malloc(sizeof(pokemon));
    firstPtr->name = malloc(sizeof(char) * POKEMON_LENGTH);

    printf ("Enter the name of the Pokemon.\n");
    fgets(firstPtr->name, POKEMON_LENGTH, stdin);

    printf ("Enter the number of the Pokemon.\n");
    scanf(" %d",&firstPtr->number);  //give a space to consume \n

    firstPtr->next =(pokemon *) malloc(sizeof(pokemon));

    thisPokemon = firstPtr->next;

    int i = 0;

    while (i < 10)
    {

        thisPokemon->name = malloc(sizeof(char) * POKEMON_LENGTH);

        printf ("Enter the name of the Pokemon.\n");
        scanf(" ");//consume white spaces or \n
        fgets(thisPokemon->name, POKEMON_LENGTH, stdin);
        printf ("Enter the number of the Pokemon.\n");
        scanf(" %d",&thisPokemon->number);

        thisPokemon->next =(pokemon *) malloc (sizeof(pokemon));
        thisPokemon = thisPokemon->next;

        i++;

        }
    }
}

最后,

为什么要给空间?

通过给出一个空格,编译器会使用之前的scanf() 中的'\n' 字符或任何其他空格('\0''\t'' '

【讨论】:

  • @ThomasChristopherDavies 我希望这能解决你的问题......我已经运行了代码,它按预期工作
  • 哦,太好了,谢谢您的额外输入。现在上面的 scanf 解决方案现在可以解决问题。一旦我开始尝试将信息保存到文件中,我就需要重新使用“fgets”。你能推荐任何关于“消费空白”的文献吗?我的意思是我完全开始明白你们的意思了,但我真的不明白这个规则的因果关系。我希望我能给你们两个支票,或者至少“答案很有用”(我还没有足够的声誉)。干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 2019-05-04
  • 2021-05-25
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
相关资源
最近更新 更多