一、定义与基本用法
scanf英文名全称scan format,即格式化扫描的意思,他的基本用法是读取用户的键盘输⼊,存给变量。它与printf函数的关系可以用以下图表示:
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int score = 0;
printf("请输入成绩:");
scanf("%d", &score);
printf("成绩是:%d\n", score);
return 0;
}
运行结果:
程序运行到scanf语句时,会停下来,等待用户从键盘输入相应数值。用户输⼊数据、按下回⻋键后,scan函数就会处理用户的输入,存入变量。它的语法跟printf函数类似,使用时也需要包含头文件<stdio.h>。
由于scanf函数传递的不是值,而是地址,因此,变量的前面要加上&(取地址,如果变量是指针,则不需要加)。
格式化字符串中可以有多少个占位符,对应的就会有多少个变量,例如:
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int i, j;
float x, y;
scanf("%d%d%f%f", &i, &j, &x, &y);
printf("i=%d, j= %d, x=%f, y=%f\n", i, j, x, y);
return 0;
}
运行结果:
上述代码中,格式字符串%d%d%f%f ,分别表示输入的前两个是整数,后两个是浮点数。
scanf函数处理数值占位符时,会自动过滤空白字符,包括空格制表符、换行符等。所以,输⼊的数据之间,有⼀个或多个空格不影响scanf函数解读数据,用户使用回车键,将输入分成几行,也不影响解读。
scanf函数在解读用户输入时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为止。
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int x = 0;
float y = 0.0;
scanf("%d", &x);
scanf("%f", &y);
printf("x=%d y=%f\n", x, y);
return 0;
}
运行结果:
上述代码中,scanf函数第一次读取用户输⼊时,%d占位符会忽略开头的空格,从-处开始获取数据,读取到-13停下来,因为后⾯的.不属于整数的有效字符。这就是说,占位符%d会读到-13,打印出来的结果就是x=-13。
第⼆次调用scanf函数,就会从上一次停下来的地方继续往下读取。这⼀次读取的首字符是.,由于对应的占位符是%f,因此会读取到.45e12(#不是浮点数有效字符,不满足条件),这是采用科学计数法的浮点数格式,转换成小数就是450000000000(没办法在内存里面精确存储)。
二、VS编译器使用scanf函数报错及解决措施
对于VS编译器使用scanf函数会报错的问题以及相应的解决措施,可以翻看我之前写过的一篇文章:解决VS编译器scanf函数报错问题
三、scanf函数返回值
scanf函数的返回值是整数,表示读取到的数据个数。如果没有读取任何项,或者匹配失败,则返回0。如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到文件结尾,则返回常量EOF(EOF:end of file文件结束的标志,值为-1)。
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
float f = 0.0f;
int r = scanf("%d %d %f", &a, &b, &f);
printf("a=%d b=%d f=%f\n", a, b, f);
printf("r = %d\n", r);
return 0;
}
运行结果:
上述代码中,r值是2,表示正确读取了2个数值。
四、占位符
scanf占位符与printf基本一致,但在scanf函数使用%c时,不会忽略空白字符,要强制跳过字符前的空⽩字符,可以写成scanf(" %c",&ch),即%c前加上⼀个空格,表表示跳过零个或多个空白字符。
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char ch = '0';
scanf("%c", &ch);
printf("%c", ch);
printf("xxxx");
return 0;
}
运行结果:
%s占位符:从第一个非空白字符起,一直读到下一个空白字符为止。
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char arr[20] = { 0 };
scanf("%s", arr);
printf("%s", arr);
return 0;
}
运行结果:
从上述代码可以看出,%s不会包含空⽩字符,所以读取读取多个单词,除⾮多个%s ⼀起使用,scanf函数不适合读取可能包含空格的字符串。另外,%s占位符会在字符串变量末尾存储⼀个空字符\0。
scanf函数将字符串读入字符数组时,不会检测字符串是否超过了数组⻓度,所以,储存字符串时, 可能会超过数组的边界(scanf函数不安全的地方)。为防止出现这种情况,使用%s占位符时,指定读⼊字符串的最大长度,即写成%[m]s。
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char arr[5] = { 0 };
scanf("%4s", arr);
printf("%s", arr);
return 0;
}
运行结果:
五、赋值忽略符
如果我们不按照规定格式输入数值,scanf函数就会解析失败:
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d-%d-%d", &year, &month, &day);
printf("year=%d month=%d day=%d\n", year, month, day);
return 0;
}
运行结果:
如果以1993 10 5这种格式输入,解析会,为了避免这种情况,只需要把*(赋值忽略符)加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃。
修改后的代码:
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d%*c%d%*c%d", &year, &month, &day);
printf("year=%d month=%d day=%d\n", year, month, day);
return 0;
}
运行结果:
关于printf函数和scanf函数的介绍就到这里,除了他们两个以外,C语言函数还有很多,像是strcpy、sizeof、strcmp...,感兴趣的小伙伴可以翻看我的其他博客。