目录
1.定义
scanf()用于读取用户的键盘输入
使用前加上
#include <stdio.h>
2.基础用法
int n=0;
scanf("%d",&n);
7点注意
1.scanf() 传递的是地址,必须取地址&n ,如果这里的变量是指针变量(比如字符串变量),那就不用加& ;
char arr[5]={0};
scanf("%s",arr);
数组名就是地址
如果想一次性输入多组值
scanf("%d %f %lf %d",a,b,c,d);
2.scanf() 处理数值占位符时,除了%c之外,会自动过滤空白字符,包括空格、制表符、换行符等.因此用户输入的数据之间有一个或多个空格不影响scanf解读数据;另外,用户使用回车键,将输入分成几行,也不影响解读
如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch); 即%c前加上一个空格表
示跳过零个或多个空白字符
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 0;
float b = 0;
double c = 0;
int d = 0;
scanf("%d %f %lf %d",& a,& b, &c, &d);
printf("%d %f %lf %d", a, b, c, d);
return 0;
}
3.scanf函数的占位符后面一般不会加\n,\n 是换行,一般在输出的时候才使用
4.scanf函数中指定的格式和给程序输入的数据格式要严格的匹配,否则可能不能得到想要
的值
#include <stdio.h>
int main()
{
int a, b, c = 0;
scanf("%d,%d,%d", &a, &b, &c);
printf("%d %d %d", a, b, c);
return 0;
}
★5.scanf和printf占位符不一样的地方
printf:%f既可以打印float类型,也可以打印double类型
scanf:%f用于float类型,%lf用于double类型
6.特殊占位符%[]
在方括号中指定一组匹配的字符(比如%[0-9]),遇到不在集合之中的字符,匹配将会停止
7.%s的特别说明
从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止
%s 的读取不会包含空白字符,所以无法用来读取多个单词,除非多个%s 一起使用;即scanf不适合读取可能包含空格的字符串; scanf() 遇到%s占位符,会在字符串变量末尾存储一个\0字符
3.工作原理
用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读,解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int x=0;
float y=0;
scanf("%d", &x);
printf("%d\n", x);
scanf("%f", &y);
printf("%f\n", y);
return 0;
}
类似0.45这样的小数计算机不会准确存储
4.返回值
返回整数,表示成功读取的变量个数;如果没有读取任何项,或者匹配失败,则返回0 ;如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF (-1)。
EOF - end of file 文件结束标志
可定义变量来接收返回值
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int c = 0;
int tmp= scanf("%d%d%d", &a,&b,&c);//这里做了两步,1.读取a,b,c 2.将返回值赋值给tmp
printf("%d", tmp);
return 0;
}
不同情况返回值不同,可用于判断是否正常读取值
5.占位符
%c :单个字符。
%d :整数。
%f : float 类型浮点数。
%lf : double 类型浮点数(l小写)。
%Lf : long double 类型浮点数(L大写)。
%s :字符串。
%[] :在方括号中指定一组匹配的字符(比如%[0-9] ),遇到不在集合之中的字符,匹配将会
停止
注意:1.上面所有占位符之中,除了%c 以外,都会自动忽略起首的空白字符,%c 不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
char a =0;
scanf("%c",&a);
printf("%c",a);
return 0;
}
*如果要强制跳过字符前的空白字符,可以写成scanf(" %c", &ch) ,即%c 前加上一个空格,表
示跳过零个或多个空白字符
2.scanf()有缺陷,读取数据的时,不会看目标空间是否能存的下数据
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
char arr[5] = { 0 };
scanf("%s", arr);
printf("%s", arr);
return 0;
}
输入123abcd后
变量周围的堆栈已损坏
但是仍然可以正常打印
3.%s从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
char arr[5] = { 0 };
scanf("%s", arr);
printf("%s", arr);
return 0;
}
原因加了\0
4.解决第2点缺陷可以指定读入字符串的最长长度,即写成%[m]s ,其中的[m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃
如
scanf("%10s", arr);
6.赋值忽略符
有时,用户的输入可能不符合预定的格式
写一个输入年月日,再按一种格式输出年月日的程序
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d %d %d", &year, &month, &day);
printf("%d-%d-%d\n", year, month, day);
return 0;
}
输出的格式发生了改变,原因是scanf当成2024,-7,-19读取了
修改后:
scanf("%d-%d-%d", &year, &month, &day);
问题解决
但是如果输入的年月日中间的分隔符换成其他形式:
无法正常读取
所以引入赋值忽略符:只要把* 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃
修改后:
scanf("%d%*c%d%*c%d", &year, &month, &day);
年月日中间的分隔符改成任意形式都能正常打印
7.指定字段的最大宽度
最大字段宽度;在达到最大字段宽度或者遇到第一个空白字符时(不管哪个先发生都一样)停止对输入项的读取
scanf("%4d%2d",®,&month);
printf("%d",reg);
printf("%d",&month);
8.思考题
scanf中一定要写&吗?
不一定,只要是地址就可以,如下方代码
int arr[3] = {0};
scanf("%d",arr);
9.VS认为scanf不安全的原因
前面提到过,在VS中使用scanf函数前,需要添加 #define _CRT_SECURE_NO_WARNINGS 代码,原因是scanf将字符串读入字符数组时,不会检测字符串是否超过了数组长度,存储字符串是可能会越界,建议使用%[m]s来指定读取的字符串的最大长度m,超过长度m的剩余字符将被忽略,不再读取
char arr[10];
scanf("%9s",arr);//%9s:留一个元素用来供scanf来填充\0