scanf与printf⽤法详解
⼀、scanf家族
1、scanf家族的原型
int scanf(char const *format,...);
int fscanf(FILE *stream,char const *format,...);
int sscanf(char const *buffer,char const *format,...);
每个原型中的省略号表⽰⼀个可变长度的指针列表。从输⼊转换⽽来的值逐个存储到这些指针指向的内存位置。由于C的参数传递都是传值调⽤决定了可变参数都是指针列表。注意:若给的不是指针,⽽是变量值。scanf将把变量值当做指针,在进⾏解引⽤时或者导致程序终⽌,或者导致不可预料的内存位置的数据被改写。
2、返回值
当格式化字符串format到达末尾或者读取的输⼊不再匹配格式字符串所指定的类型时,输⼊就停⽌,并返回被转换的输⼊值的数⽬,若在任何输⼊都没被转换之前⽂件就到达尾部则返回EOF。
3、类型的匹配
由于scanf是采⽤可变参数的机制,所以函数⽆法验证它们的指针参数是否为正确的类型,所以函数假定它们是正确的,(因此格式字符必须和后⾯的指针指向的类型保持⼀致)如果指针参数的类型和输⼊数据的类型不匹配则结果值就是垃圾。⽽且邻近的变量也有可能被改写。例如:
float a;
scanf("%d",&a); //本来a是⼀个float数据,却⽤⼀个整形指针指向变量a。
4、scanf格式代码
format字符串中包括以下内容。
空⽩字符:他们与输⼊中的零个或多个空⽩字符匹配,在处理过程中将被忽略。(常⽤于%c中)
格式代码:他们指定函数如何解释接下来的输⼊字符。
其他字符:若出现其他字符时,下⼀个输⼊字符必须与之匹配。若匹配则该输⼊字符丢弃,若不匹配,函数不再读取,直接返回。
格式代码:以%开头,后⾯接:⼀个可选的星号;⼀个可选的宽度;⼀个可选的限定符;格式代码
(1)星号:转换后的值被丢弃⽽不进⾏存储,跳过不需要的输⼊字符。
(2)宽度:限制被读取⽤于转换的输⼊字符的个数。若未给出宽度,函数读⼊字符直到遇到空⽩字符。
(3)限定符:修改有些格式代码的含义。注意转换所有的short、long、double、long double时都要加上限定符。若未加上将导致⼀个较长的变量只有⼀部分被初始化,⼀个较短的变量的邻近变量也被修改。这些取决于机器中类型的长度。
格式码\限定符h l L
d,i,n short long
o,u,x unsigned short unsigned long
e,f,g double long double
例如:short var_a;
scanf("%hd",&var_a);
(4)格式码:单个字符,表⽰输⼊字符如何被解释,以及指针列表指针的指向类型。
代码对应的指针
参数类型
含义
c char *读取和存储单个字符,前导的空⽩字符不跳过(可以在格式字符串中加⼊空格来跳过)。若给出宽度,就读取和存储这个数
⽬的字符,后⾯不会添加NUL,必须保证⾜够⼤的数组空间
i d int *有符号整数被转换。%d解释为⼗进制。%i根据第⼀个字符决定值的基数,和整型字符值常量的表⽰形式相同。
10,034,0xa2
u
o
x
unsigned *⽆符号整数被转换。u:⼗进制;o:⼋进制;x:⼗六进制
e
f
g
float *期待⼀个浮点值。他的形式必须像⼀个浮点型字⾯值常量,但⼩数点并不必须
s char *读取⼀串⾮空⽩字符,当发现空⽩时则输⼊停⽌。后⾯⾃动加上NUL。必须保证⾜够⼤的数组空间
n int *处理字符的个数
5、⽤scanf实现⾏定向的输⼊。
由于scanf把回车也当做空⽩字符处理所以使⽤scanf保持⾏边界的同步时很困难的。为了实现⾏定向。可以搭配fgets。先⽤fgets读取⼀⾏,然后⽤sscanf对读取的⾏处理。
6、使⽤sscanf处理可变格式的输⼊。
int a,b,c;
fgets(buf,20,stdin);
char *p = strrchr(buf,'\n');
*p = '\0'; //去除回车符
if(sscanf(buf,"%d%d%d",&a,&b,&c) != 3)
{
scanf用法c++a = 1; //defalut value of a
if(sscanf(buf,"%d%d",&b,&c) != 2)
{
b = 1; //default value of b
if(sscanf(buf,"%d",&c)!=1)
{
printf("input error\n ");
exit(1);
}
}
}
printf("a = %d\nb=%d\nc=%d\n",a,b,c);
⼆、printf家族
1、原型
int printf(char const *format,...);
int fprintf(FILE *stream,char const *format,...);
int sprintf(char *buffer,char const *format,...);
2、类型匹配
printf函数和scanf⼀样,⽆法验证⼀个值是否具有格式码所表⽰的正确类型。所以保证他们相互匹配是程序员的责任。3、printf格式码
format字符串包含格式码,它使参数列表的下⼀个值根据指定的⽅式进⾏格式化,对于其他的字符则原样输出。
格式码由⼀个%开头,后边可以跟:
标志字符、字段宽度、精度、修改符、#标志、格式码
(1)标志字符:
标志含义
-左对齐;默认右对齐
0右对齐时,⽤0填充左边未使⽤的列;默认⽤空格填充+当⼀个数为正数时,前⾯加上⼀个+号,默认不显⽰空格当⼀个数为正数时,前⾯加上⼀个空格,默认不显⽰
(2)字段宽度:指定输出的最⼩字符数,若输出的⼩于字段宽度。则根据标志字符进⾏相应的修改输出
(3)精度:
作⽤于%s:指定要被转换的最多字符数
作⽤于%f:指定出现在⼩数点后的数字位数
(4)修改符:
修改符作⽤对象表⽰类型
h d,i,o,u,x short型整数
l d,i,o,u,x long型整数
l e,f,g long double型数据
(5)格式代码
代码参数含义
c int参数被裁剪为unsigne
d char类型并作为字符打印
int作为⼀个⼗进制整数打印
d
i
o
unsigned int参数作为⼀个⽆符号值打印,u使⽤⼗进制,o使⽤⼋进制,x使⽤⼗六进制u
x
e、f、g double参数按照浮点数打印,精度缺少为6位
s char *打印⼀个字符串
n int *打印字符的个数
(6)#标志
#标志可以作⽤于格式代码:o,x,e,f,g 也就是⽆符号数和浮点数
o:产⽣的值以0开头;x:以0x开头;(这两个很实⽤。)
e,f,g:确保结果始终包含⼀个⼩数点即使后⾯没有数字。
long double a = 3.14;
printf("a = %08.3lf",a); //右对齐,开头补零,字符宽度8位,精度3位,以long double型输出。
三、利⽤sprintf和scanf实现字符串和数值的相互转换
利⽤sscanf可以实现字符串向数值的转换,⽽利⽤sprintf实现数值向字符串的转换
#include<stdio.h>
int main()
{
float a = 3.14;
double b;
char buf[20];
sscanf("3.42","%lf",&b); //将字符串转换为数值double
sprintf(buf,"%.2f",a); //将double型数值转换为字符串
printf("b = %.2f\n",b);
printf("buf is:%s\n",buf);
}
另外标准库提供的⽤于字符串转换为整型/浮点型的函数有:
int atoi(char const *string);
long int atol(char const *string);
long int strtol(char const *string,char **unused,int base);
long int strtoul(char const *string,char **unused,int base);
double atof(char const *string);
double strtod(char const *string,char **unused);
使⽤注意事项:
1、跳过前导空⽩字符,忽略⾮法缀尾字符
2、对于整型,当base=0时,根据string的字⾯确定string的进制。(⼋进制(以0开头)、⼗进制(默认)、⼗六进制(以0x开头));
3、若不能转换为相应类型则返回0
4、unused指向⽆法转换的字符的指针的指针。
四、通过sprintf获取⼀个整数的位数
通常对于⼀个整数data,我们需要获得其位数的⽅法为:对其与10、100、1000、等相除来确定共有多少位。
下⾯程序提供了⼀个获取data位数的⼀个好⽅法:
int number,data;
data = 12345;
char buf[20];
sprintf(buf,"%d%n",data,&number); //利⽤snprintf防⽌访问内存越界:snprintf(buf,20,"%d%n",data,&number); printf("data is %d,has %d characters\n",data,number);
利⽤printf的%n格式符记录打印字符的个数来统计data的位数。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论