<C陷阱与缺陷>中的printf

来源:互联网 发布:js target 跳转 编辑:程序博客网 时间:2024/04/29 23:50
<C陷阱与缺陷>中关于printf

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 <varargs.h>
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;
}






原创粉丝点击