Pao*_*oni 33 c putchar eof getchar
我正在阅读C语言程序,并且到目前为止已经理解了所有内容.然而,当我遇到getchar()并且putchar(),我无法理解它们的用途,更具体地说,以下代码的作用.
main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
Run Code Online (Sandbox Code Playgroud)
我理解main()函数,整数的声明c和while循环.然而我对while循环中的条件感到困惑.这个C代码的输入是什么,输出是什么.
对不起,如果这是一个基本而愚蠢的问题,但我只是在寻找一个简单的解释,然后再继续阅读本书并变得更加困惑.
Oli*_*rth 30
此代码可以更清晰地编写为:
main()
{
int c;
while (1) {
c = getchar(); // Get one character from the input
if (c == EOF) { break; } // Exit the loop if we receive EOF ("end of file")
putchar(c); // Put the character to the output
}
}
Run Code Online (Sandbox Code Playgroud)
在EOF当没有更多的输入接收的字符.在从真实文件读取输入而不是用户输入(这是文件的特殊情况)的情况下,名称更有意义.
main函数应该写成int main(void).]
Pab*_*ruz 18
getchar()是一个从标准输入中读取字符的函数.EOF是C中用于表示已达到END OF FILE的特殊字符.
通常EOF,getchar()当标准输入不是控制台(即文件)时,您将获得一个返回的字符.
如果您在unix中运行您的程序,如下所示:
$ cat somefile | ./your_program
Run Code Online (Sandbox Code Playgroud)
然后你的getchar()意志将返回每一个角色,somefile并EOF尽快somefile结束.
如果您运行这样的程序:
$ ./your_program
Run Code Online (Sandbox Code Playgroud)
并EOF通过控制台发送(通过CTRL+D在Windows中按Unix或CTRL + Z),然后getchar()也将返回EOF并执行将结束.
用当前的 C 标准编写的代码应该是
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
Run Code Online (Sandbox Code Playgroud)
循环可以改写为
int c;
while (1) {
c = getchar();
if (c != EOF)
putchar(c);
else
break;
}
Run Code Online (Sandbox Code Playgroud)
这读作
cc到标准输出中许多编程语言通过引发破坏正常程序流程的异常来处理异常情况。C 没有这样的事情。相反,可能失败的函数有一个返回值,任何异常情况都由一个特殊的返回值表示,您需要从给定函数的文档中检查。对于getchar,来自 C11 标准的文档说(C11 7.21.7.6p3):
- 该
getchar函数从 指向的输入流中返回下一个字符stdin。如果流位于文件尾,则设置流的文件尾指示符并getchar返回EOF。如果发生读取错误,则设置流的错误指示符并getchar返回EOF。
在别处说明这EOF是一个 < 0 的整数常量,并且任何普通的返回值是 >= 0 -unsigned char零扩展到int.
位于文件末尾的流意味着所有输入都已被消耗。对于标准输入,可以通过打字键盘从导致这种Ctrl+D在Unix / Linux终端和Ctrl+Z在Windows控制台窗口。另一种可能性是程序从文件或管道而不是从键盘接收输入 - 然后每当输入被完全消耗时就会发出文件结束信号,即
cat file | ./myprogram
Run Code Online (Sandbox Code Playgroud)
或者
./myprogram < file
Run Code Online (Sandbox Code Playgroud)
正如上面的片段所说,实际上有两种不同的情况会导致getchar返回EOF:到达文件末尾,或者发生了实际错误。这不能仅从返回值中推导出来。相反,您必须使用函数feof和ferror。feof(stdin)如果在标准输入上到达文件结尾,将返回一个真值。ferror(stdin)如果发生错误,将返回 true。
如果发生实际错误,则errno定义的变量<errno.h>将包含错误代码;该函数perror可用于自动显示带有前缀的人类可读错误消息。因此我们可以将示例扩展为
#include <stdio.h>
#include <errno.h> // for the definition of errno
#include <stdlib.h> // for exit()
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
if (feof(stdin)) {
printf("end-of-file reached\n");
exit(0);
}
else if (ferror(stdin)) {
printf("An error occurred. errno set to %d\n", errno);
perror("Human readable explanation");
exit(1);
}
else {
printf("This should never happen...\n");
exit('?');
}
}
Run Code Online (Sandbox Code Playgroud)
要触发文件结尾,可以^D在 Linux 上的新行上使用 Ctrl+D(此处显示为):
% ./a.out
Hello world
Hello world
^D
end-of-file reached
Run Code Online (Sandbox Code Playgroud)
(注意这里的输入是如何行缓冲的,所以输入不会在输出行内交错)。
同样,我们可以通过使用管道来获得相同的效果。
% echo Hello world | ./a.out
Hello world
end-of-file reached
Run Code Online (Sandbox Code Playgroud)
触发错误有点棘手。在bash和zshshell 中,可以通过附加到命令行来关闭标准输入,使其不会来自任何地方<&-:
% ./a.out <&-
An error occurred. errno set to 9
Human readable explanation: Bad file descriptor
Run Code Online (Sandbox Code Playgroud)
Bad file descriptor,或者EBADF意味着标准输入- 文件描述符编号 0 无效,因为它根本没有打开。
另一种产生错误的有趣方式是从目录中读取标准输入——这会导致EISDIR在 Linux 上将errno 设置为:
% ./a.out < /
An error occurred. errno set to 21
Human readable explanation: Is a directory
Run Code Online (Sandbox Code Playgroud)
实际上也putchar应该检查的返回值- 它同样返回EOF错误或写入的字符:
while ((c = getchar()) != EOF) {
if (putchar(c) == EOF) {
perror("putchar failed");
exit(1);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以通过将标准输出重定向/dev/full到来测试这一点——但是有一个问题——因为标准输出是缓冲的,我们需要写足够的内容来使缓冲区立即刷新,而不是在程序结束时刷新。我们从/dev/zero以下获得无限零字节:
% ./a.out < /dev/zero > /dev/full
putchar failed: No space left on device
Run Code Online (Sandbox Code Playgroud)
PS 始终使用类型变量int来存储getchar(). 尽管它读取一个字符,使用signed/ unsigned/纯char永远是错的。
getchar() 函数从键盘读取一个字符(即stdin)
在给定循环内的条件中while,getchar()在每次迭代之前调用,并将接收到的值分配给整数c。
现在,必须明白,在 C 中,标准输入 ( stdin)就像一个文件。即,输入被缓冲。输入将保留在缓冲区中直到被实际消耗。\nstdin实际上是标准输入流。
getchar()返回输入缓冲区中的下一个可用值。
该程序本质上显示从键盘读取的任何内容;包括空白,如\\n(换行符)、空格等。
即,输入是用户通过键盘(stdin通常指键盘)提供的输入。\n输出是我们提供的输入。
我们提供的输入会被逐个字符地读取并被视为字符,即使我们将它们作为数字给出。
\n\ngetchar()EOF仅当到达文件末尾时才会返回。我们这里关心的\xe2\x80\x98file\xe2\x80\x99就是它本身stdin(标准输入)。
想象一下存在一个文件,其中存储了我们通过键盘提供的输入。那\xe2\x80\x99s stdin。\n这个\xe2\x80\x98file\xe2\x80\x99 就像一个无限文件。所以不EOF。\n
如果我们提供的输入多于getchar()一次可以处理的输入(在按 Enter 键将其作为输入之前),多余的值仍将存储在输入缓冲区中未使用。\n将从输入中读取 getchar()第一个字符,将其存储在c and printc withputchar(c)`.
在循环的下一次迭代期间,在上一次迭代期间给出的仍在该部分while中的额外字符将在该部分中stdin被获取 。\n现在重复相同的过程,直到输入缓冲区中没有任何内容为止。while ((c = getchar()) != EOF)c=getchar()
putchar()如果在迭代期间给出多个字符作为输入,这使得它看起来好像一次返回一个字符串而不是单个字符。
例如:如果输入是
\n abcdefghijkl
\n输出将\xe2\x80\x99相同
\nabcdefghijkl
如果你不\xe2\x80\x99不想要这种行为,你可以添加fflush(stdin); 紧接在putchar(c);.\n之后,这将导致循环仅打印每次迭代期间提供的输入中的第一个字符。
例如:如果输入是
\n adgbad
\nonlya将被打印。
stdin仅当您按 Enter 键后,输入才会发送到。
putchar()与 .putchar() 相反getchar()。它将输出写入标准输出流(stdout通常是监视器)。
\nEOF不是文件中存在的字符。它\xe2\x80\x99是函数返回的错误代码。
不过,您可能无法while正常退出 \xe2\x80\x99 循环。一旦有东西通过键盘进入输入缓冲区,输入缓冲区就会清空(用于显示到输出),并且不会stdin给出EOF.
对于手动退出循环,EOF可以使用键盘发送,在 Linux 中按 \n ctrl+和\n +D
ctrlZ ,在 Windows 中
例如:
\n\nwhile ((c = getchar()) != EOF)\n{\n\n putchar(c);\n fflush(stdin);\n}\nprintf("\\nGot past!");\nRun Code Online (Sandbox Code Playgroud)\n\n如果您按组合键给出EOF,则消息Got past!,则在退出程序之前将显示
如果stdin尚未为空,则必须按此组合键两次。一次清除该缓冲区,然后模拟EOF。
c = getchar()编辑: in周围的额外一对括号while ((c = getchar()) != EOF)是为了确保返回的值在与该值进行比较之前getchar()首先被分配给cEOF。
如果没有这个额外的括号,则表达式实际上将意味着while (c = (getchar() != EOF) )可以c有两个值之一:(1对于 true)或0(对于 false),这显然不是预期的。
| 归档时间: |
|
| 查看次数: |
56942 次 |
| 最近记录: |