《C語言介面與實現》實驗——格式化(Fmt_T)
阿新 • • 發佈:2019-02-15
實驗程式是用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: naOKYes
Press 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 | |