算法学习笔记一 用scanf的输入
一、一行字符串的格式控制
在C++中一直采用的是cin、cout流,但是最近发现其实scanf和printf是很方便的,比如下面这道题:
其实是一道很简单的题,万万没想到竟然在输入这里卡了老半天。这道题输入的特点是:
①不定长;
②有规律,比如第一个数字一定是0,第三个一定是冒号;
③数字与符号相结合;
④字符串中出现了冒号;
⑤多行输入
综合以上,最佳的解决办法是:
int n; //组数
int hour;
int min;
int title;
for(int i = 0; i < n; i++ )
scanf("%d:%d 7-%d",&hour,&min,&title);
通过这一行代码,就轻松地进行了多行输入,"%d:%d 7-%d" 就是scanf存在的便捷性。
输出也是同样的方式:
for(int i = 0; i < n; i++ )
scanf("%d:%d",&hour,&min);
二、scanf函数的用法
下面进行一些用法的总结:
不要忘了加头文件:< stdio >
1. scanf(“输入控制符”, 输入参数);
功能:将从键盘输入的字符转化为“输入控制符”所规定格式的数据,然后存入以输入参数的值为地址的变量中。
int i;
scanf("%d", &i); //&i 表示变量 i 的地址,&是取地址符
2. scanf(“输入控制符非输入控制符”, 输入参数);
这也就是最上面那道题的用法,在 printf 中,所有的“非输出控制符”都要原样输出。同样,在 scanf 中,所有的“非输入控制符”都要原样输入,所以在输入的时候i=必须要原样输入。
3. 输入控制符
符号 | 含义 |
---|---|
%a | 读浮点值(仅适用于 C99) |
%A | 读浮点值(仅适用于 C99) |
%c | 读单字符 |
%d | 读十进制整数 |
%i | 读十进制、八进制、十六进制整数 |
%e | 读浮点数 |
%E | 读浮点数 |
%f | 读浮点数 |
%F | 读浮点数(仅适用于 C99) |
%g | 读浮点数 |
%G | 读浮点数 |
%o | 读八进制数 |
%s | 读字符串 |
%x | 读十六进制数 |
%p | 读指针值 |
%n | 至此已读入值的等价字符数 |
%u | 读无符号十进制整数 |
%[ ] | 扫描字符集合 |
%% | 读 % 符号(百分号) |
4.理解输入控制符
- %d 只识别“十进制整数”。对 %d 而言,空格、回车、Tab 键都是区分数据与数据的分隔符。当 scanf 进入缓冲区中取数据的时候,如果 %d 遇到空格、回车、Tab 键,那么它并不取用,而是跳过继续往后取后面的数据,直到取到“十进制整数”为止。对于被跳过和取出的数据,系统会将它从缓冲区中释放掉。未被跳过或取出的数据,系统会将它一直放在缓冲区中,直到下一个 scanf 来获取
- 如果将 %d 换成 %c,那么任何数据都会被当作一个字符,不管是数字还是空格、回车、Tab 键它都会取回
5. scanf_s()函数
scanf_s()函数是Microsoft公司VS开发工具提供的一个功能相同的安全标准输入函数,从vc++2005开始,VS系统提供了scanf_s()。在调用该函数时,必须提供一个数字以表明最多读取多少位字符。另外,很多带“_s”后缀的函数是为了让原版函数更安全,传入一个和参数有关的大小值,避免引用到不存在的元素,防止hacker利用原版的不安全性(漏洞)黑掉系统。简单的理解,就是scanf_s会比scanf更安全,那么为了安全也需要编程者多传一些参数,这些参数就是变量的长度(占用的字节数)。
对于整数和浮点数而言,和scanf()函数用法相同,对于基本的字符类型,也无需提供大小参数。
但是!在读取字符串的时候必须要提供一个要读取的字符串的大小!【OMG,因为这个报错了n次!】
char z[30];
scanf_s("%s", z,5);
printf("\n%s", z);
比方说我定义了一个30长度的字符数组,但是在读取的时候只给了一个5的长度,那么他最多只能读取4个字符,因为第五位要存放“\0”。
为了不浪费内存空间,第二个参数最好使用sizeof()。
char z[30];
scanf_s("%s", z,sizeof(z));
printf("\n%s", z);