/****************1.接口
*******************/
用一个例子说明接口中所使用的一些约定:
#ifndef ARITH_H#define ARITH_Hextern int Arith_max(
int x,
int y);
extern int Arith_min(
int x,
int y);
extern int Arith_div(
int x,
int y);
extern int Arith_mod(
int x,
int y);
extern int Arith_ceiling(
int x,
int y);
extern int Arith_floor(
int x,
int y);
#endif
接口名字以前缀的形式出现在接口的每一个标识符中,因为在文件范围内所有标识符----变量,函数,类型定义以及枚举常量共享一个专用的名字空寂,而所有的全局结构,结构体,共用体以及枚举标签共享另一个专用的名字空间,所以为了防止名字冲突,采取这种方法。
对于x和y不同符号时,以上几种运算可能在不同编译器下出现不同的结果,所以在实现的时候需要注意。
Arith_div是用更精确的数学术语定义的,Arith_div(x,y)是不超过实数z的最大整数,其中z.y=x.
而c中的内嵌操作,如-13/5则是向0取整,故-13/5=-2。
/*************2.实现*****************/
#include "arith.h"#include <stdio.h>int Arith_max(int x, int y) { return x > y ? x : y;}int Arith_min(int x, int y) { return x > y ? y : x;}int Arith_div(int x, int y) { if (-13/5 == -2 && (x < 0) != (y < 0) && x%y != 0) return x/y - 1; else return x/y;}int Arith_mod(int x, int y) { if (-13/5 == -2 && (x < 0) != (y < 0) && x%y != 0) return x%y + y; else return x%y;}int Arith_floor(int x, int y) { return Arith_div(x, y);}int Arith_ceiling(int x, int y) { return Arith_div(x, y) + (x%y != 0);}int main(int argc,char* argv[]){ int a=(-13)/5; int b=Arith_div(-13,5); int c=Arith_mod(-13,5); int d=Arith_ceiling(-13,5); int e=Arith_floor(-13,5); printf("a=%d/n",a); printf("b=%d/n",b); printf("c=%d/n",c); printf("d=%d/n",d); printf("e=%d/n",e);}
一个接口可能有多个实现,但其定义要符合接口的声明,然而c语言中并没有提供某种机制检查实现的一致性/***************3.堆栈***************/我们再来看一个关于抽象数据类型(ADT)的例子:Stack
先看接口:
#ifndef STACK_INCLUDED#define STACK_INCLUDED#define T Stack_Ttypedef
struct T *T;
extern T Stack_new (
void);
extern int Stack_empty(T stk);
extern void Stack_push (T stk,
void *x);
extern void *Stack_pop (T stk);
extern void Stack_free (T *stk);
#undef T
#endif
很简洁,也无需赘述。再来看看实现
#include <stdlib.h>#include "assert.h"//该书作者自己写的头文件#include "mem.h" //该书作者自己写的头文件#include "stack.h"#define T Stack_T
struct T {
int count;
struct elem {
void *x;
struct elem *link; } *head;};T Stack_new(
void) { T stk; NEW(stk); stk->count = 0; stk->head = NULL;
return stk;}
int Stack_empty(T stk) { assert(stk);
return stk->count == 0;}
void Stack_push(T stk,
void *x) {
struct elem *t; assert(stk); NEW(t); t->x = x; t->link = stk->head; stk->head = t; stk->count++;}
void *Stack_pop(T stk) {
void *x;
struct elem *t; assert(stk); assert(stk->count > 0); t = stk->head; stk->head = t->link; stk->count--; x = t->x; FREE(t);
return x;}
void Stack_free(T *stk) {
struct elem *t, *u; assert(stk && *stk);
for (t = (*stk)->head; t; t = u) { u = t->link; FREE(t); } FREE(*stk);}
当一个抽象数据类型用隐式指针表示时,返回的类型也是一个指针类型,所以把Stack_T定义为一个指向结构体Stack_T的指针,所以以上表达式中,stk可以用用->符号获取结构体元素