vsprintf
2015-08-12 16:57
337 查看
int vsprintf(char *buf, const char *fmt, va_list args) | |
2 | { |
3 | int len; |
4 | int i; |
5 | char * str; |
6 | char *s; |
7 | int *ip; |
8 | |
9 | int flags; /* flags to number() */ |
10 | |
11 | int field_width; /* width of output field */ |
12 | int precision; /* min. # of digits for integers; max |
13 | number of chars for from string */ |
14 | int qualifier; /* 'h', 'l', or 'L' for integer fields */ |
15 | |
16 | for (str=buf ; *fmt ; ++fmt) { //str为最终存放字符串的位置但是他随着字符串增长而增长,buf始终指向最终字符串的启始位置。fmt为格式字符串 |
17 | if (*fmt != '%') { |
18 | *str++ = *fmt; //如果不是%则表示这是需要原样打印的字符串,直接复制即可 |
19 | continue; |
20 | } |
21 | |
22 | /* process flags */ |
23 | flags = 0; |
24 | repeat: |
25 | ++fmt; /* this also skips first '%' */ //fmt指向%的后一位 |
26 | switch (*fmt) { |
27 | case '-': flags |= LEFT; goto repeat; |
28 | case '+': flags |= PLUS; goto repeat; |
29 | case ' ': flags |= SPACE; goto repeat; //判断标志位,并设置flags |
30 | case '#': flags |= SPECIAL; goto repeat; |
31 | case '0': flags |= ZEROPAD; goto repeat; |
32 | } |
33 | |
34 | /* get field width */ |
35 | field_width = -1; |
36 | if (is_digit(*fmt)) |
37 | field_width = skip_atoi(&fmt); |
38 | else if (*fmt == '*') { |
39 | /* it's the next argument */ |
40 | field_width = va_arg(args, int); |
41 | if (field_width < 0) { |
42 | field_width = -field_width; |
43 | flags |= LEFT; |
44 | } |
45 | } |
46 | |
47 | /* get the precision */ |
48 | precision = -1; |
49 | if (*fmt == '.') { |
50 | ++fmt; |
51 | if (is_digit(*fmt)) |
52 | precision = skip_atoi(&fmt); |
53 | else if (*fmt == '*') { |
54 | /* it's the next argument */ |
55 | precision = va_arg(args, int); |
56 | } |
57 | if (precision < 0) |
58 | precision = 0; |
59 | } |
60 | |
61 | /* get the conversion qualifier */ |
62 | qualifier = -1; |
63 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { |
64 | qualifier = *fmt; |
65 | ++fmt; |
66 | } |
67 | |
68 | switch (*fmt) { //如果没有上面奇怪的标志位(*/./h/l/L)则fmt仍然指向%的后一位,下面判断这个标志位 |
69 | case 'c': |
70 | if (!(flags & LEFT)) |
71 | while (--field_width > 0) |
72 | *str++ = ' '; |
73 | *str++ = (unsigned char) va_arg(args, int); |
74 | while (--field_width > 0) |
75 | *str++ = ' '; |
76 | break; |
77 | |
78 | case 's': |
79 | s = va_arg(args, char *); |
80 | len = strlen(s); |
81 | if (precision < 0) |
82 | precision = len; |
83 | else if (len > precision) |
84 | len = precision; |
85 | |
86 | if (!(flags & LEFT)) |
87 | while (len < field_width--) |
88 | *str++ = ' '; |
89 | for (i = 0; i < len; ++i) |
90 | *str++ = *s++; |
91 | while (len < field_width--) |
92 | *str++ = ' '; |
93 | break; |
94 | |
95 | case 'o': |
96 | str = number(str, va_arg(args, unsigned long), 8, |
97 | field_width, precision, flags); |
98 | break; |
99 | |
100 | case 'p': |
101 | if (field_width == -1) { |
102 | field_width = 8; |
103 | flags |= ZEROPAD; |
104 | } |
105 | str = number(str, |
106 | (unsigned long) va_arg(args, void *), 16, |
107 | field_width, precision, flags); |
108 | break; |
109 | |
110 | case 'x': |
111 | flags |= SMALL; |
112 | case 'X': |
113 | str = number(str, va_arg(args, unsigned long), 16, |
114 | field_width, precision, flags); |
115 | break; |
116 | |
117 | case 'd': //如果是整型,首先设定flags,然后利用number函数将可变参数取出,并根据base(这里是10)然后转换成字符串,赋给str |
118 | case 'i': |
119 | flags |= SIGN; |
120 | case 'u': |
121 | str = number(str, va_arg(args, unsigned long), 10, |
122 | field_width, precision, flags); |
123 | break; |
124 | |
125 | case 'n': |
126 | ip = va_arg(args, int *); |
127 | *ip = (str - buf); |
128 | break; |
129 | |
130 | default: |
131 | if (*fmt != '%')//如果格式转换符不是%,则表示出错,直接打印一个%。如果是%,那么格式转换符就是%%,就由下面if(*fmt)只输出一个% |
132 | *str++ = '%'; |
133 | if (*fmt) |
134 | *str++ = *fmt;//如果格式转换符不正确则输出%+不正确的格式转换符。如果是%%,则只输出一个% |
135 | else |
136 | --fmt;//如果转换格式符不是上面这些正确的,也不是空,那么直接输出,并返回到判断fmt的for语句;否则就指向末尾了,fmt后退一位,这样在for循环自动再加1进行判断时*fmt的条件就不满足,退出for循环 |
137 | break; |
138 | } |
139 | } |
140 | *str = '\0';//设定str字符串的最后一位为'\0' |
141 | return str-buf;//返回值为字符串的长度 |
相关文章推荐
- 最近的一些设计笔记
- qt caffe 编译error
- hdu1166 敌兵布阵(线段树 求区间和 更新点)
- Date、String、Calendar类型之间的转化
- HDU 1358 Period
- SkipList跳表基本原理
- JVM性能调优
- ubnutu 环境下 在APACHE服务器上的访问方式上去除index.php
- android优化以及相关知识点
- Selenium grid2+ testng并发式 困惑
- 集训第五周动态规划 D题 LCS
- 开启定位服务
- 如何提高ArcScene加载影像图的分辨率
- hdu3697(贪心+暴力)
- mac系统不同java版本切换
- c/c++中const使用总结(金典)
- [Leetcode] Next Permutation
- js获取自定义属性值
- JavaScript的jQuery库插件的简要开发指南
- STM8L探索套件学习笔记-EXTI外部中断