什么是getchar函数?
getchar函数是一个输入函数,包含在stdio.h头文件中。它的作用是从键盘输入缓冲区中依次读取字符,每次读取一个,然后将该字符的ASCII码值作为整型返回。若读取出错,则返回EOF(即文件结束符,值为-1)。该函数无参数,一般使用形式为getchar()。
什么是输入缓冲区?
输入缓冲区是用来暂存用户从键盘输入字符的内存区。getchar函数用到的缓冲区是行缓冲区,也就是以换行符\n作为结束标志的缓冲区。
当程序调用getchar函数时,若此时输入缓冲区为空,则程序暂停,等待用户输入字符,直到用户输入了一个换行符\n(即enter按键)为止,此时将用户输入的所有字符存放到缓冲区中(包括最后的换行符\n)。然后getchar函数开始读取第一个字符的ASCII码值,并将此值作为函数值返回。下一次调用getchar函数时,getchar函数读取缓冲区中第二个字符的ASCII码值…直到缓存区的所有字符都被读取了一遍(缓冲区最后的\n也会被读取)。此时再调用getchar函数时,程序又暂停,等待用户输入…
什么情况下getchar函数读取出错?
当getchar函数读取到一个EOF(键盘输入为Ctrl+Z)时,读取出错,此时返回EOF(即-1)。
什么是EOF?
EOF即end of file的缩写,是一个特殊的字符,称为文件结束符。类似其他字符,EOF本质上也是一个整型值,但EOF没有ASCII码,它的值为-1。在终端用键盘输入EOF的方法是Ctrl+Z,但应注意不是所有的Ctrl+Z都代表EOF。
为什么不是所有的Ctrl+Z输入都代表EOF?
Ctrl+Z在终端输入时显示为^Z,这个输入可以代表两个字符,一是ASCII码为26的控制字符SUB,另一个是文件结束符EOF。判断其到底代表哪个字符要看它在输入缓冲区中的位置,若它在输入缓冲区的第一个字符,就代表EOF。否则代表替代字符SUB。
什么是替代字符SUB?
(上文中的方块符号在本文中会显示为␚,因此上文以图片形式放出。)
实例
int main()
{
int i;
char ch;
for (i = 1, ch = getchar(); ch != EOF; i++, ch = getchar()) //ch == EOF时跳出循环
{
printf("%d", i);
printf("%c", ch);
}
return 0;
}
输入a、b、c、Ctrl+Z、Enter五个字符,运行结果如下:
程序执行了四次循环,并在第四次打印了4␚。显然,此处不在首位的Ctrl+Z被识别为了替代字符␚。执行逐过程调试并监视ch的值,也可以印证ch在第四次循环中被赋值为␚:
应注意␚后本来还有一个字符\n,本应执行第五次循环并打印5\n,但结果没有进入第五次循环,而是在第四次循环结束后等待用户输入新的字符。这说明getchar函数在读取到␚后,清空了输入缓冲区。再次调用getchar函数时需要重新从键盘输入。
输入Ctrl+Z、a、b、c、Enter五个字符,运行结果如下:
此处的Ctrl+Z在首位,因此被识别为了EOF。ch被赋初值为EOF,未满足循环条件,程序直接结束。在逐过程调试中监视ch的值可以看到,ch的初值为-1:
将for循环的循环条件表达式修改一下:
int main()
{
int i;
char ch;
for (i = 1, ch = getchar(); ch != '\x1a'; i++, ch = getchar()) //ch == SUB时跳出循环
{
printf("%d", i);
printf("%c", ch);
}
return 0;
}
此时再输入Ctrl+Z、a、b、c、Enter五个字符,运行结果如下:
输入缓冲区的首个字符EOF后还有4个字符,本应继续在后四次循环中将后四个字符依次赋给ch,打印2a3b4c5\n,但结果并非如此。这说明getchar函数在读取EOF后,也清空了输入缓冲区。再次调用getchar函数时需要重新从键盘输入。