1. 格式符
%g, %f, %e这3个格式项用于打印浮点值。%g格式项用于打印那些不需要按列对齐的浮点数特别有用。它在打印出对应的数值时,会去掉该数值尾缀的零,
保留6位有效数字。
printf("PI = %g\n", 4 * atan(1.0));
PI = 3.14159 (共6位有效数字,不包括小数点和前缀0)
printf("%g %g %g %g %g\n", 1/1.0, 1/2.0, 1/3.0, 1/4.0, 0.0);
将打印出1 0.5 0.333333 0.25 0 (注意0.3333333共6位有效数字,不包括前缀0和小数点)
printf("%g\n", 2/3.0); => 0.666667 (数值进行四舍五入)
如果一个数的绝对值大于999999,按%g的格式打印出这个数将会超过6位有效数字,故它会采用科学计数法的方法打印。
printf("%g\n", 123456789.0); => 1.23457e+08 (基数部分有6位有效数字)
对于比较小的数值,除非该数的指数小于或等于-5,%g格式项才会采用科学计数法来表示。因此
printf("%g %g %g\n", 3.14159e-3, 3.14159e-4, 3.14159e-5);
=> 0.00314159 0.000314159 3.14159e-5
%e格式项用于打印浮点数,要求一律显式地使用指数形式:PI在使用%e格式项时将被写成3.141593e+00。%e格式项将打印出小数点后6位有效数字,而并非如%g格式项打印出的数总共6位有效数字。
%f跟%e一样,即小数点后6位有效数字。
2. 修饰符
printf函数也接受辅助字符来修饰一个格式项的含义。这些辅助字符出现在%符号和后面的格式码之间。
整数有3种不同类型,对应3种不同长度: short,long和正常长度。如果一个short整数作为任何一个函数的参数出现,它会被自动的扩展为一个正常长度的整数。(K&R C)
宽度修饰符对所有的格式码都有效,甚至%%也不例外。因此,例如printf(%8%\n"); 8个%
精度修饰符的作用是控制一个数值的表示中将要出现的数字位数,或者用于限制将要打印的字符串中应该出现的字符数。精度修饰符包括一个小数点,和小数点后面的一串数字。精度修饰符出现在%符号和宽度修饰符之后,格式码与
长度修饰符之前。
1) 对于整数格式项%d, %o, %x和%u,精度修饰符指定了
打印数字的最小位数。如果不够位数,则会自动补0
printf(%.2d/%.2d/%.4d\n", 7, 14, 1789); => 07/14/1789
2) 对于%e, %E, 和%f格式项,精度修饰符指定了
小数点后应该出现的数字位数
3) 对于%g和%G格式项,精度修饰符指定了打印数值中的
有效数字位数。除非另有说明,非有效数字的0将被去除,如果小数点后不跟数字则小数点也被删除。
printf("%.1g %.2g %.4g %.8g\n", 10/3.0, 10/3.0, 10/3.0, 10/3.0);
=> 3 3.3 3.333 3.333333
4) 对于%c和%%格式项,
精度修饰符将被忽略。
3. 标志
1) ‘-’操作,左对齐
2) '+'操作,规定每个待打印的数值在输出时都应该以它的符号作为第一个字符。故正数会打印“+”, 负数会打印“-",0则不输出。
3) 空白字符作为标志字符时,含义是如果某数是一个非负数,就在它前面插入一个空白字符。如果标志字符+和空白字符同时出现一个格式项中,最终的效果是以标志字符+为准。
for (int i = -3; i <= 3; i++)
printf("% d\n", i);
-3
-2
-1
0
1
2
3
4. 可变域宽与精度
printf("%*.*s\n", 12, 5, str);
这个式子将打印出字符串str的前5个字符或更少,前面将填充若干空白字符以达到总共打印12个字符的要求。
printf("%*%\n", n);
上式将在宽度为n个字符的域内以右端对齐的方式打印出
一个%符号。换言之,先打印n-1个空白字符,后面再跟一个%符号。
varargs.h中的宏实现(K&R C)
typdef char* va_list;
#define va_dcl int va_alist;
#define va_start(list) list = (char*)&va_alist
#define va_end(list)
#define va_arg(list, mode) \
((mode *)(list += sizeof(mode)))[-1]
#include
void error(va_alist) va_dcl
int printf(va_alist) va_dcl
{
va_list ap;
char* format;
int n;
va_start(ap);
format = va_arg(ap, char*);
n = vprintf(format, ap);
va_end(ap);
return n;
}