目录
2.2.2scanf函数输入了超过其变量承受范围的数据(缓冲区问题):
2.3.2getchar()在读取错误时会返回字符EOF也就是整形数值-1。
2.5.1 fflush(stdin)在高版本中已经不再使用(经测试,VC6.0完美支持,vs2015及以后版本不再支持,GCC(GCC4.6.2)不支持)
2.5.2尽管现在fflush(stdin)使用较少,但是fflush(stdout)在查看错误指示器的时候的效果仍然出众。
前言
本文章主要着眼于输入流,主要有以下几个方面:
1.scanf函数的一些特殊用法及常规用法
2.scanf函数使用时需要注意的事项
3.getchar一些使用规则
4.fgets与gets的关系及一些编译器报错的问题
5.fflush在输入,输出流中的应用
一、什么是输入流?
输入流:用白话讲就是把数据从某处读出来。
比如:我们可以从键盘上获取数据(标准输入流),也可以从已有文件中获取数据,等等。
那么我们将在第二部分介绍一些输入函数。
二、输入函数(部分)
2.1scanf函数
2.1.1基本格式: %[*][宽度][长度]说明符
对于每一部分的理解可以参照printf函数:
比如:printf(“%*d %d”,a,a,b)的意思是跳过读取到的第一个整数,将读取到的第二,三个整数以一列宽,整形长度打印出来。
但如果去掉 “ * ”
2.1.2除了[*]修饰符外的修饰符及作用:
修饰符介绍 | 作用介绍 |
%[a-z] | 读取在 a-z 之间的字符串,如果不在此之间则停止(仅为例子,并非唯一) |
%[^a-z] | 读取不在 a-z 之间的字符串,如果碰到a-z之间的字符则停止(仅为例子,并非唯一) |
%*[^=] | 前面带 * 号表示不保存变量。跳过“ = ”前的字符串(此仅是举个例子也可以不是“=”,而是其他符号),跳过字符后还应把值保存下来,可以参照下方例子 |
%[^=] | 读取字符串直到碰到’=’号,(’^’后面可以带更多字符不必是“=”) |
总结%[ ] 类型 | %[ ]表示要读入一个字符集合, 如果[ 后面第一个字符是”^”,则表示反意思。“*”表示跳过读取的意思。 [ ]内的字符串可以是1或更多字符组成。空字符集(%[])是违反规定的,可导致不可预知的结果。%[^]也是违反规定的。 |
即 "%" , "[]" , "^" , "*" 不是变数,其他均可按照要求来自行规划。
(2)的代码及结果
2.1.3格式符说明:
格式符 | 说明 |
%c | 读入一个字符 |
%d | 读入十进制整数 |
%i | 读入十进制,八进制,十六进制整数 |
%o | 读入八进制整数 |
%x,%X | 读入十六进制整数 |
%s | 读入一个字符串,遇空格、制表符或换行符结束 |
%f,%F,%e,%E,%g,%G | 用来输入实数,可以用小数形式或指数形式输入 |
%p | 读入一个指针 |
%u | 读入一个无符号十进制整数 |
%n | 至此已读入值的等价字符数 |
%[] | 扫描字符集合 |
%% | 读%符号 |
%a,%A | 读入一个浮点值(仅C99有效) |
...................................... | ............................................................................. |
2.1.4附加格式说明字符表·修饰符说明
长度修饰符:(用于指定整型变量的长度)
注意:黄色行表示 C99 引入的说明符和子说明符。
- 宽度:用数字表示读取或输出的最大字符数。例如,"%5d"表示读取或输出最多5个字符的整数。
- 精度:对于浮点数,用".数字"表示小数点后的位数。例如,"%.2f"表示只保留两位小数的浮点数。
另附:scanf是没有输入精度一说的。
2.2scanf使用时的注意事项:
2.2.1scanf函数中断问题
scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束,是数据的输入被截断效果与%[字符])。
① 遇空格、“回车”、“跳格”键。
② 遇宽度结束。
③ 遇非法输入。(自发的键盘输入)ctrl+z(终止scanf函数继续读取数据),也有其他情况
2.2.2scanf函数输入了超过其变量承受范围的数据(缓冲区问题):
scanf()的特殊之处在于,它会将原本用于分隔输入的空格和转义字符转入变量,
此种情况即为,把空格转入了变量b中。
那么如何消除缓冲区中的无用数据呢?
我们可以使用getchar()来吸收少量的多余字符,也可以用scanf()函数来吸收
但当多余字符较多时,我们可以使用getchar(),scanf()循环来清理缓冲区,也可以使用
上文提过的scanf(%[^\n]s)的形式搭配getchar()来清除。也可以使用fflush(stdin)在vs2015版本及其以后似乎这个方法可以使用,但没有效果,可以使用rewind(stdin)进行代替。
2.2.3新手上路时易犯错误:
1.没对变量取地址,
2.格式符与输入变量类型不符(比如char c;scanf(“%s”,&c);),
3.头文件未引用导致报错,
4.搞不清楚scanf给数组赋值时什么时候需要取地址什么时候不需要取地址(观察你用scanf复赋值的对象,若其为指针类型,则无需取地址,反之则需要,对于数组而言取地址与否没有影响,因为数组名(既没有取地址的时候),与取地址数组名有相同的地址)
2.3getchar()使用的注意事项:
2.3.1getchar的括号内部不可以有参数
2.3.2getchar()在读取错误时会返回字符EOF也就是整形数值-1。
关于为什么getchar的返回值时int而不是char:其实可以从某方面证明char也是一种int类型的数据
2.4fgets与gets
在支持C99的某些编译器上gets函数是不能使用的,而fgets是可以使用的
fgets的参数及用法与gets的参数及用法及某些情况下的替代
fgets的用法:
以下是cplusplus对fgets参数的解释:
关于gets函数参数的定义及说明:
请注意,gets 与 fgets 完全不同:gets不仅使用 stdin 作为源,而且在生成的字符串中不包含结束换行符,并且不允许指定 str 的最大大小(这可能导致缓冲区溢出)。
fgets在获取字符串的时候与scanf(%[^\n]s)有异曲同工之妙,故scanf可以作为fgets和gets的一个替代。
2. 5fflush的现状:
fflush主要用于输入输出流缓冲区的清空:
2.5.1 fflush(stdin)在高版本中已经不再使用(经测试,VC6.0完美支持,vs2015及以后版本不再支持,GCC(GCC4.6.2)不支持)
在vs中fflush(stdin)已经被替代为rewind(stdin)。
2.5.2尽管现在fflush(stdin)使用较少,但是fflush(stdout)在查看错误指示器的时候的效果仍然出众。