C语言的格式化输入函数scanf
来源:互联网 发布:sql的delete语句 编辑:程序博客网 时间:2024/05/22 05:30
scanf
是C语言的标准输入输出库stdio
中提供的库函数,所以在使用它时,需要使用预处理指令#include <stdio.h>
包含stdio.h
头文件。
scanf
的功能是根据由格式化字符串表示的特定格式读取输入。输入参数包括格式化字符串和用以存储输入的变量地址。变量地址(指针)的个数没有限制,但要保证格式化字符串中的转换说明的数量和类型与对应位置的输入变量一致。
scanf(格式化字符串, 变量地址1,变量地址2...)
格式化字符串中包含普通字符和转换说明。调用scanf
函数时,从左边开始依次处理格式化字符串中的信息。
格式化字符串中的普通字符
处理格式化字符串中的普通字符时,scanf
函数的处理方式因字符为空白字符而不同:
- 空白字符。如果在格式化字符串中遇到一个或多个连续空白字符,
scanf
函数会从输入缓冲区中重复读空白字符,直到遇到一个非空白字符为止,并且把该非空白字符放回输入缓冲区,供下次读取。
/************************************ * using_scanf_1.c * * * * 格式化字符串的空白字符 * ************************************/#include <stdio.h>int main(){ int x1 = 0; scanf(" %d", &x1); int x2 = 0; scanf(" %d", &x2); int x3 = 0; scanf("%d", &x3); printf("x1 = %d, x2 = %d, x3 = %d\n", x1, x2, x3); return 0;}
- 其他字符。如果在格式化字符串中遇到一个非空白字符,scanf
函数将把它与下一个输入字符进行比较。如果两者匹配,则放弃输入字符并继续处理格式化字符串的后续内容;若不匹配,则将该字符放回输入缓冲区,异常退出,不继续处理剩下的格式化字符串。
/********************************* * using_scanf_2.c * * * * 格式化字符串中的非空白字符 * *********************************/#include <stdio.h>int main(){ int x1 = 0; scanf("x1 = %d", &x1); printf("x1: %d\n", x1); /********************************** *scanf函数执行完成后,会忽略最后 * *的换行符,留由下一次scanf调用时 * *读取。因此这里调用scanf函数时第 * *一个字符为\n,所以要把\n作为转换* *说明中的第一个字符 * **********************************/ scanf("\nx1 = %d", &x1); printf("x1: %d\n", x1); return 0;}
上例子在为x1读入第二个值时,期望的形式是x1 = 30
,但却直接输入30,因此scanf
异常退出,x1
值不变。
格式化字符串中的转换说明
scanf的格式说明的通用格式为%<*><m><L>X
。
- 转换说明符X。用于scanf的转换说明符及其意义如下表:
d
匹配十进制整数,对应的变量地址为指向int型值 i
匹配整数,对应的变量地址指向int型值。若输入数据以0
开头则以八进制格式读入,若输入数据以0x
或0X
开头,则以十六进制读入,否则以十进制读入。 o
匹配八进制整数,对应的变量地址指向unsigned int型值 u
匹配十进制整数,对应的变量地址指向unsigned int型值 x,X
匹配十六进制整数,对应的变量地址指向unsigned int型值 e,E,f,g,G
匹配float型,对应的变量地址执行float型值 s
匹配一个非空字符序列,并在末尾添加空字符,对应的变量地址指向字符串 [
匹配来自匹配集合的非空字符序列,并在末尾添加空字符,对应的变量地址指向字符串。匹配集合的形式为%[集合]
,表示输入字符必须是集合中声明的字符,还有一种形式%[^集合]
,表示输入字符不能是集合中声明的字符 c
如果指定了最大字符宽度m, 则匹配m个字符,否则匹配一个字符。对应的变量地址指向字符 p
匹配printf
函数可以写出的格式的指针值,对应的变量地址指向void *
类型值 n
把目前为止读入的字符数量存储在此变量中。 %
匹配字符%/******************************************* * using_scanf_6.c * * * * 转换声明中的转换声明符 * *******************************************/#include <stdio.h>int main(){ int x1 = 0; scanf("%d", &x1); printf("x1 = %d\n", x1); int x2 = 0; int x3 = 0; int x4 = 0; scanf("\n%i,%i,%i", &x2, &x3, &x4); printf("x2 = %i, x3 = %i, x4 = %i\n", x2, x3, x4); unsigned int x5 = 0; scanf("\n%o", &x5); printf("x5 = %d\n", x5); unsigned int x6 = 0; scanf("\n%u", &x6); printf("x6 = %d\n", x6); unsigned int x7 = 0; scanf("\n%x", &x7); printf("x7 = %d\n", x7); unsigned int x8 = 0; scanf("\n%X", &x8); printf("x8 = %d\n", x8); float x9 = 0.0f; scanf("\n%f", &x9); printf("x9 = %f\n", x9); char x10[10] = ""; scanf("\n%s", x10); printf("x10 = %s\n", x10); char x11[10] = ""; scanf("\n%[123]", x11); printf("x11 = %s\n", x11); char x12; scanf("\n%c", &x12); printf("x12 = %c\n", x12); char x13[2] = ""; scanf("\n%2c", x13); printf("x13_1 = %c, x13_2 = %c\n", x13[0], x13[1]); printf("%p\n", x13); char *p = NULL; scanf("\n%p", &p); printf("x13_1 = %c\n", p[0]); int num = 0; scanf("\n%d%d%n", &x1, &x2, &num); printf("num = %d\n", num); int x14 = 0; scanf("\n%%%d", &x14); printf("x14 = %d\n", x14); return 0;}
- 长短整型标记
L
,h,l,L
中的一个,可选。当读取整数时,h
表示对应的变量地址指向short
型整数值,l
说明对应的变量地址指向long
型整数值。当读取浮点数时,l
说明对应的变量地址指向double
型值,L
说明对应的变量地址指向long double
型值。
/***************************************** * using_scanf_5.c * * * * 转换说明中的长短整型标记 * *****************************************/#include <stdio.h>int main(){ short x1 = 0; long x2 = 0; double x3 = 0.0; long double x4 = 0.0; scanf("%hd,%ld,%lf,%Lf", &x1, &x2, &x3, &x4); printf("x1 = %hd, x2 = %ld, x3 = %f, x4 = %Lf\n", x1, x2, x3, x4); return 0;}
- 最大字段宽度
m
,可选。限制输入项的字符数量,达到最大值则此数据项的转换结束,不包括转换开始跳过的空白字符。
/****************************************** * using_scanf_4.c * * * * scanf转换说明的最大字符宽度 * ******************************************/#include <stdio.h>int main(){ int x1 = 0; int x2 = 0; scanf("%5d,%5d",&x1, &x2); printf("x1 = %d, x2 = %d\n", x1, x2); return 0;}
- 字符
*
,可选。用以赋值屏蔽:读入此数据项,但不把它赋值给变量,也不包含在scanf
函数返回的计数中。
/************************************ * using_scanf_3.c * * * * 转换声明中的赋值屏蔽符* * ************************************/#include <stdio.h>int main(){ int x1 = 0; int x2 = 0; int num = scanf("%*d, %d, %d", &x1, &x2); printf("x1 = %d, x2 = %d, num = %d\n", x1, x2, num); return 0;}
处理格式化字符串中的转换说明时,scanf
函数跳过输入缓冲区中必要的空格,定位适当类型的项,然后读入数据项存储于相应的变量地址。若读入成功,则继续处理后续的格式化字符串,否则立即返回,不再查看格式化字符串的剩余部分。
当转换声明指定要输入的变量为数时,scanf
函数会忽略空白字符(包括空格符,横向和纵向制表符,换页符和换行符)。因此数值开以放在一行或多行内输入。
- 读入整数。当要求读入整数时,
scanf
函数首先找到一个数字、正号或负号,然后继续读取数字知道遇到非数字的符号为止。 - 读入浮点数。当要求读入浮点数时,
scanf
函数首先会找到一个数字、正号或符号,然后继续读取一串数字,最后读取由e
或E
和正负号、数字构成的指数。
scanf
函数执行完后,会忽略最后的换行符,留由下一次scanf
函数作为首个符号读取。
scanf
的可能错误及检测
scanf
的返回值说明了存储的数据项的个数,可以根据期望的返回值和实际的返回值之间的比较检测是否发生了输入错误。
scanf
的错误包括三种可能情况:
- 文件末尾。在完全匹配格式化字符串前遇到了文件结尾。
- 错误。程序的其他部分发生了错误。
- 匹配失败。数据项格式错误。
当scanf函数返回小于预期值时,可以使用feof和ferror函数检测问题。若feof返回非零值,则说明输入达到了文件的末尾。如果ferror返回非零值,则表示在输入过程中出现了错误。如果两个都为0,则一定是发生了匹配错误。
/************************************** * using_scanf_7.c * * * * scanf的可能错误及检测 * **************************************/#include <stdio.h>int main(){ int x1 = 0; int num = scanf("x1 = %d", &x1); printf("期望输出1,实际输出%d\n", num); int isEOF = feof(stdin); int hasError = ferror(stdin); printf("是否文件结尾标识: %d\n", isEOF); printf("是否存在错误标识: %d\n", hasError); printf("x1 = %d\n", x1); return 0;}
调用scanf
函数是读取数据的一种有效但不理想的方法,更稳妥的方法是采用字符格式读取所有数据,再将其转换为数值形式。
参考文献
- K.N. King 著,吕秀峰 译. C语言程序设计-现代方法. 人民邮电出版社
- C语言的格式化输入函数scanf
- C语言scanf()函数:格式化输入函数
- C语言scanf()函数:格式化输入函数
- C语言中scanf格式化输入函数
- C语言中scanf格式化输入函数
- C语言中scanf格式化输入函数
- C语言中scanf格式化输入函数
- c中scanf的格式化输入函数
- C语言之格式化输入(printf函数和scanf函数)
- scanf函数格式化输入
- C语言的scanf输入
- C语言--格式化输入/输出函数(printf/scanf,fprintf/fscanf,sprintf,sscanf)
- C语言中scanf函数输入回车符的问题
- C语言中scanf函数输入回车符的问题
- C语言中scanf函数输入回车符的问题
- C语言中scanf函数输入回车符的问题
- C语言中scanf函数输入回车符的问题
- C语言中scanf函数输入回车符的问题
- HDU5274
- LeetCode Fraction to Recurring Decimal
- Product of Array Except Self
- DT大数据梦工厂 温故而知新 之18讲
- Havok_2014-1-0_Pc_Xs_User_Guide(1.1.2-基础系统)
- C语言的格式化输入函数scanf
- HttpPost 中文乱码。
- Android中的Selector的用法
- 8.3知识总结
- Havok_2014-1-0_Pc_Xs_User_Guide(2.5.3-保存接触点)
- DT大数据梦工厂 温故而知新 之19讲
- UML读书笔记——03组件化软件的手段:对象技术
- 【LeetCode-面试算法经典-Java实现】【081-Search in Rotated Sorted Array II(搜索旋转的排序数组)】
- 【LeetCode-面试算法经典-Java实现】【082-Remove Duplicates from Sorted List II(排序链表中删除重复元素II)】