實驗程式是用vc6編譯,一定注意副檔名為c,不是cpp,下載前面幾個測試程式(鏈表、表、原子中有下載連結)中直接將下面來源程式覆蓋1.c的內容即可!
再次強烈建議在這些函數上設上斷點,按F11跟進去把源碼走一遍,才有真正的學習效果!
來源程式如下:
#include <stdio.h>#include <string.h>#include "include/Fmt.h"#include "include/Str.h"#pragma comment(lib, "libcii.lib")typedef int (*FN)(int, void *);void main(){//注意:C語言一定要將這些變數聲明放在函數的頭部char *s1 = NULL;////以下為【格式化】函數//Fmt_fmt((FN)fputc, stdout, "測試1: Fmt_fmt: %d, %s, %x, %f, %e, %g, 單字元: %c, 16進位:0X%x\n", 9988, "OK", 9988, 90.89, 90.89, 90.89, 101, 101);/*下面這些函數最終會調用:Fmt_vfmt 遇到【%d】時,調用:cvt_d,此靜態函數已經在初始化時安裝好,見書中文版P164的cvt[]初始賦值'd' = 100(ASCII值),對應:cvt_d 函數'c' = 100,對應: cvt_c 函數'e' = 101,'f' = 102, 'g' = 103,三個都是浮點數轉換,下標均對應cvt_f函數,見中文版P170說明,內部都是調用了sprintf庫函數來格式化'x' = 101,,對應: cvt_x 函數,留心源碼的“*--p = "0123456789abcdef"[m&0xf];”部分;.............*/////Fmt_print("測試2: Fmt_print: %d, %s, %x\n", 9988, "OK", 9988);//Fmt_fprint(stdout, "測試3: Fmt_fprintf: %d, %s, %x\n", 9988, "OK", 9988);//s1 = Fmt_string("測試4: Fmt_string: %d, %s, %x\n", 9988, "OK", 9988);printf("%s", s1);////以下為【轉換】函數//Fmt_register('@', Str_fmt);/*'@' = 64, 關聯上 Str_fmt,Str_fmt和cvt_d,cvt_s, cvt_o,cvt_f等等是一樣的定義方式觀察Str_fmt的內部實現,是接受【開始位移】和【顯示長度】兩個參數,因此僅適合下面Fmt_print的用法可以比較Str_fmt和cvt_s兩個函數的實現(附後)*/Fmt_print("測試5: Fmt_string: %@\n", "ChinaOKYes", 0, 4);}
輸出
測試1: Fmt_fmt: 9988, OK, 2704, 90.890000, 9.089000e+001, 090.89, 單字元: e, 16進位:0X65測試2: Fmt_print: 9988, OK, 2704測試3: Fmt_fprintf: 9988, OK, 2704測試4: Fmt_string: 9988, OK, 2704測試5: Fmt_string: naOKYesPress any key to continue
比較cvt_s(src/fmt.c),和Str_fmt(src/str.c)兩個函數:
static void cvt_s(int code, va_list *app,int put(int c, void *cl), void *cl,unsigned char flags[], int width, int precision) {char *str = va_arg(*app, char *);assert(str);Fmt_puts(str, strlen(str), put, cl, flags,width, precision);}void Str_fmt(int code, va_list *app,int put(int c, void *cl), void *cl,unsigned char flags[], int width, int precision) {char *s;int i, j;assert(app && flags);s = va_arg(*app, char *);i = va_arg(*app, int);j = va_arg(*app, int);convert(s, i, j);Fmt_puts(s + i, j - i, put, cl, flags,width, precision);}
附:ASCII表非常有用,再附上一遍,便於查看:
The following table lists 0 - 127.
| Code |
Char |
Code |
Char |
Code |
Char |
Code |
Char |
| 0 |
|
32 |
[space] |
64 |
@ |
96 |
` |
| 1 |
|
33 |
! |
65 |
A |
97 |
a |
| 2 |
|
34 |
" |
66 |
B |
98 |
b |
| 3 |
|
35 |
# |
67 |
C |
99 |
c |
| 4 |
|
36 |
$ |
68 |
D |
100 |
d |
| 5 |
|
37 |
% |
69 |
E |
101 |
e |
| 6 |
|
38 |
& |
70 |
F |
102 |
f |
| 7 |
|
39 |
' |
71 |
G |
103 |
g |
| 8 |
** |
40 |
( |
72 |
H |
104 |
h |
| 9 |
** |
41 |
) |
73 |
I |
105 |
i |
| 10 |
** |
42 |
* |
74 |
J |
106 |
j |
| 11 |
|
43 |
+ |
75 |
K |
107 |
k |
| 12 |
|
44 |
, |
76 |
L |
108 |
l |
| 13 |
** |
45 |
- |
77 |
M |
109 |
m |
| 14 |
|
46 |
. |
78 |
N |
110 |
n |
| 15 |
|
47 |
/ |
79 |
O |
111 |
o |
| 16 |
|
48 |
0 |
80 |
P |
112 |
p |
| 17 |
|
49 |
1 |
81 |
Q |
113 |
q |
| 18 |
|
50 |
2 |
82 |
R |
114 |
r |
| 19 |
|
51 |
3 |
83 |
S |
115 |
s |
| 20 |
|
52 |
4 |
84 |
T |
116 |
t |
| 21 |
|
53 |
5 |
85 |
U |
117 |
u |
| 22 |
|
54 |
6 |
86 |
V |
118 |
v |
| 23 |
|
55 |
7 |
87 |
W |
119 |
w |
| 24 |
|
56 |
8 |
88 |
X |
120 |
x |
| 25 |
|
57 |
9 |
89 |
Y |
121 |
y |
| 26 |
|
58 |
: |
90 |
Z |
122 |
z |
| 27 |
|
59 |
; |
91 |
[ |
123 |
{ |
| 28 |
|
60 |
< |
92 |
\ |
124 |
| |
| 29 |
|
61 |
= |
93 |
] |
125 |
} |
| 30 |
- |
62 |
> |
94 |
^ |
126 |
~ |
| 31 |
|
63 |
? |
95 |
_ |
127 |
|