程序设计基础:字符能像整数一样计算
常定义在stdio.h中,实际上它们是预处理宏,不是真正的函数。虽然这些宏看起来很简单,但有时出了问题,却找不出原因。比如:
char ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d\n", ch1, ch2);
此时,如果输入字符'a',而打印结果却是"97,10"。因为从键盘输入一个字符后,就打印出了结果,还没有输入第二个字符程序就结束了。由于键盘输入一次结束后,会将数据存储在一个被称为缓冲区的临时存储区,按下Enter键后程序才可使用用户输入的字符,因此scanf()和getchar()也是从输入流缓冲区中取值的,而人们常常会产生这样的错觉,误以为它们是从键盘缓冲区取值的。实际上,数据是通过cin函数直接从输入流缓冲区中取走的,所以,当缓冲区中有残留数据时,cin函数会直接读取这些残留数据而不会请求键盘输入。
这里的10恰好是Enter键输入的换行符'\n',当读取数据遇到换行符'\n'结束时,换行符会一起读入输入流缓冲区,所以第一次接受输入时,取走字符后会留下字符'\n',于是第二次直接从缓冲区中将\n取走。
为何要有缓冲区呢?首先,将若干字符作为一个块进行传输比逐个发送这些字符节约时间。其次,如果用户打错字符,可以直接通过键盘修正错误。当最后按下Enter键时,传输的是正确的输入。虽然输入缓冲区的好处很多,但在某些交互式程序中也需要无缓冲区输入。比如,在游戏中,如果希望按下一个键就执行相应的命令,因此缓冲输入和无缓冲输入各有各的用武之地,但本书假设所有的输入都是缓冲输入。
缓冲分为两类:完全缓冲I/O和行缓冲I/O,完全缓冲输入指的是当缓冲区被填满时才刷新缓冲区,内容被发送到目的地,通常出现在文件输入中。缓冲区的大小取决于系统,常见的大小为512字节和4096字节。行缓冲区I/O指的是在出现换行符时刷新缓冲区,键盘输入通常是行缓冲区输入,所以在按下Enter键后才刷新缓冲区。
getchar()和scanf()
getchar()读取每个字符,包括空格、制表符和换行符;而scanf()在读取数字时,则会跳过空格、制表符和换行符。虽然这两个函数都很好用,但不能混合使用。
虽然putchar()的参数ch定义为int类型,但实质上它接收的是一个char类型字符,因为在putchar()内部,系统会将ch强制转换为char类型后再使用。如果字符输出成功,则putchar()返回输出的字符((char)ch),而不是输入的参数ch;如果不成功,则返回预定义的常量EOF(end of file,文件结束),EOF是一个整数。
getchar()没有输入参数,其返回值为int型,而不是char型。这里需要区分文件中的有效数据和输入结束符,当有字符可读时,getchar()不会返回文件结束符EOF,所以
ch = getchar() != EOF // 相当于ch = (getchar() != EOF)
取值为true,变量ch被赋值为1。
当程序没有输入时,则getchar()返回文件结束符EOF,即表达式取值为false,此时变量ch被赋值为0,程序结束运行。如果将getchar()函数的返回值定义为int型,则既能存储任何可能的字符,也能存储文件结束符EOF,将输入复制到输出的例程序详见程序清单1.36。
程序清单1.36 将输入复制到输出范例程序
1 #include
2 int main(int argc, char *argv[])
3 {
4 int ch;
5
6 while((ch = getchar()) != EOF){
7 putchar(ch);
8 }
9 return 0;
10 }
当然,也可以用getchar()的另一种惯用法替代程序清单
C语言编程 相关文章:
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 所有C语言数组和指针的知识都在这里了!|周立功手把手教你学C语言编程(08-01)
- 周立功《程序设计与数据结构》:字符串函数(08-05)
- 周立功手把手教你学C语言编程:用数组,构造一个双重指针(08-04)
- 周立功教你学程序设计结构体:内存对齐和基本数据类型(08-01)
- 跟周立功学C语言编程:如何将二维数组作为函数参数传递?这三要素要时刻谨记!(08-06)