当 ((c = getchar()) != EOF) 时,不会终止

5
我一直在阅读《C程序设计语言》这本书,看到了有关输入和输出的部分。
我看到其他帖子中提到控制台无法将回车识别为EOF,因此我应该在Windows中使用CTRL + Z,在Unix中使用CTRL + D(这两个都对我不起作用)。
我还看到其他人也问过同样的问题,他们可以使其工作,但问题在于代码语法而非程序未终止。
是否有其他解决方案?
以下是代码:
#include <stdio.h>

main()
{
    int nb, nl, nt, c;
    nb = 0;
    nl = 0;
    nt = 0;
    while ((c = getchar()) != '\n') {
        if (c == ' ')
            ++nb;
        else if (c == '\n')
            ++nl;
        else if (c == '\t')
            ++nt;
    }
    printf("Input has %d blanks, %d tabs, and %d newlines\n", nb, nt, nl);
}

编辑:本来 \n 应该是一个 EOF,我在发布之前进行了一些操作,然后忘记更改它了 :P
它也不适用于 EOF,我只是跳过了那个。

2
在 while 循环条件 (c = getchar()) != '\n') 中,\n 应该被替换为 EOF - Grijesh Chauhan
2
我在你的代码中没有看到 != EOF - user93353
你的上面的代码将接受 '\n' 作为终止条件。 - phuclv
2
请编辑您的问题,以便我们可以看到您正在运行的实际代码,这显然是指EOF。复制并粘贴源代码;不要重新输入它。 while ((c = getchar())!= EOF) 应该能够正常工作。您是在Windows还是Unix / Linux上?在您运行程序时,请在问题中(而不是在回复此评论中)描述您正在输入的确切内容。 - Keith Thompson
1
我使用 putty 连接到 Ubuntu,对我来说按下 CTRL+DD 会发送 EOF 条件。 - Daan
请注意,在UNIX中,EOF不是一个字符,而是一个条件触发器,当输入驱动程序看到由stty eof设置的eof字符时触发。该字符默认为^D,可以通过stty -all显示为eof = ^D; - U. Windl
9个回答

5
while ((c = getchar())  !=EOF) {


}

然后在Windows上使用Ctrl+ZF6

以下代码将等待首先到达的\nEOF

while((c = getchar()) != '\n' && c != EOF){

}

3
不应将\n作为停止条件,因为OP的目的是计算遇到的\n字符的数量。 - Eric Z

4
while ((c = getchar()) != '\n'){
    if (c == ' ')
        ++nb;
    else if (c == '\n')
        ++nl;
    else if (c == '\t')
        ++nt;
} 

根据你的while循环条件,你将无法计算换行符的数量,因为当用户输入换行符('\n')时,你将停止while循环。

除此之外,计算空格和制表符可以正常工作。

在Windows中,CTRL+Z将被识别为EOF。但是为了在程序中识别它,请在while循环中使用条件((c = getchar()) != EOF)。现在,当用户按下键组合:CTRL+Z时,它将作为EOF输入到控制台,并且程序应该将其识别为字符输入。

这样做将允许你计算输入中的行数。

因此,我的建议是:

while ((c = getchar()) != EOF){
    if (c == ' ')
        ++nb;
    else if (c == '\n')
        ++nl;
    else if (c == '\t')
        ++nt;
} 

4
如果您使用的是Unix系统,手动输入程序时模拟 EOF 的唯一方法是按下 CTRL+D。以下是一些向程序输入数据并在输入结束时发送 EOF 信号的方法:
- 使用here string格式提供文件的字符串表示形式。
./myprog <<< "Here is a string to work with"
  • 或者,你也可以使用输入重定向将包含输入的文件提供给程序。
./myprog < input.file

任何上述列出的方法都可以与以下代码配合使用:
#include <stdio.h>
#ifndef EOF
#define EOF (-1)
#endif
int main(void)
{
    int nb, nl, nt, c;
    nb = 0;
    nl = 0;
    nt = 0;
    while ((c = getchar()) != EOF){
        if (c == ' ')
            ++nb;
        else if (c == '\n')
            ++nl;
        else if (c == '\t')
            ++nt;
    }
    printf("Input has %d blanks, %d tabs, and %d newlines\n", nb, nt, nl);
    return 0;
}
  • 不要忽略Windows操作系统。在Windows上模拟键盘的EOF,请使用CTRL+Z组合键。

不确定Unix中的here-string格式是否适用于Windows,但输入重定向应该类似。


3
不,文件并不总是在末尾有一个“EOF字符”。Windows文本文件 有时候 会有,但Unix文本文件没有。文件结束是一种条件,而不是字符,“EOF”是getchar()返回的特殊值,表示文件结束或错误条件。Control-D或Control-Z并不是“模拟EOF”;它们触发文件结束条件,导致getchar()EOF作为其结果返回。(这就是为什么getchar()返回int而不是char的原因。) - Keith Thompson
@Keith Thompson 很好知道 - smac89

4
在Windows系统中,您需要在单独的一行上(没有空格或其他内容)键入Ctrl-Z,然后再键入Return。在Windows系统中,您可以技术上跳过EOF指示器并继续读取字符,但这不适用于其他操作系统,因为EOF实际上意味着EOF。

1
    /* This program will calculate the number of blanks, tabs and new line in a text stream */

#include <stdio.h>

main () 
{
    int c,nl = 0, blank = 0, tab = 0; //Newline, blanks and tabs.
    while ((c = getchar()) != EOF) {
        if (c == '\n')
            ++nl;
        else if (c == '\t')
            ++tab;
        else if (c == ' ')
            ++blank;
}
    printf("Tabs = %d\nBlanks = %d\nNewLine = %d",tab, blank, nl);
}

我编写了下面的代码,并在Ubuntu上成功运行。由于它与你编写的代码相似,我尝试了这段代码,在UNIX中Ctrl-D正常工作。

我测试了下面的代码,并意识到如果我们在文本流中输入\n,它不会增加换行符的计数器,\t也是一样的。只有按回车键换行和按Tab键制表符才会被计入计数器,这点需要注意。

这是因为按回车键实际上会放置一个换行符,它是一个单一的字符,而输入\n则会被视为不同的两个字符。

我认为这将为这个问题添加价值,所以我也解释了这个问题。谢谢。


0

更改这行

// Buggy, you want calculate the # of '\n' in loop body,
// so logically you shouldn't use it as a stop condition.
while ((c = getchar()) != '\n')

while ((c = getchar()) != EOF)

尝试在Windows上的控制台窗口中按下Ctrl + C。这在我的运行Win7的平台上有效。

enter image description here


1
使用Ctrl-C是解决这个问题的简单方法,而不是回答问题的答案。 - alk

0
首先按下 Ctrl + Z,这将打印出^Z,然后按下 Enter 键以到达 EOF。

-1
我曾遇到过同样的问题,所以我通过调试代码来检查ctrl+D的值,并发现其值为255。于是我将EOF替换为了255,这对我有效。如果这种方法对你无效,那就尝试找出Unix中ctrl+D的值。
#include <stdio.h>

main()
{
    int nb, nl, nt, c;
    nb = 0;
    nl = 0;
    nt = 0;
    while ((c = getchar()) != 255) {
        if (c == ' ')
            ++nb;
        else if (c == '\n')
            **++nl;**
        else if (c == '\t')
            ++nt;
    }
    printf("Input has %d blanks, %d tabs, and %d newlines\n", nb, nt, nl);
}

EOF 通常被定义为 (-1)。在您的代码中,如果将 c 定义为 unsigned char 或者如果 char 在您的平台上是无符号的,则与 255 进行比较会起作用,但读取 ÿ 可能会产生相同的字节值 255,并且也可能被误认为是 EOF。在发布的代码中,c 被正确地定义为 int,应将其与 EOF 进行比较,以使循环迭代到文件结尾。 - chqrlie
你是对的,我把 char 改成了 signed char,这样 EOF 就起作用了。 - Maher Sheikh
仅将 'char' 更改为 'signed char' 是不够的,您必须将 'c' 改为 'int',以使 'EOF' 检测可靠。 - chqrlie

-2
在Turbo C++中识别EOF,在终端窗口按下Ctrl+z;这将作为程序中的EOF,并终止程序...以满足以下条件:
while ((c = getchar()) != EOF) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接