07-字符输入_输出和输入验证

把输入和输出简称为I/O函数,负责把信息传送到程序中

0x00 例子

getchar()和putchar()每次只处理一个字符,这是绝大多数文本处理程序所用的核心方法。

/*echo.c – 该程序获取从键盘输入的字符,并把这些字符发送到屏幕上,程序使用while循环,当读到#字符时停止*/

 #include <stdio.h>

int main(void)
{
    char ch;

    while((ch = getchar()) != ‘#’)
{
    putchar(ch);
}
    return 0;
}

可以输入’#’符号来结束程序

0x01 缓冲区

  • 无缓冲区输入:iilliikkee yyoouu..[enter],不会有回显,因为无缓冲区会立刻打印到标准输出设备
  • 有缓冲区输入:like you.[enter],会有回显,因为字符存在系统缓冲区内,按下enter键程序才会输出用户打印的值
  • 为什么需要缓冲区:把若干个字符作为一个块输出比逐个发送这些块节省时间,而且用户如果输入错误可以修改。
  • 缓冲区分为两类:完全缓冲I/O和行缓冲
    • 完全缓冲输入指的是当缓冲区倍填满时才刷新缓冲区,通常出现在文件输入中,缓冲区大小取决于系统,常见的是512字节和4096字节
    • 行缓冲I/O值得是在出现换行符刷新缓冲区,键盘输入通常是行缓冲
  • ANSI C和后续的C标准都管的输入时缓冲的,不过最初K&R把这个决定权交给了编译器的编写者。ANSI C 绝大把缓冲区输入作为标准的原因是:一些计算机不允许无缓冲区输入,如果你的计算机允许无缓冲输入,那么你所用的C编译器很可能会提供一个无缓存输如的选项。conio.h头文件提供了无缓存输入的函数,回显无缓冲输入的getche()函数和用于无回显无缓冲输入的getch()函数。UNIX系统使用另一种不同的方式控制缓冲类型,使用ioctl()函数指定待输入的类型,然后用getchar()执行相应的操作。在ASNCI C中,用setbuf()setvbuf()函数控制缓冲,但是受限于一些系统的内部设置。

0x02文件、流和键盘输入

  • 文件是存储器中储存信息的区域。通常,文件都保存在某种永久存储器中,如:硬盘、U盘或DVD。编程的C源代码保存在文件中,用来编译C的源代码也保存在文件中。编译器打开C文件并读取其中的内存,当编译器处理完之后会关闭该源文件,文字处理器会打开、读取、修改、关闭
  • C可以使用主机操作系统的基本文件工具直接处理文件,这些直接调用操作系统的函数被称为底层I/O,由于计算机系统各不不同,所以C语言只是从较高层面通过标准I/O包来处理文件。这涉及创建用于处理文件的标准模型和一套标准I/O函数。
  • 差异指的是不同的系统储存文件的方式不同,有些系统把文件的内容储存在溢出,而文件相关的信息储存在另一处;有些系统在文件中创建一份文件描述。在处理文件方面,有些系统使用单个换行符标记末尾,而其他系统可能使用回车符合换行符的组合来表示行末表示行末尾。有些系统用最小字节来衡量文件的大小,有些系统则以字节块的大小来衡量。如果使用标准I/O包,就不用考虑这些差异。可以用if(ch == ‘\n’)检查换行符,即使系统实际用的是回车符合换行符的组合来标记行末,I/O函数会在两种表示法之间相互转换。
  • 从概念上看,C程序处理的是流而不是之间处理文件。流是一个实际输入或输出映射的理想化数据流。这意味着不同属性和不同种类的输入,由属性更统一的流来表示。
  • stdin流表示键盘输入,stdout流表示屏幕输出,getchar()、putchar()、printf()和scanf()函数都是标准的I/O包的成员,处理这两个流。
  • C把输入和输出设备视为存储设备上的普通文件,尤其是把键盘和显示设备视为每个C程序自动打开的文件。

0x03 文件结尾

计算机检测结尾通过检测文件末尾的一个特殊的字符标记文件结尾,或者使用CTRL+Z字符来标记文件结尾。现在可以记录文件的大小。无论操作系统实际使用何种方法检测文件结尾,在C语言中,使用getchar()读取文件检测到文件结尾时返回一个特殊的值,即EOF,scanf()函数检测到文件结尾时也返回EOF。通常EOF在stdio.h头文件定义为:#define EOF (-1)

因为getchar()只能识别一个字符。EOF只是标识文件达到了结尾,而不是在文件夹找得到的符号。

/*echo_eof.c – 重复输入,直到文件结尾*/

#include <stdio.h>

int main(void)
{
    int ch;
    while((ch = getchar()) != EOF)
{
    putchar(ch);
}

    return 0;
} 

  • 不用定义EOF,因为标准头文件已经定义过了
  • 不用担心EOF的实际值,因为在头文件中用#define预处理指令定义,可以直接使用
  • 变量ch的类型从char变成int,getchar()函数的实际返回类型是int
  • ch是整形不会影响putchar()函数
  • 找到当前系统要求,UNIX和Linux系统中,在一行开始处按下CTRL+D会传输文件结尾信号。许多微信计算机系统都把一行开始出的CTRL+Z识别为文件结尾信号,一些系统把任意位置的CTRL+Z解释成文件结尾信号。

0x04重定向和文件

重定向输入让程序使用文件而不是键盘来输入,重定向让程序输出至文件而不是屏幕。

  • “<”符号是UNIX和DOS/Windows的重定向运算符,echo_of.exe < words,该运算符使words文件与stdin流相关联,把文件中的内容导入echo_of.exe。echo_of.exe程序本身并不知道输入的内容是来自文件还是键盘,它只知道这是需要导入的字符流,所以它读取这些内容并把字符逐个打印在屏幕上,直到读到文件结尾

有一些系统不支持在重定向符号和文件名添加空格

  • “>”符号是第2个重定向运算符,echo_eof.exe>mywords。创建了一个mywords新文件,然后把echo_eof的输出重定向至该文件中。如果文件已存在通常会擦除该文件的内容,然后替换新的内容,有些系统会有保护现有文件的选择,使其成为只读文件。

  • 组合重合向保存mywords文件的副本,并命名为mywordsbak

    • 重定向运算符连接一个可执行程序包括标准操作系统和一个数据文件,不能用于连接一个数据文件和另一个数据文件,也不能用于连接一个程序和另一个程序
    • 使用重定向运算符不能读取多个文件的输入,也不能把输出定向至多个文件
    • 通常,文件名和运算符之间的空格不是必须的
    • >>运算符可以把数据添加到现有文件的末尾,而|运算符能把一个的输出连接到另一个文件的输入

0x05 减少错误输入的影响

  • 使用getchar跳过无效的字符输入
  • 使用scanf和getchar混合使用的时候注意scanf读取数字时会跳过空格、制表符和换行符而getchar()会读取。调用getchar()之前使用scanf()在输入行留下一个换行符,会导致一些问题。
0 条评论
发表一条评论