scanf()使用注意事项

以下是对scanf()函数的总结,有些部分来源于C Primer Plus。
scanf()的优势:
相比于其他的接收输入的函数,getchar()接收单个字符,get()和fget()只能接收字符串,而scanf()能接收混合格式的输入。
scanf()的劣势:
C编译器不会检查引号中格式说明符的是否匹配后面的参数

空白字符
1.除了%c,对于其他的所有格式说明符,scanf()会跳过所有空白字符(包括空格、制表符、换行符)
2.举个例子,输入 -13.45e12# 0 

scanf("%d", &ch);
printf("%d", ch);

scanf()首先会跳过缓冲区中的任何空白字符,随后遇到负号-。
而格式说明符%d的含义是将输入解释成有符号的十进制整数,于是scanf找到了一个负号 - ,保存该字符,然后读取下一个字符,如果下一个字符是数字,保存该字符并读取下一个字符。
当遇到一个非数字字符,它会认为已经读到了整数的末尾。然后scanf()会把这个字符放回到输入。程序在下一次读取输入的时候,首先会读取到上一次读取丢弃的字符小数点 ‘.’ 。

3.如果scanf()中有多个%d,那么当第一个%d丢弃小数点后会发生什么情况呢

scanf("%d%d", &ch1, &ch2);
printf("ch1=%d, ch2=%d", ch1, ch2);

书中说到,C规定在第一个出错处停止读取输入,也就是说其他变量的读取会一直卡在小数点这个地方。之后发生了什么我不太清楚,总之除了第一个ch1,后面的变量的值都不是期望得到的值。
再给一个更多变量的例子

scanf("%d%d%d%d", &ch1, &ch2, &ch3, &ch4);
printf("ch1=%d, ch2=%d, ch3=%d, ch4=%d", ch1, ch2, ch3, ch4);

%s

scanf()会把跳过所有空白,读取-13.45e12#,而空格会留在输入中,作为下一次输入的首字符。如果用字符数组存储字符串-13.45e12#,scanf()会在字符串末尾自动加上空字符 ‘\0’ ,所以在计算字符数组的时候记得算上‘\0’的位置

5.再来看一种情况,看下scanf()在有字段宽度的%s中,是否会读取字符串之间的空格

char ch1[20]={'a'}, ch2[20]={'a'};
scanf("%12s", ch1, ch2);
printf("\nch1=%s\n", ch1);
printf("ch2=%s\n", ch2);

可以看到,无法通过指定字段宽度,来实现跳过字符串之间的空格

%c

scanf()会读取当前输入中还剩下的第一个字符,无论这个字符是什么(也就是说可能读入换行符等奇怪🤔的字符)
因此,如果想跳过字符前的空格,或是换行符,常使用getchar()来跳过字符
另外,还有进阶的玩法,在%c前添加空格或是换行符,此时scanf()会跳过所有的空格(换行符)

char ch={'a'};
scanf("\n%c", &ch);
printf("\nch=%c\n", ch);

没有加\n的情况,输入“\n66”

char ch={'a'};
scanf("%c", &ch);
printf("\nch=%c\n", ch);
//printf("ch2=%s\n", ch2);

缓冲区

以下直接摘录一段书中的话
“回显用户输入的字符后立即重复打印该字符是属于无缓冲输入,即正在等待的程序可立即使用输入的字符。
在用户在用户按下Enter前不会重复打印刚输入的字符,这种输入形式属于缓冲输入。用户输入的字符被收集并存储在一个被称为缓冲区的临时存储区。
ANSI C规定输入是缓冲的。
缓冲分两类。完全缓冲I/O,常见于文件输入,指缓冲区被填满时才刷新缓冲区。行缓冲I/O,指出现换行符时刷新缓冲区。”

添加普通字符
最近才发现,在格式字符串中输入任意普通字符,scanf()会跳过这个字符,接收该字符后面的内容

scanf("_%c", &ch);
printf("\nch=%c\n", ch);

但是这个只能跳过一次

char ch[10];
scanf("/%s", ch);
printf("\nch=%s\n", ch);

前面说的空格、换行符、制表符除外,对于它们,C会跳过所有的空白字符(对于%c也一样)
此外,符号 / 也除外

char ch;
scanf(" %c", &ch);
printf("\nch=%c\n", ch);

参考链接:https://blog.csdn.net/night_152/article/details/114993287

posted @ 2021-07-05 00:00  余生以学  阅读(520)  评论(0编辑  收藏  举报