《C语言接口与实现》实验——格式化(Fmt_T)

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

CodeCharCodeCharCodeCharCodeChar
0 32[space]64@96`
1 33!65A97a
2 34"66B98b
3 35#67C99c
4 36$68D100d
5 37%69E101e
6 38&70F102f
7 39'71G103g
8**40(72H104h
9**41)73I105i
10**42*74J106j
11 43+75K107k
12 44,76L108l
13**45-77M109m
14 46.78N110n
1547/79O111o
1648080P112p
1749181Q113q
1850282R114r
19 51383S115s
20 52484T116t
21 53585U117u
2254686V118v
2355787W119w
2456888X120x
2557989Y121y
2658:90Z122z
27 59;91[123{
2860<92\124|
2961=93]125}
30-62>94^126~
31 63?95_127

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值