scanf高级用法【至此丢弃gets用法 】

三个方面讲解 scanf() 的高级用法。
1) 指定读取长度
还记得在 printf() 中可以指定最小输出宽度吗?就是在格式控制符的中间加上一个数字,例如,%10d 表示输
出的整数至少占用 10 个字符的位置:
 如果整数的宽度不足 10,那么在左边以空格补齐;
 如果整数的宽度超过了 10,那么以整数本身的宽度来输出,10 不再起作用。
其实,scanf() 也有类似的用法,也可以在格式控制符的中间加一个数字,用来表示读取数据的最大长度,例如:
%2d 表示最多读取两位整数;
%10s 表示读取的字符串的最大长度为 10,或者说,最多读取 10 个字符。
请看下面的例子:

 1 #include <stdio.h>
 2 int main(){
 3      int n;
 4      float f;
 5      char str[23];
 6 
 7      scanf("%2d", &n);
 8      scanf("%*[^\n]"); scanf("%*c"); //清空缓冲区
 9      scanf("%5f", &f);
10      scanf("%*[^\n]"); scanf("%*c"); //清空缓冲区
11      scanf("%22s", str);
12      printf("n=%d, f=%g, str=%s\n", n, f, str);
13 
14      return 0;
15 }

 


输入示例 ①:
20↙
100.5↙
http://c.biancheng.net↙
n=20, f=100.5, str=http://c.biancheng.net
输入示例 ②:
8920↙
10.2579↙
http://data.biancheng.net↙
n=89, f=10.25, str=http://data.biancheng.
这段代码使用了多个 scanf() 函数连续读取数据,为了避免受到缓冲区中遗留数据的影响,每次读取结束我们都使用 scanf("%*[^\n]"); scanf("%*c");来清空缓冲区。
限制读取数据的长度在实际开发中非常有用,最典型的一个例子就是读取字符串:我们为字符串分配的内存是有限的,用户输入的字符串过长就存放不了了,就会冲刷掉其它的数据,从而导致程序出错甚至崩溃;如果被黑客发现了这个漏洞,就可以构造栈溢出攻击,改变程序的执行流程,甚至执行自己的恶意代码,这对服务器来说简直是灭顶之灾。
在用 gets() 函数读取字符串的时候,有一些编译器会提示不安全,建议替换为 gets_s() 函数,就是因为 gets()不能控制读取到的字符串的长度,风险极高。

常用的连字符举例:
%[a-z]表示读取 abc...xyz 范围内的字符,也即小写字母;
%[A-Z]表示读取 ABC...XYZ 范围内的字符,也即大写字母;
%[0-9]表示读取 012...789 范围内的字符,也即十进制数字。
你也可以将它们合并起来,例如:
%[a-zA-Z]表示读取大写字母和小写字母,也即所有英文字母;
%[a-z-A-Z0-9]表示读取所有的英文字母和十进制数字;
 %[0-9a-f]表示读取十六进制数字。


 %[^\n]表示匹配除换行符以外的所有字符,遇到换行符就停止读取;
 %[^0-9]表示匹配除十进制数字以外的所有字符,遇到十进制数字就停止读取。

读取一行不能包含十进制数字的字符串,并且长度不能超过 30:
scanf("%30[^0-9\n]", str);


 %*d 表示读取一个整数并丢弃;
 %*[a-z]表示读取小写字母并丢弃;
 %*[^\n]表示将换行符以外的字符全部丢弃。

 

 

 

 
posted @ 2020-12-17 20:06  泥烟  阅读(347)  评论(0编辑  收藏  举报