我正在尝试了解终端驱动程序如何与getchar一起使用。以下是我在阅读KandR时编写的一些示例代码:
代码1:
#include <stdio.h>
int main(){
int c = getchar();
putchar(c);
return 0;
}
代码2:
#include <stdio.h>
int main(){
int c = EOF;
while((c=getchar()) != EOF){
printf("%c",c);
}
return 0;
}
代码3: //模仿wc命令功能的准系统程序
#include <stdio.h>
#define IN 1
#define OUT 0
int main(){
//nc= number of characters, ns = number of spaces, bl=number of newlines, nw=number of words
int c = EOF,nc=0,nw=0,ns=0,nl=0, state = OUT;
while((c=getchar())!=EOF){
++nc;
if(c=='\n'){
++nl;
state = OUT;
}
else if(c==' '){
++ns;
state = OUT;
}
else{
if(state == OUT){
state = IN;
++nw;}
}
}
printf("\n%d %d %d %d",nc,nw,ns,nl);
return 0;
}
我希望了解终端驱动程序何时将输入字符串移交给程序。假设我的输入是字符串“这是一个测试”,我按回车,然后这是上述代码如何工作:
代码1:输出“t”(程序结束)
代码2:输出“这是一个测试”,跳转到下一行(因为它也输出按下的输入)并再次等待输入。
代码3:不输出上面的字符串后跟一个输入的任何内容。我需要按Ctrl + D才能显示输出(输出为15 4 3 1)
1)为什么在代码3的情况下,我是否需要显式按Ctrl + D(EOF)才能将输入发送到我的程序?换句话说,为什么我的输入字符串发送到我的程序代码1和代码2后我按下回车?为什么不要求EOF?
2)另外,在代码3的情况下,如果我没有在输入字符串后按Enter键,我需要按两次Ctrl + D才能显示输出。为什么会这样?
修改
对于另一个输入说“TESTING ^ D”,以下是上述代码的工作原理:
1)输出“T”并结束
2)输出“TESTING”并等待更多输入
3)在按下另一个Ctrl + D之前不输出任何内容。然后它输出7 1 0 0.
如果是这个输入,在代码1和代码2的情况下接收到Ctrl + D时,终端驱动程序将输入字符串发送到程序。这是否意味着/ n和Ctrl + D的处理方式相同,即它们两者都作为终端驱动程序的标记,将输入发送给程序?那么为什么我需要按Ctrl + D两次才能进行第二种情况?
此http://en.wikipedia.org/wiki/End-of-file表示驱动程序在换行符时将Ctrl + D转换为EOF。但是在我的“TESTING ^ D”输入的情况下,即使^ D与输入的其余部分位于同一行,它也能正常工作。可能的解释是什么?
答案 0 :(得分:3)
一般信息:
如果代码2:您还需要执行ctrl + D才能退出。
实际上EOF是通过按ctrl + D来实现的,所以你的while循环条件是:
EOF只是整数-1,这可以通过按ctrl + D在终端中实现。以此为例:
while((c=getchar()) != EOF){
// execute code
}
printf("loop has exited because you press ctrl+D");
当按下ctrl + D时,条件继续接收输入但停止,然后继续执行其余代码。
回答你的问题:
1)为什么在代码3的情况下我需要显式按Ctrl + D(EOF) 输入要发送到我的程序?换句话说, 在代码1和代码的情况下,为什么我的输入字符串被发送到我的程序 我按下后输入2?为什么不要求EOF?
在代码2和3(不仅仅是3)中,您需要按Ctrl + D,因为while循环仅在读取EOF时停止从键盘输入。在代码1中,您没有循环,所以当您输入一个或多个字符时,程序将读取输入的字符但仅存储第一个字符,然后它将打印它并终止程序,因此在这种情况下不需要EOF因为在任何情况下你都不会要求它。
2)另外,在代码3的情况下,如果我在输入后没有按回车键 字符串,我需要按两次Ctrl + D才能显示输出。 为什么会这样?
如果您在程序预期输入时开始输入,那么在输入至少一个字符后按ctrl + D,这将告诉程序停止输入并返回输入的字符。之后,如果你再次按ctrl + D而不输入任何字符,这将返回EOF,这将不满足while循环的条件并跳过继续执行其余代码