一、scanf函数的介绍
下面展示来自cplusplus.com网站的scanf函数的定义
翻译过来是这样的: scanf 函数用于从 标准输入(通常是键盘) 读取数据。它根据提供的 格式(format) 字符串来解析输入,并把解析后的数据存储到指定的变量中。这些变量的地址作为 scanf 的附加参数传递,并且它们应该已经被分配了内存,类型与格式字符串中指定的格式说明符相匹配。
补充: scanf函数位于 <stdio.h> 库中,使用scanf函数前必须包含 <stdio.h>
scanf的语法定义
int scanf( const char * format, ... );
关于scanf函数中的format参数
format: 一个格式字符串,指定了输入值的预期类型和顺序。格式字符串中可以包含普通字符和格式说明符。普通字符必须与输入中相应的字符完全匹配,而格式说明符则指定了预期的输入类型(如整数、浮点数等)。
在程序中我们可以这样表达format
%[*][width][length]specifier(格式说明符)
后面与格式对其的数据必须是数据的地址
格式说明符: 格式说明符以 % 开头,后跟一个或多个字符来指定输入类型,类似与printf函数中的参数。下面表格中是基本的格式说明符:
格式说明符 | 作用 |
---|---|
%d or %i | 读取一个整型数据(int) |
%ld | 读取一个长整形 |
%lld | 读取一个长长整形 |
%c | 读取一个字符型数据(char) |
%f | 读取一个单精度浮点型数据(float) |
%lf | 读取一个双精度(double) |
%s | 读取一串字符串 |
%u | 读取一个无符号的整形数据(unsigned int) |
%o | 读取一个八进制整数 |
%e or %E | 读取一个科学计数法表示的浮点型数据 |
%g or %G | 读取一个浮点型数据,根据输入的浮点数自动识别为%f或%e |
%p | 读取一个指针类型数据 |
%n | 不读取输入,而是将到目前为止成功读取的字符数存储在相应的变量中 |
%a or %A | 读取一个十六进制表示的浮点数(C99标准中引入) |
%[] | 读取一系列字符,直到遇到字符集外的内容[ ]中的内容是字符集 |
%* | 忽略下一项的输入不读取 |
注意事项:length则是h、l、ll等对格式说明符的修饰
scanf的返回值
我们可以查看cplusplus.com网站中的scanf的返回值的介绍
我们可以对其简单翻译
- 成功读取:
如果 scanf 成功读取并存储了数据,它将返回成功读取的项数。这个数字可能小于或等于您在格式字符串中指定的项数。 - 错误处理:
如果在读取过程中遇到错误,如输入不匹配预期的格式,scanf 将停止读取并返回已成功读取的项数。
如果在任何数据成功读取之前就到达文件末尾或发生读取错误,scanf 将返回 EOF(-1)。 - 编码错误: 在处理宽字符时,如果输入的字符序列不符合预期的编码格式,scanf 将设置 errno 为 EILSEQ 以指示发生了非法的字节序列错误。
二、scanf的使用细节
1.scanf函数与输入缓冲区
scanf函数是一个功能十分强大的函数,键盘是我们的输入设备,但是scanf函数并不是直接从键盘读取数据直接存入到变量的内存块中,而是会经过读取流,再存入到数据内存块中。 我们可以通过下面的图表示其关系
键盘输入数据,存入到输入缓存区,然后scanf再读取缓存区的数据到指定的变量中
-
输入缓冲区: scanf 会从输入缓冲区中读取数据,如果输入不匹配,可能会导致输入缓冲区中留下未处理的数据。
-
安全性: scanf 不会自动检查缓冲区溢出,因此如果输入的数据超过了变量的大小,可能会导致程序崩溃。建议使用 fgets 和 sscanf 等更安全的函数。
2.%[width]c 与 %[width]s 的差别
在使用%c 与%s 对字符与字符串的读取时,我们可以选择通过使用 %[width]c or %[width]s 来控制读取字符串的长度,width是读取的长度,我们可以举例以下代码简单说明。
#include <stdio.h>
int main() {
char str1[10] = { '1','1' ,'1' ,'1','1' ,'1' ,'1' ,'1' ,'1' ,'1' };
scanf("%5s", str1);
char str2[10] = { '1','1' ,'1' ,'1','1' ,'1' ,'1' ,'1' ,'1' ,'1' };
scanf("%5c", str2);
return 0;
}
我们可以得到以下结果
我们可以观察到,使用 %5s 与 %5c 程序都读取了5个字符到数组中,但是 %5s 与%5c不同的是,%5c在读取完5个字符后会在字符串的结尾添加一个'\0'作为字符串的结束标志,但是%5c是没有的,所以我们在用%c读取数据作为字符串时要注意加上'\0'
3. scanf函数的读取细则
在 C 语言中,scanf 函数在处理某些格式说明符时会跳过空白字符。空白字符:空格、制表符(\t)、换行符(\n)等
下面我们对scanf对整型的读取举个例子
#include <stdio.h>
int main() {
int num1 = 0;
int num2 = 0;
scanf("%d", &num1);
scanf("%d", &num2);
printf("%d\n", num1);
printf("%d\n", num2);
return 0;
}
我们先输入一串空格,再输入10
再输入20
我们可以观察到以下结果
可以观察到scanf越过了空格
下面我们对scanf对字符型的读取举个例子
#include <stdio.h>
int main() {
char c;
scanf("%c", &c);
printf("%c\n", c);
return 0;
}
下面我们通过调试查看c的值
我们可以观察到,scanf读取了空格,所以使用 %c 格式说明符时,scanf 不会跳过空白字符。它会读取下一个可用的字符,无论它是不是空白字符。
下面是总结
- %s: 当使用 %s 格式说明符读取字符串时,scanf 会跳过任何前导空白字符,然后开始读取字符,直到遇到下一个空白字符或输入结束。
- %d、%i、%u、%x 等: 当读取整数时,scanf 也会跳过前导空白字符,然后开始- 读取数字。如果输入中包含非数字字符(除非它们紧随数字之后,如在科学记数法中),scanf 将停止读取并返回已成功读取的项数。
- %f、%lf、%e 等: 在读取浮点数时,scanf 同样会跳过前导空白字符,然后开始读取数字和小数点。
- %c: 使用 %c 格式说明符时,scanf 不会跳过空白字符。它会读取下一个可用的字符,无论它是不是空白字符。
- %[…]: 当使用字符集合格式说明符时,scanf 会跳过前导空白字符,然后开始读取匹配字符集合的字符序列。
End
对于scanf函数的介绍我们就讲到这里,scanf函数是一个非常强大的函数,不止这些使用的方法与细则,但是博主的知识有限,只能介绍到这里,如有讲错的地方,请各位大佬指正,同时我也希望我的文章对各位有所作用!谢谢大家的阅读!