【C-Primer-Plus读书笔记】第8章:字符输入/输出和输入验证
IO函数负责把信息传送到程序中。
单字符I/O:getchar()和putchar()
- getchar()和putchar()每次只处理一个字符,这种方法很适合计算机。而且,这是大多数文本处理程序所用的核心方法。
- 其实getchar()和putchar()都不是真正的函数,它们被定义为供预处理器使用的宏。
缓冲区
无缓冲和缓冲输入
- 用户输入文本时回显用户输入的字符后立即重复打印该字符是属于无缓冲(直接)输入,即正在等待的程序可立即使用输入的字符;
- 而在用户按下Enter键之前不会重复打印刚输入的字符,这种输入形式属于缓冲输入,用户输入的字符被收集并存储在一个被称为缓冲区的临时存储区,按下Enter键后,程序才可以使用用户输入的字符。
为什么要有缓冲区?
- 把若干字符作为一个块进行传输比逐个发送这些字符节约时间;
- 如果用户打错字符,可以直接通过键盘修正错误,当按下Enter键时,传输的是正确输入。
缓冲输入和无缓冲输入都有用武之地
缓冲的分类:完全缓冲I/O和行缓冲I/O
- 完全缓冲输入指的是当缓冲区被填满时才刷新缓冲区(内容被发送至目的地),通常出现在文件输入中。
- 行缓冲I/O指的是在出现换行符时刷新缓冲区。键盘输入通常是行缓冲输入,所以在按下Enter键后才刷新缓冲区。
缓冲区的大小取决于系统,常见的大小是512字节和4096字节。
结束键盘输入
文件、流和键盘输入
- 文件是存储器中存储信息的区域。
- 从较低层面上,C可以使用主机操作系统的基本文件工具直接处理文件,这些直接调用操作系统的函数被称为底层I/O。
- 从较高层面上,C还可以通过标准I/O包来处理文件。这涉及创建用于处理文件的标准模型和一套标准I/O函数。在这一层面上,具体的C实现负责处理不同系统的差异,以便用户使用统一的界面。
- 从概念上看,C程序处理的是流而不是直接处理文件。流是一个实际输入或输出映射的理想化数据流。这意味着不同属性和不同种类的输入,由属性更统一的流来表示。
- C把输入和输出设备视为存储设备上普通的文件,尤其是把键盘和显示设备视为每个C程序自动打开的文件。stdin流表示键盘输入,stdout流表示屏幕输出。
- C的输入函数内置了文件结尾检查器。既然可以把键盘输入视为文件,那么也应该能使用文件结尾检查器结束键盘输入。
文件结尾
计算机操作系统要以某种方式判断文件的开始和结束:
- 检测文件结尾的第一种方法是,在文件末尾放一个特殊字符(如 Ctrl+Z)标记文件结尾;
- 操作系统使用的另一种方法是存储文件大小的信息(程序读到该文件的字节大小时即到达文件末尾)。
- 无论操作系统实际使用何种方法检测文件结尾,在C语言中,用getchar()读取文件检测到文件结尾时将返回一个特殊的值,即EOF。scanf()函数检测到文件结尾时也返回EOF。
- EOF是一个值(一般定义为(-1)的宏),标志着检测到文件结尾,并不是在文件中找得到的符号。
- 在程序进行键盘输入,要设法输入EOF字符。在大多数UNIX和Linux系统中,在一行开始处按下
Ctrl+D
会传输文件结尾信号。许多微型计算机(PC)系统把一行开始处的Ctrl+Z
识别为文件结尾信号,一些系统把任意位置的Ctrl+Z
解释成文件结尾信号。
重定向和文件
- 输入和输出涉及函数、键盘和设备。
- 在默认情况下,C程序使用标准I/O包查找标准输入作为输入源,即
stdin
流。 程序可以通过两种方式使用文件:
- 显式使用特定的函数打开文件、关闭文件、读取文件、写入文件;
- 设计能与键盘和屏幕互动的程序,通过不同的渠道重定向输入至文件和从文件输出。换言之,把stdio流重新赋给文件。继续使用getchar()函数从输入流中获取数据,但他并不关心从流的什么位置获取数据。
- 重定向的一个主要问题是它与操作系统有关,与C无关。
UNIX、Linux和DOS重定向
重定向输入让程序使用文件而不是键盘来输入,重定向输出让程序输出至文件而不是屏幕。<
符号是重定向输入运算符,该运算符把文件与stdio
流相关联;>
符号是重定向输出运算符,该运算符把文件与stdout
流相关联。- 使用两个重定向运算符可以达到组合重定向的作用。
- 重定向是一个命令行概念,因为我们要在命令行输入特殊的符号发出指令。
创建更友好的用户界面
使用缓冲输入。
- 缓冲输入用起来比较方便,因为在输入发送前,用户还可以编辑输入。
- 注意处理用户按下Enter键发送输入后产生的换行符。
- 混合数值和字符输入
getchar()
读取每个字符,包括空格、制表符和换行符;而scanf()
在读取数字时则会跳过空格、制表符和换行符,所以很容易留下一些字符在输入队列中。两个都是输入函数,但是注意不能混用getchar()
和scanf()
。
输入验证
- 程序遵循模块化的编程思想,使用独立函数(模块)来验证输入和管理显示。
main()
函数管理程序流,为其他函数委派任务。- 输入流和数字:在我们眼中,用户的输入是一个由字符、数字或者浮点数组成的字符串,但对C程序而言,这就是一个字节流。输入函数会根据实际的转换说明进行数据转换以便存入对应数据类型的变量中。
菜单浏览
C的语句是根据选项决定行为的好工具,用户的每个选择都可以对应一个特定的case标签。