《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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于c语言接口网上的资料是少之又少,所以下面这些文字全是我一个字一个字打印上来的希望大家 能对的起我的付出: 现在的程序员都面临大量的关于应用程序接口(Application Programming Interface,API) 的信息,大多数人都会使用API和程序库,并在其所写的每一个应用程序中实现它们,但是很少人 会创建或发布新的能广泛应用的API,事实上,程序员似乎倾向与循环使用他们自己的东西,而不 愿意查找,能满足他们要求的程序库,这或许是因为写特定应用程序代码要比查找设计好的API容易。 这里我所提到的是一种基于接口与其实现的设计方法,并且通过对24个接口及其实现的描述详细地演示了这种方法,这些接口涉及到计算机领域的很多知识,其中包括数据结构,算法,字符串处理 和并发程序,这些实现并不是简单的玩具----它们是为了在你们所设计的软件代码中使用而设计的。(当然了我会通过阅读量来看是否继续发下去,人要少了我就没有必要浪费时间了) c编程语言对基于接口设计方法的支持是极少的。 而面向对象的语言,如c++,Modula-3,则鼓励将接口实现分离,基于接口的设计独立与任何特定 的语言,但是它要求程序员对像c一样的语言有更多的驾驭能力和更高的警惕性,因为这类语言很容易破坏带有隐含实现信息的接口,反之亦然。 然而一但掌握了基于接口的设计方法,就能够在服务于众多应用程序的通用接口基础上建立应用程序,从而加速开发,在一些c++环境中的基础类库就体现了这种效果。 增加对现有软件的重用---接口实现库,能够减少初始开发成本,同时还能减少维护成本,因为应用程序的更多部分都建立在经过良好测试的通用接口实现上,这里我提到的接口是针对数据结构的,但它并不是数据结构,我重点将放在算法引擎----包装数据结构以供应用程序使用----而不在数据结构算法本身,接口的示例和实现都以literate程序的方式给出,换句话说就是源代码及其解释是按照最适合理解代码的顺序交织出现的。 下面我将我想要给大家讲的内容分一下类: 基础 1,接口实现 2,异常与断言 3,内寸管理 4,进一步内寸管理 数据结构 5,链表 6,表格 7,集合 8,动态数组 9,序列 10,环 11,位向量 字符串 12,原子 13,格式化 14,低级字符串 15,高级字符串 算法 16,扩展精度算法 17,任意精度算法 18,多精度算法 线程 19,线程 建议: 看到这里的朋友我相信对c语言都有了很长时间的学习 如果你还没有搞懂c语言的全部内容,我强烈建议你先别看这里

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值