C语言格式化输入输出

C语言中,格式化的输入输出由其标准库中的scanf和printf函数实现,下面分别介绍。

1、用printf格式化输出

用printf可以完成准确的格式化输出。每个printf调用包含说明输出格式的格式控制字符串。格式控制字符串包含格式转换符、标志、字段宽度、精度和字面量字符(literal character),和前面的%一起,这些就构成了格式转换规格。
printf函数的形式是printf(格式控制字符串,其它参数)。格式控制字符串说明了输出格式,而"其它参数"(可选)对应于格式控制字符串中的每个转换说明。每个转换说明从一个百分号开始,用格式转换符结束。在一个格式控制字符串中可以有多个转换说明。下面分别介绍不同类型数据的格式转换符。

1.1 输出整数

格式控制符

d显示有符号十进制数
i显示有符号十进制数(当和scanf一起使用时,i和d说明符是不一样的)
o显示无符号八进制数
u显示无符号十进制数
x或者X显示无符号十六进制整数。X将显示数字0到9和字母A到F,而x将显示数字0到9和字母a到f
h或者l(字母l)放在整数格式转换符之前,分别说明显示short或者long整数。更准确地说,字母h和l应该成为长度修饰符。
例子

#include <stdio.h>
int main()
{
	printf("455%%d:%d\n",455);
	printf("455%%i:%i\n",455);
	printf("+455%%d:%d\n",+455);
	printf("-455%%d:%d\n",-455);
	printf("32000%%hd:%hd\n",32000);
	printf("2000000000%%ld:%ld\n",2000000000);
	printf("455%%o:%o\n",455);
	printf("455%%u:%u\n",455);
	printf("-455%%u:%u\n",-455);
	printf("455%%x:%x\n",455);
	printf("455%%X:%X\n",455);
	return 0;
}
运行结果:


上面的例子中,应该注意输出整数的格式转换符,默认忽略正号,仅输出负号。另外,要注意的是如果用%u,输出-455,结果是4294966841,这应该是内存中有符号整数和无符号整数的编码方式不同,当用无符号数的编码方式去读取一个有符号的数所导致的结果。

1.2 输出浮点数

格式控制符

e或者E以幂计数法的形式来显示浮点数
f显示常规的浮点数
g或者G用浮点形式f或者幂形式e(或者E)来显示浮点数值,g和G的区别同e和E。
l(字母l)放置在任何浮点格式转换符之前,以规定显示long double浮点数
说明

默认情况下,用格式转换符e、E和f输出的数值,是用精确到小数点右边6位的精度输出的。(当然,我们也可以控制显示其它精度。)格式转换符f总是至少输出小数点左边1位,格式转换符e和E分别在幂之前输出小写字母e和大写字母E,而且总是准确地输出小数点左边1位。
格式转换符g(或者G)将使用e(或者E)或f来进行格式输出,但是没有后面的0(1.234000将输出1.234)。如果在将数值转换为幂计数法之后,值的幂小于-4或者大于等于规定的精度(默认情况下,g和G是6位),则将使用e(或者E)来输出数值。否则,将使用格式转换符f来输出数值。用%g格式转换符将把值0.0000875、8750000.0、8.75、87.50和875输出为8.75e-05、8.75e+6、8.75、87.5和875。格式转换符g和G的精度说明了包括小数点左边的数字在内所能够输出的有效数字最多个数。浮点格式转换符的默认精度是6,使用格式转换符%g将把数值1234567.0输出为1.23457e+06;使用格式转换符%.4g将把数值1234567.0输出为1.235e+06。
例子

#include <stdio.h>
int main()
{
	printf("%e\n",1234567.89);
	printf("%e\n",+1234567.89);
	printf("%.4e\n",-1234567.89);
	printf("%E\n",1234567.89);
	printf("%f\n",1234567.89);
	printf("%.1f\n",1234567.89);
	printf("%g\n",1234567.89);
	printf("%G\n",1234567.89);
	printf("%.7G\n",1234567.89);
	printf("%.7g\n",12345678.9);
	printf("%.4g\n",1234567.89);
	return 0;
}

运行结果:


1.3 输出字符串和字符

格式转换符c和s分别用于输出单个字符和字符串。格式转换符c需要char参数;格式转换符s需要指向char的指针作为参数。格式转换符s将输出字符,直到遇到空字符('\0')。

例子:

#include <stdio.h>
int main()
{
	char character='A';
	char str[]="This is a string.";
	char *strPtr="This is also a string.";
	printf("%c\n",character);
	printf("%s\n","This is a string.");
	printf("%s\n",str);
	printf("%s\n",strPtr);
	return 0;
}
运行结果:


1.4 其它

1.4.1 其它格式转换符

格式控制符

p用系统定义的方式来显示指针的值
n存储当前printf语句中已经输出的字符个数。对应的参数是指向存储已经输出字符个数的整数变量指针,%n不会输出任何内容。
%显示%
例子:

#include <stdio.h>
int main()
{
	int *ptr;
	int x=12345;
	int y;
	ptr=&x;
	printf("The value of ptr is %p\n",ptr);
	printf("The address of x is %p\n\n",&x);
	printf("012345:%n\n",&y);
	printf("The number of printed characters of last printf:%d\n\n",y);
	y=printf("This line has 28 characters\n");
	printf("%d characters were printed\n\n",y);
	printf("Printing a %% in a format control string.");

	return 0;
}
运行结果:


1.4.2 控制字段宽度和精度

输出数据字段的大小是用字段宽度来指定的。如果字段宽度大于要输出的数据,则默认是在那个字段内右对齐数据。在百分号和格式转换符之间插入表示字段宽度的整数来控制输出的字段宽度。如果输出数据的宽度大于字段宽度,那么字段宽度将会增加,负号将在字段宽度中占一个字符的为位置,字段宽度可以和任何格式转换符一起使用。
printf函数也提供了指定输出精度的功能。对于不同的数据类型,精度有不同的含义。当和整数格式转换符一起使用时,精度确定了要输出的最小数位个数,如果输出数值所包含的位数比规定的精度少,则在输出数值前面加0,直到数位总和等于精度,整数的默认精度是1;当和浮点格式转换符e、E和f一起使用时,精度就是小数点后的数位个数;当和格式转换符g和G一起使用时,精度就是要输出的有效数字的对多个数;当和格式转换符s一起使用时,精度就是从字符串写入的字符的最多个数。要使用精度,可以在百分号和格式转换符之间插入小数点,后面加入表示精度的整数。输出浮点值时使用的精度小于原始数值中十进制位数的个数时,将会对浮点数进行四舍五入。
通过在百分号和格式转换符之间加入字段宽度,后面是小数点,然后加入精度,就可以组合使用字段宽度和精度。可以在格式控制字符串后面的参数列表中用整数表达式来指定字段的宽度和精度,只需在字段宽度和精度出插入一个星号,printf将计算参数列表中匹配的int参数,并用它取代星号。字段宽度的数值可以是正值或者负值(将导致字段左对齐输出),精度必须是正值。

例子:

#include <stdio.h>
int main()
{
	int i=873;
	double f=123.95367;
	char s[]="Happy Birthday";
	printf("Using precision for integers:\n");
	printf("\t%.4d\n\t%.9d\n\n",i,i);
	printf("Using precision for floating-point numbers:\n");
	printf("\t%.3f\n\t%.3e\n\t%.3g\n1.12789%%.4g:%.4g\n0.12789%%.4g:%.4g\n\n",f,f,f,1.12789,0.12789);
	printf("Using precision for strings:\n");
	printf("\t%.11s\n",s);
	return 0;
}
运行结果:


1.4.3 使用标记

printf函数也提供了标记来补充它的格式化输出功能。用户可以在格式控制字符串中使用如下5个标记:

-(负号)在指定字段内左对齐输出
+(正号)在正数面前显示正号,在负数面前显示负号
空格在正数面前显示空格而不显示正号
#当和八进制转换符o一起使用时,在输出数值前面加入前缀0(数字0);当和十六进制格式转换符x或者X一起使用时,在输出数值前面加入0x或0X;对于用e、E、f、g或者G强制输出小数点(通常情况下,只有在小数点后有数字的情况下,才输出小数点),对于g和G,不会删除后面的0。
0(数字0)在数值面前用零填充字段
要在格式控制字符串中使用标记,可以将标记紧接在百分号的右边,可以在一个转换说明中组合使用多个标记。

例子:

#include <stdio.h>
int main()
{
	//左对齐和右对齐
	printf("左对齐右对齐\n%10s%10d%10c%10f\n","Hello",7,'A',1.23);
	printf("%-10s%-10d%-10c%-10f\n\n","Hello",7,'A',1.23);
	//是否输出正号
	printf("是否输出正号\n%d\t%d\n",786,-786);
	printf("%+d\t%+d\n\n",786,-786);
	//在正数前面加入空格
	printf("在正数前面加入空格\n% d\t% d\n\n",786,-786);
	//#使用
	int c=1427;
	double p=1427.0;
	printf("#使用\n%#o\t%#x\n",c,c);
	printf("%#X\n",c);
	printf("%g\n",p);
	printf("可见这里往往补齐到6位有效数字\n%#g\n",p);
	printf("%#g\t%#g\t%#g\n\n",123456.0,3.1,3.0);
	//组合+和0
	printf("组合+和0\n%+09d\n",352);
	printf("%09d\n",352);
	return 0;
}
运行结果:



1.4.4 字面量和转义序列

在printf中,多数要输出的字面量都是可以包含在格式控制字符串中的。但是,有些字符必须用转义序列来表示,如下:

\'输出单引号字符
\"输出双引号字符
\?输出问号字符
\\输出反斜线字符
\a导致可听见的(铃声)或者视觉上的警告
\b当前行的光标退后一个位置
\f将光标移动到下一个逻辑页面的开头
\n将光标移动到下一行的开头
\r将光标移动到当前行的开头
\t将光标移动到下一个水平制表符位置
\v将光标移动到下一个垂直制表符位置
例子:

#include <stdio.h>
int main()
{
	printf("abcdefghijk\bu\n");
	printf("abcdefghijk\b\nlmnopq\rrstu\n");
	printf("\a");
	return 0;
}
运行结果:


说明:转义序列\a的声音吵死了,而且电脑静音也不管用。

2、用scanf格式化输入

精确的输入格式转换是由scanf来完成的。每条scanf语句都包含说明输入数据格式的格式控制字符串。格式控制字符串包括转换控制符和字面量字符。函数scanf有以下输入格式化功能:
(1)输入所有类型的数据
(2)从输入流中读取特定的字符
(3)跳过输入流中特定的字符
函数scanf的形式是scanf(格式控制字符串,其它参数),格式控制字符串说明了输入格式,而其它参数是指向存储输入值的变量的指针。

2.1 输入所有数据类型的格式转换符

整数
d读取可选的有符号十进制整数。相应的参数是整数指针
i读取可选的有符号十进制、八进制或十六进制整数。相应的参数是整数指针。
o读取八进制整数。相应的参数是指向无符号整数的指针。
u读取无符号十进制整数。相应的参数是指向无符号整数的指针
x或者X读取十六进制整数。相应的参数是指向无符号整数的指针
h或者l(字母l)放在所有的整数格式转换符前,说明将输入short或者long整数
浮点数
e,E,f,g或者G读取浮点值。相应的参数是指向浮点变量的指针
l或者L放置在所有浮点格式转换符前,以说明将输入double或者long double数值
字符和字符串
c读取一个字符。相应的参数是指向char的指针,不加入空字符('\0')
s读取一个字符串。相应的参数是指向char类型的数组的指针,这个数组应该足够大,以容纳字符串和自动添加的空字符('\0')
扫描集合
[扫描字符]在字符串中扫描字符集合中的字符
其它
p用与在printf语句中用%p输出地址时所产生的格式相同的格式来读取地址
n存储迄今为止在这条scanf中输出的字符个数。相应的参数是指向整数的指针
%跳过输入中的百分号
2.2 几个例子

2.2.1 输入整数

#include <stdio.h>
int main()
{
	int a,b,c,d,e,f,g;
	printf("Enter seven integers:\n");
	scanf("%d%i%i%i%o%u%x",&a,&b,&c,&d,&e,&f,&g);
	printf("The input displayed as decimal integers is:\n");
	printf("%d %d %d %d %d %d %d \n",a,b,c,d,e,f,g);
	return 0;
}
运行结果:


2.2.2 输入浮点数

#include <stdio.h>
int main()
{
	double a,b,c;
	printf("Enter 3 float-point numbers:\n");
	scanf("%le%lf%lg",&a,&b,&c);
	printf("Here are the numbers entered in plain:\n");
	printf("%f\n%f\n%f\n",a,b,c);
	printf("Enter 3 float-point numbers:\n");
	scanf("%le%lf%lg",&a,&b,&c);
	printf("Here are the numbers entered in plain:\n");
	printf("%f\n%f\n%f\n",a,b,c);
	return 0;
}
运行结果:


2.2.3 扫描集合

可以使用扫描集合来输入字符序列。扫描集合是方括号中的一组字符,而且格式控制字符串的前面有百分号。扫描集合可以扫描输入流中的字符,并查找那些能够匹配扫描集合中所包含的字符。每次找到匹配的字符时,将把它存储在扫描集合的相应参数中,即指向字符数组的指针。扫描集合在遇到扫描集合中没有的字符时,就停止输入字符。如果输入流中的第一个字符不匹配扫描集合中的字符,则仅在数组中存储空字符('\0')。也可以在扫描字符前面的方括号内加入补字号(^)来创建反向扫描集合,用来扫描集合中没有的字符。这将存储扫描集合中没有出现的字符。当遇到反向扫描集合中包含的字符时,输入结束。

例子:

#include <stdio.h>
int main()
{
	char z[9],x[9];
	printf("Enter string:\n");
	scanf("%[aeiou]",z);
	printf("The input was \"%s\".\n\n",z);

	printf("Enter string:\n");
	scanf("%[^aeiou]",x);
	printf("The input was \"%s\".\n",x);
	return 0;
}
运行结果:


2.2.4 指定输入字段宽度和赋值抑制符*

可以在scanf格式转换符中使用字段宽度来从输入流中读取指定个数的字符。也可以使用赋值抑制符*来从输入中读取任意类型的数据并删除它,而不将它赋值给变量,如%*c,就是在%c中使用赋值抑制符来说明应该读取和删除输入流中的某个字符。

例子:

#include <stdio.h>
int main()
{
	int x;
	int z;
	printf("Enter an integer:\n");
	scanf("%2d%d",&x,&z);
	printf("The integers input were %d and %d\n",x,z);

	int y,m,d;
	printf("Enter the year, month, day:\n");
	scanf("%d%*c%d%*c%d",&y,&m,&d);
	printf("Date input is %4d年%02d月%02d日\n",y,m,d);
	printf("Enter the year, month, day:\n");
	scanf("%d%*c%d%*c%d",&y,&m,&d);
	printf("Date input is %4d年%02d月%02d日\n",y,m,d);
	return 0;
}
运行结果:



好吧,到这里,又结束了。还是没多少自己的东西,大部分是书上摘下来的。索性叫这几篇叫读书笔记系列吧。大笑

参考<C语言程序设计经典教程>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值