理解C语言中的getchar()和putchar()

理解C语言中的getchar()和putchar(),c,C,getchar函数从屏幕读取字符并返回其ASCII值。此函数一次只能读取单个字符 putchar函数将传递的字符放在屏幕上,并返回字符的ASCII值。此函数一次只放置一个字符 现在考虑下面的代码1 输出: a a abcd abcd ^Z 代码1工作正常,因为如果我们键入超过1个字符,那么getchar函数将只读取第一个字符并返回其ASCII值。但是在代码2带有循环的情况下,为什么要打印整个字符串而不是1个字符 代码段1读取一个无符号字符,打印它并结束程序 代码段2读取一个无符号字符,如果它没有

getchar函数从屏幕读取字符并返回其ASCII值。此函数一次只能读取单个字符

putchar函数将传递的字符放在屏幕上,并返回字符的ASCII值。此函数一次只放置一个字符

现在考虑下面

的代码1 输出:

a

a

abcd

abcd

^Z

代码1工作正常,因为如果我们键入超过1个字符,那么getchar函数将只读取第一个字符并返回其ASCII值。但是在代码2带有循环的情况下,为什么要打印整个字符串而不是1个字符

代码段1读取一个无符号字符,打印它并结束程序

代码段2读取一个无符号字符,如果它没有读取EOF(通常为-1),则打印字符并读取另一个无符号字符,然后程序重新开始打印。否则,如果读取了EOF,则程序结束


这就是所谓的直线运动

长话短说: 来自终端的输入由线路处理。在您点击回车键之前,不会向您的程序传递任何内容。 这样可以编辑行擦除最后一个字符,并在出现错误时重新键入。这是由内核在getchar之前处理的,getchar通常作为宏来实现

类似地,输出在libc内部缓冲,只有在看到换行符“\n”字符时才实际发送到内核,除非显式刷新。注意这与上面的不同,因为它由libc处理,而输入由内核处理

如果要一次处理一个输入字符,在输入字符后,必须立即将用于cbreak的特定终端的行规程设置为cbreak。许多终端处理库就是这样做的,例如:ncurses

请参阅stty 1的手册页以进行一些讨论

回到您的代码片段: 发生的事情是,所有的字符都被缓冲在内核中,并在第一行正确地回显,直到您点击CR。 在这一点上,整行代码被传递到您的程序,该程序将愉快地循环吃char并将其吐回。 当到达cr时,libc实际上会将其转换为换行符“\n”,您一次生成一个字符的整行代码会被吐回内核,从而被吐回终端。 然后点击CTRL-Z,内核将其解释为EOF,因此通过libc返回的另一个getchar将失败并返回-1。
如果您希望能够在Win上读取所有字符,包括Ctrl-Z,那么在Unix/Linux下,塔尔将是Ctrl-D。您需要将行规则设置为raw,这是一种非常高级的功能,可能会锁定您的终端

在代码2中,当您键入字符串时,比如说abcd并按enter键,输入的数据进入标准输入流stdin1。getchar从stdin读取一个字符,然后程序的执行到达while循环

在循环中,putchar输出存储在c中的字符,即您输入的第一个字符,即a。对getchar的下一个调用不会等待进一步的输入,因为它在stdin2中看到了字符。这个getchar读取下一个字符b,因为它不是EOF,所以循环继续

此过程将继续,直到getchar读取使用CTRL+Z输入的EOF字符,最后程序结束

1:所有数据包括您按下的enter键。
2:这也意味着getchar在stdin为空时等待您输入字符。

@alk为什么打印整个字符串而不是1个字符OT:至少是int mainvoid。您的问题是关于getchar和putchar还是关于循环?根据您的描述,您似乎理解了正在发生的事情,除了在代码2中您有一个循环之外,您不了解它的哪些方面?
#include<stdio.h>
void main()
{
    int c=getchar();
    putchar(c);
}
#include<stdio.h>
void main()
{
    int c=getchar();
    while(c!=EOF)
    {
        putchar(c);
        c=getchar();
    }
}