一、scanf
(一)语法
scanf("格式控制",地址表列);
scanf("a = %d");
a.普通字符 --- 原样输入
b.占位符 --- 将从键盘输入的数据 转换成指定的格式
1.格式控制字符
整型
%d --- 转换为 有符号 十进制形式
%u --- 转换为 无符号 十进制形式
%o --- 转换为 八进制形式
%x --- 转换为 十六进制形式
%X --- 转换为 十六进制形式 a b c d e f以大写形式输出
浮点型
%f --- 转换为 十进制形式的小数,输出时默认保留6位小数,不足6位 补0
输入的时候 ,这里要做到精确匹配
%f --- float
%lf --- double
%Lf --- long double
%ld --- long
%lld --- long long
%e --- 转换为 科学计数法的形式
%E 指数形式中e 变成 大写 E
%g --- 以 一种 更简洁的方式输出,同时不会输出无意义的0
字符型
%c --- 转换为字符形式输出
%s --- 转换为字符串形式输出
2.地址表列
int a;
scanf("a = %d",&a);
3.辅助控制符
%md
m //数据宽度 ---输入宽度
%7.2f // 输出宽度为7,保留两位小数
注意:
1. scanf 格式控制字符串中 尽量不出现 普通字符,一般只写 占位符
2. scanf 的地址列表中,一定是有效的地址
3. scanf 输入结束的条件(匹配结束的条件)
int a,b=0;
scanf("%d%d",&a,&b);如果你输入一个数比如(1234),scanf不会把它分割而只会把它当作输入的第一个数。
(二)scanf 读取结束条件
1)遇到与格式说明符不匹配的字符
例如,如果格式字符串是 "%d" 但输入是 "abc",则 scanf 将无法读取到整数,并立即返回。
“abc”会留在缓冲区供后续读取。
2)读取到足够的数据项
3)遇到文件结束符
Unix/Linux 系统中通常是 Ctrl+D,在 Windows 系统中通常是 Ctrl+Z 后跟回车键。
4)遇到空白符(空格,换行,tab)匹配结束
(三) 格式控制中如果出现空白符
表示 可以匹配多个空白符
注意 空白符 不要出现在格式控制末尾,因为他会一直读取,直到非空白字符的出现,也就是空白符不能结束读取了。
(四)scanf 函数读取时遵循的规则:
1.自动跳过前导空白:
在读取任何非字符串类型的数据(如整数、浮点数等)之前,
scanf 会自动跳过输入缓冲区中的任何前导空白字符(空格、制表符、换行符等)。
读取数据:根据格式说明符,scanf 会从输入缓冲区中读取相应的数据。
2.处理尾随空白:
如果格式字符串中的某个格式说明符后面紧跟一个或多个空白字符(空格、制表符等),
则 scanf 在读取完该数据项后,会尝试读取并丢弃输入缓冲区中的这些尾随空白字符。
但是,请注意,scanf 只有在遇到非空白字符时才会停止读取并返回。
二、缓冲区
(一)缓冲区的作用
缓冲区:stdin 、stdout、 stderr 都有缓冲区。
1.临时存储:
缓冲区是用于临时存储从输入设备(如键盘)读取的数据的内存区域。
对于标准输入(stdin),C语言会提供缓冲区来存储用户输入的字符。
2.提高效率:
使用缓冲区可以减少程序和输入设备之间的交互次数,
因为数据可以首先被读取到缓冲区,然后程序再从缓冲区中批量读取数据,这比逐个字符地从输入设备读取数据要高效。
3.格式化输入:
缓冲区允许 scanf 这样的函数在读取输入时执行格式化输入,它会从缓冲区中提取数据并将其转换为指定的类型(如整数、浮点数等)。
(二)为什么使用scanf时要清除缓冲区
因为在缓冲区的数据会影响下一次读取,所以必须要清除缓冲区的数据
常用的清除缓冲区的方法
1、while(getchar() !='\n');
2、char buffer[100];
fgets(buffer,sizeof(buffer),stdin);
3、scanf("%*s");
(三)缓冲区与scanf的关系
1.读取数据:
scanf 从标准输入的缓冲区中读取格式化的输入。
当用户输入数据并按下回车键时,这些数据被存储在缓冲区中,scanf 会从缓冲区中读取并解析这些数据。
2.处理空白字符:
scanf 默认使用空白字符(空格、制表符、换行符等)作为分隔符,来确定输入数据的界限。
它会从缓冲区中跳过这些空白字符,从而分隔不同的输入项。
3.返回读取项的数量:
scanf 返回成功匹配并读取的输入项的数量。
如果输入数据在缓冲区中不符合预期格式,scanf 可能无法读取所有预期的输入项。
4.残留数据:
如果用户的输入不完全符合 scanf 的格式字符串,一些输入数据可能会残留在缓冲区中,导致后续的输入读取操作可能无法正确执行。
5.清除缓冲区:
当 scanf 未能正确读取输入时,通常需要清除缓冲区,以防止残留数据影响后续的读取。
这可以通过读取并丢弃缓冲区中的剩余字符直到换行符来实现。
(四)缓冲区和回车键:
我们可能时常有疑问,为什么在使用scanf函数输入数据时,最后都要敲击一下回车键,数据才能被写入,程序才运行。
我们已知从键盘输入进去的数据是先进入输入缓冲区的,那么缓冲区和回车键到底是一个什么关系呢?
首先我们要了解行缓冲:
标准输入(stdin)通常是行缓冲的。(从键盘输入进去的,就是标准输入)
这意味着输入被存储在缓冲区中,直到遇到换行符(\n)或缓冲区满了,这时缓冲区中的内容会被发送给程序。
其次就是缓冲区的刷新:
当用户按下回车键时,缓冲区中累积的字符(包括换行符)会被刷新(即传递给程序处理)。
最后才是程序读取:
程序通过调用如 scanf、getchar 等输入函数从标准输入读取数据。
这些函数从缓冲区中读取数据,直到换行符,换行符通常不会被读取到程序变量中。
至于为什么使用回车键刷新跟早期打字机习惯有关。打字机有一个“回车”动作,它的作用是将纸张卷回起始位置,准备下一行的打字。所以我们就沿用了回车键刷新数据、换行这一习惯。