实验程序是用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 | |