【问题标题】:Testing getchar() == EOF doesn't work as expected测试 getchar() == EOF 没有按预期工作
【发布时间】:2012-10-22 05:04:22
【问题描述】:

我有一个任务是“编写一个允许用户输入最多 20 个整数的 C 程序(它将停止接受基于标记值或达到 20 个整数限制的数字)。然后程序应该以相反的输入顺序显示数字。”

我决定将我的标记值设为“EOF”(或 CTRL+D / CRTL+Z)。我的代码有一些非常不稳定的行为:

  1. 您必须按 EOF 键两次(这也会创建一个空白条目,该条目会被计入数组。
  2. 第一个条目的第一个数字被截断。

其他一切似乎都可以正常工作,但这显然不是预期的结果。下面是我的代码。你能解释一下有什么问题吗?

main() {
int i,iMax;
double dblMean;
int x[MAX];

printf("Please Enter Up to 20 Integers\n");

for (i=0; i<MAX; i++)
{
    printf("%d.> ",i+1);
    if (getchar() == EOF)           /* Check for CTRL+D OR CTRL+Z */
    break;                          /* Exit loop if EOF entered :: Must be pressed twice and eats first character of first entry */
    scanf("%d",&x[i]);
    iMax=i;
}

printf("\nYou entered  %d numbers\n",iMax+1);               /* Should be i+1 but EOF had to be entered twice */
printf("\nIndex       Item        Reverse Item\n");
for (i=0; i<=iMax; i++)
    printf("%3d%4c%8d%9c%11d\n",i,'  ',x[i],'  ',x[iMax-i]);
return 0;

}

编辑: 这是我的最终代码,谢谢大家的帮助:

#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int main()
{
    int i,iMax;
    int x[MAX];

    printf("Please Enter Up to 20 Integers\n");

    for (i=0; i<MAX; i++)
    {
        printf("%d.> ",i+1);
        if (scanf("%d",&x[i]) != 1)                         /* Checks for CTRL+D OR CTRL+Z */
        break;                                              /* EOF returns -1 and loop will be exited */
        iMax=i;                                             /* iMax must be set for second loop to exit properly */
                                                            /* Can sizeof x be used instead for second loop? */
    }

    printf("\nYou entered  %d numbers\n",iMax+1);           /* Displays number of items entered... Will be <= MAX*/
    printf("\nIndex       Item        Reverse Item\n");
    for (i=0; i<=iMax; i++)                                 /* Why wont 'for (i=0; i<=sizeof x; i++)' work? */
        printf("%3d%4c%8d%9c%11d\n",i,'  ',x[i],'  ',x[iMax-i]);
    return 0;
}

【问题讨论】:

    标签: c arrays eof getchar


    【解决方案1】:

    getchar() 调用读取(并有效地丢弃)第一个数字,因为它不是 EOF。

    您没有测试scanf() 是否有效;你应该。

    for (i = 0; i < MAX; i++)
    {
        if (scanf("%d", &x[i]) != 1)
            break;
    }
    

    此时,数组中有i个整数;你真的不需要在循环中设置iMax。您可以在循环退出时简单地设置它。

    【讨论】:

    • 这对我来说非常有效!!另外仅供参考,我需要设置 iMax,因为我需要知道第二个循环的条目停止位置的索引。如果我知道如何让 sizeof 为我工作,我可以将 iMax 排除在外!
    • 你可以简单地在循环之后使用iMax = i;(我注意到,我省略了提示printf())。在某一时刻,我认为你完全可以不用iMax,但我意识到打印循环实际上确实需要它,因为它是编写的。不过,那个版本的答案只显示了大约 10 分钟。
    【解决方案2】:

    另外,除了检查scanf,你还需要知道以下几点:-

    EOF 不是字符。 EOF 是 getchar() 在到达输入末尾或遇到某种错误时返回的宏。 ^D 不是“EOF 字符”。当您在一行上单独点击 ^D 时,在 linux 下发生的事情是它关闭了流,并且 getchar() 调用到达输入的末尾并返回 EOF 宏。如果您在一行中间的某处键入 ^D,则流不会关闭,因此 getchar() 返回它读取的值并且您的循环不会退出。

    请参阅http://www.c-faq.com/stdio/getcharc.html 以获得很好的描述。

    【讨论】:

    • 你说得对,EOF 不是字符,也不是 ^D。当您在终端键入 ^D 时,它会将所有可用字符发送到读取过程。如果没有可用字符,read() 返回 0 个可用字节,并且“可用零字节”通常被视为 EOF(如果您正在读取普通文件,当您读取每个文件中的字节)。它关闭流;它可能会在流状态上设置 EOF 位(您可以使用 clearerr() 清除它)但它不会正式关闭流。
    猜你喜欢
    • 1970-01-01
    • 2016-08-27
    • 2014-11-22
    • 1970-01-01
    • 2013-07-05
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    相关资源
    最近更新 更多