我读的C语言程序设计,至今已经明白了一切。 然而,当我穿过来getchar()
和putchar()
我不明白什么是他们的使用,更具体,下面的代码做什么。
main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
据我所知, main()
函数,该整数的声明c
和while
循环。 然而,我感到困惑的内部条件while
循环。 什么是在这个C代码的输入,什么是输出。
很抱歉,如果这是一个基本的和愚蠢的问题,但我只是在寻找一个简单的解释之前,我在书中前进,变得更加混乱。
Answer 1:
该代码可以更清楚地写为:
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
}
}
该EOF
当没有更多的输入接收的字符。 该名称可以在正在从一个真实的文件读取输入,而不是用户的输入(这是一个文件的特殊情况)的情况下,更有意义。
[顺便说一句,一般的
main
功能应写为
int main(void)
。]
Answer 2:
getchar()
是从标准输入读取的字符的功能。 EOF
是在C中声明,已经达到了文件的末尾一个特殊字符。
通常你会得到一个EOF
字符从返回getchar()
当你的标准输入比其他主机(即文件)。
如果您在UNIX上运行您的程序是这样的:
$ cat somefile | ./your_program
那么你getchar()
将返回在每一个字符somefile
和EOF
尽快somefile
结束。
如果你像这样运行你的程序:
$ ./your_program
并发送EOF
通过控制台(通过按CTRL+D
在Unix或CTRL + Z在Windows中),那么getchar()
也将返回EOF
和执行将结束。
Answer 3:
也许你被一个事实,即进入-1在命令行上不会结束你的程序困惑? 因为getchar()
读取此为两个字符, -和1.在分配到c,字符被转换成ASCII数值。 这个数值被存储在某些存储位置,以c访问。
然后putchar(c)
检索该值,查找该ASCII表和转换回字符,其上打印。
我猜找到值-1十进制的ASCII表是不可能的,因为表从0开始。所以getchar()
必须考虑到在不同的平台上不同的解决方案。 也许有一个getchar()
版本,每个平台?
我只是觉得奇怪,这个EOF是不是在常规的ASCII。 它可能是第一个字符,这是不可打印的一个。 举例来说,最终的行为ASCII。
如果从Windows转移你的文件,将Linux会发生什么? 会在EOF文件字符自动更新?
Answer 4:
的getchar()函数从键盘读入一个字符(即, stdin
)
在给定的内部的状态while
循环, getchar()
在每次迭代之前调用,并且所接收的值被分配给整数c
。
现在,必须理解的是在C,标准输入( stdin
)是像一个文件。 即,输入被缓冲。 输入将留在缓冲区,直到它被实际消耗。 stdin
实际上是标准的输入流 。
getchar()
返回在输入缓冲器中的下一个可用的值。
该计划主要显示无论是从键盘读取; 包括空白像\n
(换行),空间等。
即,输入是用户通过键盘提供输入( stdin
通常意味着键盘)。 和输出是什么,我们提供的输入。
我们所提供的输入通过文字阅读文字和为字符,即使我们给他们的数字处理。
getchar()
返回EOF
只有到达文件的末尾。 我们在这里关注的是“文件”是stdin
本身(标准输入)。
想象一下,一个文件,其中存在被存储,我们通过键盘输入的内容。 这就是stdin
。 该“文件”就像是一个无限的文件 。 因此,没有EOF
。
如果我们比提供更多输入getchar()
可以同时处理(按enter给它输入前),多余的值将仍然被存储在输入缓冲器未消费。 所述getchar()
将来自输入读出的第一个字符,将其存储在c and print
Ç with
的putchar(C)`。
在的下一次迭代while
循环,以前的迭代过程中给予额外的字符,这仍然在stdin
的过程中采取的while ((c = getchar()) != EOF)
与c=getchar()
的一部分。 现在,重复同样的过程,直到没有任何留在输入缓冲区。
这使得它看起来仿佛putchar()
是在一个时间如果超过一个字符被迭代期间给定为输入返回字符串而不是一个单独的字符。
例如:如果输入的是
abcdefghijkl
输出会一直同
abcdefghijkl
如果你不希望这种行为,你可以添加fflush(标准输入); 后右putchar(c);
。 这将导致循环中的每个迭代期间提供的输入仅打印的第一个字符。
例如:如果输入的是
adgbad
只有a
将被打印。
输入发送到stdin
只有按下回车。
的putchar()是相反getchar()
它的输出写到标准的输出流( stdout
,通常是在显示器上)。
EOF
不是存在于文件中的字符。 这是由函数作为返回错误代码的东西。
你可能不能够从给退出while
循环正常不过。 输入缓冲器将清空(用于显示与输出),只要东西通过键盘进入它和stdin
不会给EOF
。
用于手动退出循环, EOF
可以使用键盘通过在Linux和按下Ctrl + d发送
CTRL + Z在Windows
例如:
while ((c = getchar()) != EOF)
{
putchar(c);
fflush(stdin);
}
printf("\nGot past!");
如果您按下组合键给EOF
,该消息Got past!
在退出程序之前将被显示。
如果stdin
是已经为空,则必须按两次此组合键。 一旦清除该缓冲器,然后simuate EOF
。
编辑:一对额外左右括号的c = getchar()
中while ((c = getchar()) != EOF)
是确保返回的值getchar()
被首先分配给c
之前值与比较EOF
。
如果这个额外的括号里不存在,表达将有效地一直while (c = (getchar() != EOF) )
这将已经意味着c
可能要么2个的值: 1
(真正的)或0
(对于假的),这显然不是什么打算。
Answer 5:
与目前的C类标准编写的代码应该是
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
循环可改写为
int c;
while (1) {
c = getchar();
if (c != EOF)
putchar(c);
else
break;
}
此全文
- 永远重复
- 得到输入的下一个字符(“字节”) 的标准输入并存储到
c
- 如果在阅读上述文字没有发生异常情况
- 其他
许多编程语言处理通过提高是打破正常的程序流程例外的例外情况。 C不用没有这样的事。 相反,可能出现故障的功能有返回值和任何异常情况是由一个特殊的返回值,这需要从给定函数的文档,以检查信号。 在的情况下getchar
,从C11标准的文件说( C11 7.21.7.6p3 ):
- 该
getchar
函数返回从输入流中的下一个字符被指向stdin
。 如果流是在结束的文件,该流结束文件指示符被设置和getchar
返回EOF
。 如果发生读取错误时,该流的错误指示器被设置和getchar
返回EOF
。
它在其它地方指出, EOF
是一个整数常量,它是<0,以及任何普通的返回值是> = 0 -的unsigned char
零扩展到int
。
处于-的文件结束的流是指所有的输入已被消耗掉。 对于标准的输入,可以在Windows控制台窗口中输入在Unix / Linux终端按Ctrl + d和Ctrl + Z从键盘导致此问题。 另一种可能性是,该方案从文件或管道,而不是从键盘接收输入 - 那么档案结尾将信号每当输入被完全消耗,即
cat file | ./myprogram
要么
./myprogram < file
由于上述片段说,实际上有两种不同的情况,可能会导致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('?');
}
}
要触发档案结尾,人们会使用Ctrl + d(这里显示为^D
在Linux上一个新行):
% ./a.out
Hello world
Hello world
^D
end-of-file reached
(注意这里的输入是如何行缓冲,所以输入不与输出线路内交错)。
同样,我们可以通过使用管道获得同样的效果。
% echo Hello world | ./a.out
Hello world
end-of-file reached
触发一个错误是一个比较棘手。 在bash
和zsh
壳标准输入可以被关闭 ,使得它不从任何地方来,通过附加<&-
到命令行:
% ./a.out <&-
An error occurred. errno set to 9
Human readable explanation: Bad file descriptor
错误的文件描述符 ,或EBADF
意味着标准输入 -文件描述符0是无效的,因为它完全没有打开。
另一种有趣的方式来产生一个错误将读取目录标准输入-这将导致错误号设置为EISDIR
在Linux上:
% ./a.out < /
An error occurred. errno set to 21
Human readable explanation: Is a directory
事实上的返回值putchar
也应该被检查-它同样返回EOF
上的错误,或字符写的:
while ((c = getchar()) != EOF) {
if (putchar(c) == EOF) {
perror("putchar failed");
exit(1);
}
}
现在我们可以通过标准输出重定向到测试此/dev/full
-但有一个疑难杂症-因为标准输出缓冲,我们需要编写足以引起缓冲区马上而不是在节目的最后冲洗。 我们从无限零个字节/dev/zero
:
% ./a.out < /dev/zero > /dev/full
putchar failed: No space left on device
PS是非常重要的始终使用类型的变量int
存储的返回值getchar()
即使它读入一个字符 , 使用signed
/ unsigned
/纯char
永远是错的 。
Answer 6:
以类似的方式向| 以上你管命令可以使用系统上的重定向利用上面的代码来显示一个文件的所有字符内容,直到它到达由CTRL-Z或CTRL-d通常表示的结束(EOF)。
在控制台: ProgramName < FileName1.txt
并创造了什么是从FILENAME1您可以阅读副本: ProgramName < FileName1.txt > CopyOfInput.txt
这表明你以多种方式帮助有希望您的理解程序。
-Hope帮助。
Answer 7:
main(){
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
实际上C =的getchar()提供了用户在控制台上进入字符并将该值与EOF表示文件的结束进行检查。 EOF在最后一个文件的遭遇。 (C =的getchar())!= EOF相当于到c!= EOF。 现在,我认为这是容易得多。 如果任何进一步的询问让我知道。
Answer 8:
getchar()
会从输入的字符。
c = getchar()
这种分配的值是左侧的分配后的价值,或者说已经读过该字符的值。 价值EOF
是默认-1
。
((c = getchar()) != EOF)
只要值保持比其他东西EOF
或者,换句话说,只要条件保持为真,循环将继续进行迭代。 一旦该值变为EOF
整个条件的值将是0
,它会中断环路。
周围的附加括号c = getchar()
是编译器,要强调的是,我们真正想做的条件内的任务,因为它通常假定你想输入==
并发出警告。
main() {
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
所以整个代码实际上回显你输入。 其分配的字符的值c
的条件内,然后输出它放回循环体,检测文件的末尾时,仅仅结束。
文章来源: I'm trying to understand getchar() != EOF