【C语言学习】scanf函数

一、定义与基本用法

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...,感兴趣的小伙伴可以翻看我的其他博客。

相关推荐
淮北4941 小时前
STL学习(十一、常用的算数算法和集合算法)
c++·vscode·学习·算法
月光有害1 小时前
PL-0功能拓展及基于VSCode的IDE配置
ide·vscode·编辑器
R-G-B2 小时前
【12】大恒相机SDK C#开发 ——多相机开发,枚举所有相机,并按配置文件中的相机顺序 将所有相机加入设备列表,以便于对每个指定的相机操作
c#·大恒相机sdk·大恒多相机开发·大恒多相机枚举·大恒多相机指定顺序
R-G-B2 小时前
【13】大恒相机SDK C#开发 —— Fom1中实时处理的8个图像 实时显示在Form2界面的 pictureBox中
c#·大恒相机sdk·图像实时显示在另一个界面
_Kayo_4 小时前
VUE2 学习笔记14 nextTick、过渡与动画
javascript·笔记·学习
天若有情6735 小时前
【python】Python爬虫入门教程:使用requests库
开发语言·爬虫·python·网络爬虫·request
哪 吒6 小时前
OpenAI放大招:ChatGPT学习模式上线,免费AI智能家教
人工智能·学习·ai·chatgpt·gemini·deepseek
寒水馨6 小时前
Java 17 新特性解析与代码示例
java·开发语言·jdk17·新特性·java17
启山智软6 小时前
选用Java开发商城的优势
java·开发语言