【问题标题】:It seems I must first press enter before getchar() gets EOF看来我必须在 getchar() 获取 EOF 之前先按 Enter
【发布时间】:2014-09-27 09:48:09
【问题描述】:

我开始学习 EOF 并编写了以下简单程序:

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

void main()
{    
    int i=0;
    while(getchar()!=EOF)
    {
        i++;    
    }       
    printf("number of characters : %d \n",i);       
}

问题是,当我写一个字符串时,按回车,然后按Ctrl+Z,输出是我写的字符数加 1(对于EOF)。但是,如果我写一个字符串并且不换行,按Ctrl+Z,while 循环不会终止。这是为什么呢?

【问题讨论】:

  • 添加了 Windows,因为我从您使用 Ctrl+Z 获取 EOF 那是您的平台。顺便说一句,main 应该返回 int,而不是 void,如果您关心可移植代码。
  • @larsmans 首先我想我必须知道它是如何工作的,然后我会开始担心可移植代码..!
  • 是的 paxdiablo 说,如果我按任意位置 Ctrl+Z 和换行符,我会完成我的工作,但我已经完成了,程序继续,“while”不会停止。跨度>

标签: c windows eof


【解决方案1】:

首先,EOF 仅在 Ctrl + Z 位于行首时才会发出信号。考虑到这一点:

在您第一次尝试使用your input (10 个字符) 然后Enter 时,您实际上将your input\n 推送到输入流,它会逐个字符地读取通过getchar,现在有 11 个字符,由于您的 Enter,在末尾添加了新行。

在新行上,然后您使用 Ctrl + Z 组合来发出EOF 的信号,并且您确实在那里正确地执行了该操作;给EOF发信号,结果是11。

奇怪的是,您期望在这里看到 10。如果您要输入多行怎么办?您希望它不计入新行吗?然后你可以使用类似的东西:

int onechar;
while ((onechar = getchar( )) != EOF)
{
    if (onechar != '\n')
        i++;
}

或者更进一步,您是否总是期待单行输入?那么您可能需要考虑将循环条件更改为以下内容:

while(getchar( ) != '\n')
{
    i++;
}

哦,你希望它能够获得多行输入,以及计算\n 字符,最重要的是,只希望它能够在 处停止Ctrl + Z 组合不一定在行首?那么,这里有这个:

// 26 is the ASCII value of the Substitute character
for (int onechar = getchar( ); onechar != EOF && onechar != 26; onechar = getchar( ))
{
    i++;
}

26,正如所评论的那样,是Substitute character,至少在我的机器上,这是当我不恰当地使用 Ctrl + Z 时程序得到的。使用这个,如果你要输入:

// loop terminated by the result of (onechar != 26) comparison
your input^Z

如果您要输入,您将得到 10 作为结果:

// loop terminated by the result of (onechar != EOF) comparison
your input
^Z

您将得到 11 个,将您输入的换行符连同之前的所有其他 10 个字符一起计算在内。此处,^Z 已用于将 Ctrl + Z 组合键显示为输入。

【讨论】:

    【解决方案2】:

    输入使用缓冲区。第一个 getchar 请求系统级读取。当您按 enter 或 ctrl-z 时,读取会将缓冲区返回给程序。当您按下回车键时,系统还会在返回缓冲区之前向缓冲区添加一个换行符。 Eof 不是实际字符,而是读取空缓冲区的结果。

    控制权返回给程序后,getchar 顺序读取返回缓冲区中的每个字符,完成后请求再次读取。

    在第一种情况下,getchar 读取包含换行符的缓冲区。然后由于缓冲区为空,getchar 请求另一个读取,该读取通过按 ctrl-z 中断,返回一个空缓冲区并导致 EOF。

    在第二种情况下,按 ctrl-z 只会返回缓冲区,并且在 getchar 完成读取它后,它会请求另一个尚未完成的读取,因为您从未按 ctrl-z 或再次输入。

    永远不会结束的不是你的 while 循环,而仅仅是 read 调用。在第二种情况下尝试按 ctrl-z 两次。

    【讨论】:

      【解决方案3】:

      我在这里看到了与此相关的主题。您需要做的是将 pts/tty 设置为非规范模式并使用某种 TCSANOW 进行操作(立即更改 attr)。 您可以使用 termios.h 中的函数,在 struct termios 上运行;

      【讨论】:

        猜你喜欢
        • 2015-06-30
        • 2013-09-21
        • 2013-06-10
        • 2021-07-12
        • 1970-01-01
        • 1970-01-01
        • 2020-12-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多