scanf ()- 读取数据
格式
#include <stdio.h>
int scanf(const char *format-string, argument-list);语言级别
ANSI
线程安全
是
语言环境敏感
此函数的行为可能受当前语言环境的 LC_CTYPE 和 LC_NUMERIC 类别影响。 如果在编译命令中指定了 LOCALETYPE (*LOCALEUCS2) 或 LOCALETYPE (*LOCALEUTF) ,那么此行为也可能受当前语言环境的 LC_UNI_CTYPE 类别影响。 有关更多信息,请参阅 了解 CCSID 和语言环境。
描述
scanf() 函数将数据从标准输入流 stdin 读取到 argument-list中每个条目给定的位置。 每个 自变量 都必须是一个指向变量的指针,该变量的类型与 format-string中的类型说明符相对应。 format-string 控制输入字段的解释,是一个以初始移位状态开始和结束的多字节字符串。
- 空格字符,由
isspace()函数 指定 (例如空格和换行符)。 空格字符会导致scanf()函数读取但不存储输入中的所有连续空格字符,直到下一个非空格字符为止。 format-string 中的一个空格字符与输入中的任何空格字符组合相匹配。 - 非空格字符 (百分号字符 (%) 除外)。 非空格字符会导致
scanf()函数读取但不存储匹配的非空格字符。 如果stdin中的下一个字符不匹配,那么scanf()函数结束。 - 格式规范,由百分号 (%) 引入。 格式规范使
scanf()函数读取输入中的字符并将其转换为指定类型的值。 该值将分配给自变量列表中的自变量。
scanf() 函数从左到右读取 format-string 。 格式规范之外的字符应该与 stdin中的字符序列相匹配; 将扫描 stdin 中的匹配字符,但不会存储这些字符。 如果 stdin 中的字符与 format-string冲突,那么 scanf() 结束。 冲突字符将保留在 stdin 中,就像尚未读取该字符一样。
找到第一个格式规范时,将根据格式规范转换第一个输入字段的值,并将其存储在 argument-list中的第一个条目指定的位置中。 第二个格式规范会转换第二个输入字段,并将其存储在 argument-list中的第二个条目中,依此类推,直到 format-string结束。
输入字段定义为所有字符,直到第一个空格字符 (空格,制表符或换行符) ,直到第一个字符无法根据格式规范转换,或者直到达到字段 width (以先到者为准)。 如果格式规范的自变量过多,那么将忽略额外的自变量。 如果没有足够的参数用于格式规范,那么未定义结果。
格式规范具有以下格式:
格式规范的每个字段都是单个字符或表示特定格式选项的数字。 出现在最后一个可选格式字段之后的 type 字符确定是将输入字段解释为字符,字符串还是数字。 最简单的格式规范仅包含百分号和 类型 字符 (例如, %s)。
下面详细讨论了格式规范的每个字段。 如果百分号 (%) 后跟没有格式控制字符含义的字符,那么行为未定义。 此行为的一个例外是 %%。 要指定百分号字符,请使用 %%。
- 如果打印出一个指针并从同一个激活组中扫描回来,那么扫描回来的指针将与打印出来的指针进行比较。
- 如果
scanf()系列函数扫描由其他激活组输出的指针,那么scanf()系列函数会将该指针设置为 NULL。
有关使用 IBM® i 指针的更多信息,请参阅 ILE C/C++ Programmer 's Guide 。
百分号后面的星号 (*) 禁止分配下一个输入字段,这将解释为指定 类型的字段。 已扫描但未存储该字段。
width 是一个正十进制整数,用于控制要从 stdin读取的最大字符数。 转换不超过 width 个字符,并将其存储在相应的 自变量上。 如果在达到 width 之前出现空格字符 (空格,制表符或换行符) 或无法根据给定格式转换的字符,那么将读取少于 width 个字符。
可选大小修饰符 h , l , ll , L , H , D 和 DD 指示接收对象的大小。 如果对应的自变量是指向短整型的指针而不是指向整型的指针,那么转换字符 d , i 和 n 必须以 h 开头,如果它是指向长整型的指针,那么由 l 开头,如果它是指向长整型整型的指针,那么由 ll 开头。 类似地,如果对应的参数是指向无符号短整型的指针而不是指向无符号整型的指针,那么转换字符 o , u , x 和 X 必须以 h 开头,如果是指向无符号长整型的指针,那么由 l 开头,如果是指向无符号长整型的指针,那么由 ll 开头。 转换字符 a , A , e , E , f , F , g 和 G 必须前置 l (如果对应的自变量是指向双精度型而不是指向浮点型的指针) , L (如果是指向长整型双精度型的指针) , H (如果是指向 _Decimal32的指针) , D (如果是指向 _Decimal64的指针) 或 DD (如果是指向 _Decimal128的指针)。 最后,如果对应的自变量是指向 wchar_t 的指针,而不是指向单字节字符类型的指针,那么转换字符 c , s 和 [必须以 l 开头。 如果 h , l , L , ll , H , D 或 DD 与任何其他转换字符一起出现,那么行为未定义。
下表中包含 type 字符及其含义:
| 字符 | 期望的输入类型 | 参数类型 |
|---|---|---|
| 天 | 带符号十进制整数 | 指向 int 的指针。 |
| o | 无符号八进制整数 | 指向无符号整数的指针。 |
| x和 X | 无符号十六进制整数 | 指向无符号整数的指针。 |
| i | 十进制,十六进制或八进制整数 | 指向 int 的指针。 |
| u | 无符号十进制整数 | 指向无符号整数的指针。 |
| a , A , e , E , f , F , g 和 G | 对于非十进制浮点数,可选择带符号的浮点数、无穷大或 NaN, ,其格式与 strtod() 函数的预期格式相同。 对于十进制浮点数,可选择带符号的浮点数、无穷大或 NaN, ,其格式与 strtod64() 函数的预期格式相同。 |
指向浮点的指针。 |
| D (n , p) | 压缩十进制值,由可选符号 (+ 或-) 组成; 然后是非空的数字序列, (可选) 一个或多个十进制数字序列可能包含小数点,但不包含十进制后缀。 主题序列定义为输入字符串的最长初始子序列,以期望的格式从第一个非空格字符开始。 如果输入字符串为空或完全由空格组成,或者如果第一个非空格字符不是符号,数字或小数点字符,那么它不包含任何字符。 | 指向 decimal (n , p)的指针。 由于二进制编码十进制对象的内部表示与压缩十进制数据类型的内部表示相同,因此可以使用类型字符 D (n , p)。 |
| c | 字符; 通常跳过的空格字符在指定 c 时读取 | 指向对于输入字段足够大的字符的指针。 |
| 请 | 字符串 | 指向足以用于输入字段的字符数组的指针,加上自动追加的结束空字符 (\0)。 |
| n | 未从 流 或缓冲区读取任何输入 | 指向 int 的指针,将从 流 或缓冲区成功读取的字符数存储到对 scanf()的调用中的该点。 |
| p | 指向 void 的指针已转换为一系列字符 | 指向 void的指针。 |
| lc | 多字节字符常量 | 指向 wchar_t 的指针。 |
| ls | 多字节字符串常量 | 指向 wchar_t 字符串的指针。 |
要读取未由空格字符定界的字符串,请将方括号 ([]) 中的一组字符替换为 s (字符串) 类型字符。 相应的输入字段被读取到未出现在括号字符集中的第一个字符。 如果集合中的第一个字符是插入标记 (^) ,那么效果将相反: 输入字段将读取到在字符集的其余部分中出现的第一个字符。
要存储字符串而不存储结束空字符 (\0) ,请使用规范 %ac,其中 a 是十进制整数。 在此实例中, c 类型字符表示自变量是指向字符数组的指针。 下一个 字符将从输入流读取到指定位置,并且不会添加空字符。
%x 格式说明符的输入解释为十六进制数字。
scanf() 函数按字符扫描每个输入字段字符。 它可能会在到达空格字符之前,达到指定的 width 时或无法将下一个字符转换为指定的字符时停止读取特定输入字段。 当规范与输入字符发生冲突时,下一个输入字段从第一个未读字符开始。 如果存在冲突字符,那么该字符将被视为未读字符,并且是下一个输入字段的第一个字符或 stdin上后续读操作中的第一个字符。
对于 %lc 和 %ls ,指定读取的数据是多字节字符串,并转换为宽字符,就像调用 mbtowc一样。
对于 %a , %A , %e, %E , %f, %F , %g和 %G 格式说明符,字符序列INFINITY或NAN允许 (忽略大小写) ,并分别生成值 INFINITY 或 Quiet Not-A-Number (NaN)。
作为替代方法,可以使用上面图中概述的格式规范来分配自变量列表中的特定条目。 在对 scanf()的同一调用中,不能混合此格式规范和先前的格式规范。 否则,可能会发生不可预测的结果。
arg-number 是正整数常量,其中 1 引用自变量列表中的第一个条目。 自变量数不能大于自变量列表中的条目数,否则结果未定义。 Arg-number 也不能大于 NL_ARGMAX。
返回值
scanf() 函数返回已成功转换和分配的字段数。 返回值不包含已读取但未分配的字段。
如果未执行转换,那么对于尝试在文件结束时读取的操作,返回值为 EOF 。 返回值 0 表示未指定任何字段。
错误条件数
如果要分配到的自变量的类型与格式规范不同,那么可能会出现不可预测的结果。 例如,读取浮点值,但将其分配到类型为 int的变量中是不正确的,并且会产生不可预测的结果。
如果参数多于格式规范,那么将忽略额外的参数。 如果没有足够的参数用于格式规范,那么未定义结果。
如果格式字符串包含无效的格式规范,并且正在使用位置格式规范,那么 errno 将设置为 EILSEQ。
如果使用了位置格式规范并且没有足够的自变量,那么 errno 将设置为 EINVAL。
如果发生转换错误,那么可以将 errno 设置为 ECONVERT。
示例
#include <stdio.h>
int main(void)
{
int i;
float fp;
char c, s[81];
printf("Enter an integer, a real number, a character "
"and a string : \n");
if (scanf("%d %f %c %s", &i, &fp, &c, s) != 4)
printf("Not all fields were assigned\n");
else
{
printf("integer = %d\n", i);
printf("real number = %f\n", fp);
printf("character = %c\n", c);
printf("string = %s\n",s);
}
}
/***************** If input is: 12 2.5 a yes, *******************
************** then output should be similar to: ****************
Enter an integer, a real number, a character and a string :
integer = 12
real number = 2.500000
character = a
string = yes
*/
#include <stdio.h>
int main(void)
{
int number;
printf("Enter a hexadecimal number or anything else to quit:\n");
while (scanf("%x",&number))
{
printf("Hexadecimal Number = %x\n",number);
printf("Decimal Number = %d\n",number);
}
}
/*************** If input is: 0x231 0xf5e 0x1 q, ****************
**************** then output should be similar to: **************
Enter a hexadecimal number or anything else to quit:
Hexadecimal Number = 231
Decimal Number = 561
Hexadecimal Number = f5e
Decimal Number = 3934
Hexadecimal Number = 1
Decimal Number = 1
*/
stdin 中读取数据,并使用备用位置格式字符串来分配数据。#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
char s[20];
float f;
scanf("%2$s %3$f %1$d",&i, s, &f);
printf("The data read was \n%i\n%s\n%f\n,i,s,f);
return 0;
}
/*************** If the input is : test 0.2 100 *****************
************** then the output will be similar to: ***************
The data read was
100
test
0.20000
*/
--------------------------------------------------------------------
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
void main(void)
{
wchar_t uString[20];
setlocale(LC_UNI_ALL, "");
scanf("Enter a string %ls",uString);
printf("String read was %ls\n",uString);
}
/* if the input is : ABC
then the output will be similiar to:
String read was ABC
*/
