【问题标题】:getchar() keeps reading a '\n'. What is going on?getchar() 一直读取 '\n'。到底是怎么回事?
【发布时间】:2015-10-09 04:53:41
【问题描述】:

我正在编写一个小程序来练习 C 编程。

我希望它使用 getchar();获取用户输入的功能。 我使用以下函数提示用户输入,然后循环使用 getchar() 将输入存储在数组中:

函数被传递一个引用结构成员的指针。

getInput(p->firstName); //The function is passed an argument like this one




void getInput(char * array)
{
    int c;

    while((c=getchar()) != '\n')
        *array++ = c;
    *array = '\0'; //Null terminate
}

此函数被多次调用,因为它是创建结构并填充其数组成员的函数的一部分。

但是,当程序执行时,前两次调用它工作正常,但任何后续调用此函数都会导致对 getchar() 的所有其他调用不等待键盘输入。

经过一些调试,我发现错误是 getchar();由于某种原因,读取 '\n' 字符而不是等待输入,while 循环测试失败,并且该函数基本上返回一个空字符串。

我已经做了一些研究,并一直在寻找使用

while(getchar() != '\n');

在函数结束时为了正确刷新标准输入,但是,这会产生不希望的结果,因为在我键入 ENTER 后程序将再次提示输入更多输入。再次按 ENTER 继续执行程序,但随后的所有调用都会立即读取这个神秘的 '\n' 字符,导致测试失败,并在需要打印内容时产生空字符串结构。

谁能向我解释这里发生了什么?为什么即使我应该清除输入缓冲区,getchar() 仍会继续获取 '\n'?我试过只放置一个 getchar();在函数的开头和结尾声明,尝试了“do while”循环,并对其进行了其他攻击,但我似乎无法弄清楚这一点。

【问题讨论】:

  • 您也应该始终检查 EOF:while ((c = getchar()) != EOF && c != '\n')(或者您可以先测试换行符,然后再测试 EOF)。这是否真的是你的麻烦的根源充其量是值得商榷的。
  • 您使用哪些其他函数来读取输入?请发布一个完整的程序来显示您的问题。
  • 我已经尝试了上面的代码行,但它仍然会产生相同的不良结果,尽管我最终计划相应地设计程序。婴儿步骤!
  • 等一下... Random832... 我想你刚刚解决了我的问题... 在调用我的getInput 后​​我有一个scanf() 函数!我会立即检查!
  • 是的!感谢@Random832 提出正确的问题!我在我拥有的 scanf 函数之后放置了一个 getchar while 循环并且它有效!虫子被压扁了!

标签: c arrays stdin prompt getchar


【解决方案1】:

您编写的代码有几个缺点。我将尝试解释它们,因为不清楚您的代码在哪里失败(可能在您发布的功能之外)

  • 首先,您不要在getchar() 结果值中检查EOFgetchar(3) 不会精确地返回 char 以允许返回所有可能的 char 值加上一个额外的 EOF 来标记文件的结尾(这可以通过输入 @987654327 从终端生成@ 在 unix 上,或 Ctrl-Z 在 Windows 机器上)这种情况必须在您的代码中明确考虑,因为您会将结果转换为 char 并且会丢失您从函数收到的额外信息。阅读 getchar(3) 手册页来解决这个问题。
  • 其次,您没有检查输入的字符是否足以填充所有数组并使其溢出。对于函数,您只传递一个指向数组开头的指针,但没有任何东西表明它延伸了多远,因此您可能会过度填充超出其边界的末尾,只是覆盖未保留用于输入目的的内存。这通常会导致称为 U.B.在文献中(Undefined Behaviour)并且是您必须关心的事情。这可以通过传递一个有效位置的计数器来填充数组并为每个填充的有效位置递减它来解决。并且在缓冲区填满后不允许更多输入。

另一方面,您有一个标准函数可以做到这一点,fgets(3) 只是从输入文件中读取一个字符串数组,并将其存储在您传递给它的指针(和大小)上:

char *fgets(char *buffer, size_t buffer_size, FILE *file_descriptor);

你可以像这样使用它:

char buffer[80], *line;
...
while (line = fgets(buffer, sizeof buffer, stdin)) {
    /* process one full line of input, with the final \n included */
    ....
}

/* on EOF, fgets(3) returns NULL, so we shall be here after reading the
 * full input file */

【讨论】:

    猜你喜欢
    • 2010-12-25
    • 2019-12-19
    • 2022-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    相关资源
    最近更新 更多