第1章 简介
1. literate程序
2. 宏指令与条件编译指令
第2章 接口与实现
1. 接口与实现的关系
2. Arith接口及实现:
arith.h:
/*
$Id: H:/drh/idioms/book/RCS/inter.doc,v 1.11 1997/02/21 19:42:15 drh Exp $
*/
extern 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);
extern 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);
arith.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/inter.doc,v 1.11 1997/02/21 19:42:15 drh Exp $
";
#include " arith.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);
}
#include " arith.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);
}
3. 抽象数据类型Stack
4. 客户调用程序的责任
stack.h
View Code
stack.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/inter.doc,v 1.11 1997/02/21 19:42:15 drh Exp $
";
#include <stddef.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);
}
#include <stddef.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);
}
第3章 原子
1. 接口
atom.h:
View Code
atom.c:
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/atom.doc,v 1.10 1997/02/21 19:42:46 drh Exp $
";
#include " atom.h "
#include < string.h>
#include " assert.h "
#include <limits.h>
#include " mem.h "
#define NELEMS(x) ((sizeof (x))/(sizeof ((x)[0])))
static struct atom {
struct atom *link;
int len;
char *str;
} *buckets[ 2048];
static unsigned long scatter[] = {
2078917053, 143302914, 1027100827, 1953210302, 755253631, 2002600785,
1405390230, 45248011, 1099951567, 433832350, 2018585307, 438263339,
813528929, 1703199216, 618906479, 573714703, 766270699, 275680090,
1510320440, 1583583926, 1723401032, 1965443329, 1098183682, 1636505764,
980071615, 1011597961, 643279273, 1315461275, 157584038, 1069844923,
471560540, 89017443, 1213147837, 1498661368, 2042227746, 1968401469,
1353778505, 1300134328, 2013649480, 306246424, 1733966678, 1884751139,
744509763, 400011959, 1440466707, 1363416242, 973726663, 59253759,
1639096332, 336563455, 1642837685, 1215013716, 154523136, 593537720,
704035832, 1134594751, 1605135681, 1347315106, 302572379, 1762719719,
269676381, 774132919, 1851737163, 1482824219, 125310639, 1746481261,
1303742040, 1479089144, 899131941, 1169907872, 1785335569, 485614972,
907175364, 382361684, 885626931, 200158423, 1745777927, 1859353594,
259412182, 1237390611, 48433401, 1902249868, 304920680, 202956538,
348303940, 1008956512, 1337551289, 1953439621, 208787970, 1640123668,
1568675693, 478464352, 266772940, 1272929208, 1961288571, 392083579,
871926821, 1117546963, 1871172724, 1771058762, 139971187, 1509024645,
109190086, 1047146551, 1891386329, 994817018, 1247304975, 1489680608,
706686964, 1506717157, 579587572, 755120366, 1261483377, 884508252,
958076904, 1609787317, 1893464764, 148144545, 1415743291, 2102252735,
1788268214, 836935336, 433233439, 2055041154, 2109864544, 247038362,
299641085, 834307717, 1364585325, 23330161, 457882831, 1504556512,
1532354806, 567072918, 404219416, 1276257488, 1561889936, 1651524391,
618454448, 121093252, 1010757900, 1198042020, 876213618, 124757630,
2082550272, 1834290522, 1734544947, 1828531389, 1982435068, 1002804590,
1783300476, 1623219634, 1839739926, 69050267, 1530777140, 1802120822,
316088629, 1830418225, 488944891, 1680673954, 1853748387, 946827723,
1037746818, 1238619545, 1513900641, 1441966234, 367393385, 928306929,
946006977, 985847834, 1049400181, 1956764878, 36406206, 1925613800,
2081522508, 2118956479, 1612420674, 1668583807, 1800004220, 1447372094,
523904750, 1435821048, 923108080, 216161028, 1504871315, 306401572,
2018281851, 1820959944, 2136819798, 359743094, 1354150250, 1843084537,
1306570817, 244413420, 934220434, 672987810, 1686379655, 1301613820,
1601294739, 484902984, 139978006, 503211273, 294184214, 176384212,
281341425, 228223074, 147857043, 1893762099, 1896806882, 1947861263,
1193650546, 273227984, 1236198663, 2116758626, 489389012, 593586330,
275676551, 360187215, 267062626, 265012701, 719930310, 1621212876,
2108097238, 2026501127, 1865626297, 894834024, 552005290, 1404522304,
48964196, 5816381, 1889425288, 188942202, 509027654, 36125855,
365326415, 790369079, 264348929, 513183458, 536647531, 13672163,
313561074, 1730298077, 286900147, 1549759737, 1699573055, 776289160,
2143346068, 1975249606, 1136476375, 262925046, 92778659, 1856406685,
1884137923, 53392249, 1735424165, 1602280572
};
const char *Atom_string( const char *str) {
assert(str);
return Atom_new(str, strlen(str));
}
const char *Atom_int( long n) {
char str[ 43];
char *s = str + sizeof str;
unsigned long m;
if (n == LONG_MIN)
m = LONG_MAX + 1UL;
else if (n < 0)
m = -n;
else
m = n;
do
*--s = m% 10 + ' 0 ';
while ((m /= 10) > 0);
if (n < 0)
*--s = ' - ';
return Atom_new(s, (str + sizeof str) - s);
}
const char *Atom_new( const char *str, int len) {
unsigned long h;
int i;
struct atom *p;
assert(str);
assert(len >= 0);
for (h = 0, i = 0; i < len; i++)
h = (h<< 1) + scatter[(unsigned char)str[i]];
h &= NELEMS(buckets)- 1;
for (p = buckets[h]; p; p = p->link)
if (len == p->len) {
for (i = 0; i < len && p->str[i] == str[i]; )
i++;
if (i == len)
return p->str;
}
p = ALLOC( sizeof (*p) + len + 1);
p->len = len;
p->str = ( char *)(p + 1);
if (len > 0)
memcpy(p->str, str, len);
p->str[len] = ' \0 ';
p->link = buckets[h];
buckets[h] = p;
return p->str;
}
int Atom_length( const char *str) {
struct atom *p;
int i;
assert(str);
for (i = 0; i < NELEMS(buckets); i++)
for (p = buckets[i]; p; p = p->link)
if (p->str == str)
return p->len;
assert( 0);
return 0;
}
#include " atom.h "
#include < string.h>
#include " assert.h "
#include <limits.h>
#include " mem.h "
#define NELEMS(x) ((sizeof (x))/(sizeof ((x)[0])))
static struct atom {
struct atom *link;
int len;
char *str;
} *buckets[ 2048];
static unsigned long scatter[] = {
2078917053, 143302914, 1027100827, 1953210302, 755253631, 2002600785,
1405390230, 45248011, 1099951567, 433832350, 2018585307, 438263339,
813528929, 1703199216, 618906479, 573714703, 766270699, 275680090,
1510320440, 1583583926, 1723401032, 1965443329, 1098183682, 1636505764,
980071615, 1011597961, 643279273, 1315461275, 157584038, 1069844923,
471560540, 89017443, 1213147837, 1498661368, 2042227746, 1968401469,
1353778505, 1300134328, 2013649480, 306246424, 1733966678, 1884751139,
744509763, 400011959, 1440466707, 1363416242, 973726663, 59253759,
1639096332, 336563455, 1642837685, 1215013716, 154523136, 593537720,
704035832, 1134594751, 1605135681, 1347315106, 302572379, 1762719719,
269676381, 774132919, 1851737163, 1482824219, 125310639, 1746481261,
1303742040, 1479089144, 899131941, 1169907872, 1785335569, 485614972,
907175364, 382361684, 885626931, 200158423, 1745777927, 1859353594,
259412182, 1237390611, 48433401, 1902249868, 304920680, 202956538,
348303940, 1008956512, 1337551289, 1953439621, 208787970, 1640123668,
1568675693, 478464352, 266772940, 1272929208, 1961288571, 392083579,
871926821, 1117546963, 1871172724, 1771058762, 139971187, 1509024645,
109190086, 1047146551, 1891386329, 994817018, 1247304975, 1489680608,
706686964, 1506717157, 579587572, 755120366, 1261483377, 884508252,
958076904, 1609787317, 1893464764, 148144545, 1415743291, 2102252735,
1788268214, 836935336, 433233439, 2055041154, 2109864544, 247038362,
299641085, 834307717, 1364585325, 23330161, 457882831, 1504556512,
1532354806, 567072918, 404219416, 1276257488, 1561889936, 1651524391,
618454448, 121093252, 1010757900, 1198042020, 876213618, 124757630,
2082550272, 1834290522, 1734544947, 1828531389, 1982435068, 1002804590,
1783300476, 1623219634, 1839739926, 69050267, 1530777140, 1802120822,
316088629, 1830418225, 488944891, 1680673954, 1853748387, 946827723,
1037746818, 1238619545, 1513900641, 1441966234, 367393385, 928306929,
946006977, 985847834, 1049400181, 1956764878, 36406206, 1925613800,
2081522508, 2118956479, 1612420674, 1668583807, 1800004220, 1447372094,
523904750, 1435821048, 923108080, 216161028, 1504871315, 306401572,
2018281851, 1820959944, 2136819798, 359743094, 1354150250, 1843084537,
1306570817, 244413420, 934220434, 672987810, 1686379655, 1301613820,
1601294739, 484902984, 139978006, 503211273, 294184214, 176384212,
281341425, 228223074, 147857043, 1893762099, 1896806882, 1947861263,
1193650546, 273227984, 1236198663, 2116758626, 489389012, 593586330,
275676551, 360187215, 267062626, 265012701, 719930310, 1621212876,
2108097238, 2026501127, 1865626297, 894834024, 552005290, 1404522304,
48964196, 5816381, 1889425288, 188942202, 509027654, 36125855,
365326415, 790369079, 264348929, 513183458, 536647531, 13672163,
313561074, 1730298077, 286900147, 1549759737, 1699573055, 776289160,
2143346068, 1975249606, 1136476375, 262925046, 92778659, 1856406685,
1884137923, 53392249, 1735424165, 1602280572
};
const char *Atom_string( const char *str) {
assert(str);
return Atom_new(str, strlen(str));
}
const char *Atom_int( long n) {
char str[ 43];
char *s = str + sizeof str;
unsigned long m;
if (n == LONG_MIN)
m = LONG_MAX + 1UL;
else if (n < 0)
m = -n;
else
m = n;
do
*--s = m% 10 + ' 0 ';
while ((m /= 10) > 0);
if (n < 0)
*--s = ' - ';
return Atom_new(s, (str + sizeof str) - s);
}
const char *Atom_new( const char *str, int len) {
unsigned long h;
int i;
struct atom *p;
assert(str);
assert(len >= 0);
for (h = 0, i = 0; i < len; i++)
h = (h<< 1) + scatter[(unsigned char)str[i]];
h &= NELEMS(buckets)- 1;
for (p = buckets[h]; p; p = p->link)
if (len == p->len) {
for (i = 0; i < len && p->str[i] == str[i]; )
i++;
if (i == len)
return p->str;
}
p = ALLOC( sizeof (*p) + len + 1);
p->len = len;
p->str = ( char *)(p + 1);
if (len > 0)
memcpy(p->str, str, len);
p->str[len] = ' \0 ';
p->link = buckets[h];
buckets[h] = p;
return p->str;
}
int Atom_length( const char *str) {
struct atom *p;
int i;
assert(str);
for (i = 0; i < NELEMS(buckets); i++)
for (p = buckets[i]; p; p = p->link)
if (p->str == str)
return p->len;
assert( 0);
return 0;
}
第4章 异常与断言
except.h
/*
$Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $
*/
#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include <setjmp.h>
#define T Except_T
typedef struct T {
char *reason;
} T;
typedef struct Except_Frame Except_Frame;
struct Except_Frame {
Except_Frame *prev;
jmp_buf env;
const char *file;
int line;
const T *exception;
};
enum { Except_entered= 0, Except_raised,
Except_handled, Except_finalized };
#ifdef WIN32
__declspec(thread)
#endif
extern Except_Frame *Except_stack;
extern const Except_T Assert_Failed;
void Except_raise( const T *e, const char *file, int line);
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
Except_frame.file, Except_frame.line)
#define RETURN switch (Except_stack = Except_stack->prev,0) default: return
#define TRY do { \
volatile int Except_flag; \
Except_Frame Except_frame; \
Except_frame.prev = Except_stack; \
Except_stack = &Except_frame; \
Except_flag = setjmp(Except_frame.env); \
if (Except_flag == Except_entered) {
#define EXCEPT(e) \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} else if (Except_frame.exception == &(e)) { \
Except_flag = Except_handled;
#define ELSE \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} else { \
Except_flag = Except_handled;
#define FINALLY \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} { \
if (Except_flag == Except_entered) \
Except_flag = Except_finalized;
#define END_TRY \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} if (Except_flag == Except_raised) RERAISE; \
} while ( 0)
#undef T
#endif
#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include <setjmp.h>
#define T Except_T
typedef struct T {
char *reason;
} T;
typedef struct Except_Frame Except_Frame;
struct Except_Frame {
Except_Frame *prev;
jmp_buf env;
const char *file;
int line;
const T *exception;
};
enum { Except_entered= 0, Except_raised,
Except_handled, Except_finalized };
#ifdef WIN32
__declspec(thread)
#endif
extern Except_Frame *Except_stack;
extern const Except_T Assert_Failed;
void Except_raise( const T *e, const char *file, int line);
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
Except_frame.file, Except_frame.line)
#define RETURN switch (Except_stack = Except_stack->prev,0) default: return
#define TRY do { \
volatile int Except_flag; \
Except_Frame Except_frame; \
Except_frame.prev = Except_stack; \
Except_stack = &Except_frame; \
Except_flag = setjmp(Except_frame.env); \
if (Except_flag == Except_entered) {
#define EXCEPT(e) \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} else if (Except_frame.exception == &(e)) { \
Except_flag = Except_handled;
#define ELSE \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} else { \
Except_flag = Except_handled;
#define FINALLY \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} { \
if (Except_flag == Except_entered) \
Except_flag = Except_finalized;
#define END_TRY \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} if (Except_flag == Except_raised) RERAISE; \
} while ( 0)
#undef T
#endif
except.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $
";
#include <stdlib.h>
#include <stdio.h>
#include " assert.h "
#include " except.h "
#define T Except_T
#ifdef WIN32
__declspec(thread)
#endif
Except_Frame *Except_stack = NULL;
void Except_raise( const T *e, const char *file,
int line) {
Except_Frame *p = Except_stack;
assert(e);
if (p == NULL) {
fprintf(stderr, " Uncaught exception ");
if (e->reason)
fprintf(stderr, " %s ", e->reason);
else
fprintf(stderr, " at 0x%p ", e);
if (file && line > 0)
fprintf(stderr, " raised at %s:%d\n ", file, line);
fprintf(stderr, " aborting...\n ");
fflush(stderr);
abort();
}
p->exception = e;
p->file = file;
p->line = line;
Except_stack = Except_stack->prev;
longjmp(p->env, Except_raised);
}
#include <stdlib.h>
#include <stdio.h>
#include " assert.h "
#include " except.h "
#define T Except_T
#ifdef WIN32
__declspec(thread)
#endif
Except_Frame *Except_stack = NULL;
void Except_raise( const T *e, const char *file,
int line) {
Except_Frame *p = Except_stack;
assert(e);
if (p == NULL) {
fprintf(stderr, " Uncaught exception ");
if (e->reason)
fprintf(stderr, " %s ", e->reason);
else
fprintf(stderr, " at 0x%p ", e);
if (file && line > 0)
fprintf(stderr, " raised at %s:%d\n ", file, line);
fprintf(stderr, " aborting...\n ");
fflush(stderr);
abort();
}
p->exception = e;
p->file = file;
p->line = line;
Except_stack = Except_stack->prev;
longjmp(p->env, Except_raised);
}
assert.h
/*
$Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $
*/
#undef assert
#ifdef NDEBUG
#define assert(e) ((void)0)
#else
#include " except.h "
extern void assert( int e);
#define assert(e) ((void)((e)||(RAISE(Assert_Failed),0)))
#endif
#undef assert
#ifdef NDEBUG
#define assert(e) ((void)0)
#else
#include " except.h "
extern void assert( int e);
#define assert(e) ((void)((e)||(RAISE(Assert_Failed),0)))
#endif
assert.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $
";
#include " assert.h "
const Except_T Assert_Failed = { " Assertion failed " };
void (assert)( int e) {
assert(e);
}
#include " assert.h "
const Except_T Assert_Failed = { " Assertion failed " };
void (assert)( int e) {
assert(e);
}
第5章 内存管理
MEM分配接口
mem.h
/*
$Id: H:/drh/idioms/book/RCS/mem.doc,v 1.12 1997/10/27 23:08:05 drh Exp $
*/
#ifndef MEM_INCLUDED
#define MEM_INCLUDED
#include " except.h "
extern const Except_T Mem_Failed;
extern void *Mem_alloc ( long nbytes,
const char *file, int line);
extern void *Mem_calloc( long count, long nbytes,
const char *file, int line);
extern void Mem_free( void *ptr,
const char *file, int line);
extern void *Mem_resize( void *ptr, long nbytes,
const char *file, int line);
#define ALLOC(nbytes) \
Mem_alloc((nbytes), __FILE__, __LINE__)
#define CALLOC(count, nbytes) \
Mem_calloc((count), (nbytes), __FILE__, __LINE__)
#define NEW(p) ((p) = ALLOC((long)sizeof *(p)))
#define NEW0(p) ((p) = CALLOC(1, (long)sizeof *(p)))
#define FREE(ptr) ((void)(Mem_free((ptr), \
__FILE__, __LINE__), (ptr) = 0))
#define RESIZE(ptr, nbytes) ((ptr) = Mem_resize((ptr), \
(nbytes), __FILE__, __LINE__))
#endif
#ifndef MEM_INCLUDED
#define MEM_INCLUDED
#include " except.h "
extern const Except_T Mem_Failed;
extern void *Mem_alloc ( long nbytes,
const char *file, int line);
extern void *Mem_calloc( long count, long nbytes,
const char *file, int line);
extern void Mem_free( void *ptr,
const char *file, int line);
extern void *Mem_resize( void *ptr, long nbytes,
const char *file, int line);
#define ALLOC(nbytes) \
Mem_alloc((nbytes), __FILE__, __LINE__)
#define CALLOC(count, nbytes) \
Mem_calloc((count), (nbytes), __FILE__, __LINE__)
#define NEW(p) ((p) = ALLOC((long)sizeof *(p)))
#define NEW0(p) ((p) = CALLOC(1, (long)sizeof *(p)))
#define FREE(ptr) ((void)(Mem_free((ptr), \
__FILE__, __LINE__), (ptr) = 0))
#define RESIZE(ptr, nbytes) ((ptr) = Mem_resize((ptr), \
(nbytes), __FILE__, __LINE__))
#endif
mem.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/mem.doc,v 1.12 1997/10/27 23:08:05 drh Exp $
";
#include <stdlib.h>
#include <stddef.h>
#include " assert.h "
#include " except.h "
#include " mem.h "
const Except_T Mem_Failed = { " Allocation Failed " };
void *Mem_alloc( long nbytes, const char *file, int line){
void *ptr;
assert(nbytes > 0);
ptr = malloc(nbytes);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed, file, line);
}
return ptr;
}
void *Mem_calloc( long count, long nbytes,
const char *file, int line) {
void *ptr;
assert(count > 0);
assert(nbytes > 0);
ptr = calloc(count, nbytes);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed, file, line);
}
return ptr;
}
void Mem_free( void *ptr, const char *file, int line) {
if (ptr)
free(ptr);
}
void *Mem_resize( void *ptr, long nbytes,
const char *file, int line) {
assert(ptr);
assert(nbytes > 0);
ptr = realloc(ptr, nbytes);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed, file, line);
}
return ptr;
}
#include <stdlib.h>
#include <stddef.h>
#include " assert.h "
#include " except.h "
#include " mem.h "
const Except_T Mem_Failed = { " Allocation Failed " };
void *Mem_alloc( long nbytes, const char *file, int line){
void *ptr;
assert(nbytes > 0);
ptr = malloc(nbytes);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed, file, line);
}
return ptr;
}
void *Mem_calloc( long count, long nbytes,
const char *file, int line) {
void *ptr;
assert(count > 0);
assert(nbytes > 0);
ptr = calloc(count, nbytes);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed, file, line);
}
return ptr;
}
void Mem_free( void *ptr, const char *file, int line) {
if (ptr)
free(ptr);
}
void *Mem_resize( void *ptr, long nbytes,
const char *file, int line) {
assert(ptr);
assert(nbytes > 0);
ptr = realloc(ptr, nbytes);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Mem_Failed);
else
Except_raise(&Mem_Failed, file, line);
}
return ptr;
}
第6章 进一步内存管理
arena.h
View Code
arena.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/arena.doc,v 1.10 1997/02/21 19:45:19 drh Exp $
";
#include <stdlib.h>
#include < string.h>
#include " assert.h "
#include " except.h "
#include " arena.h "
#define T Arena_T
const Except_T Arena_NewFailed =
{ " Arena Creation Failed " };
const Except_T Arena_Failed =
{ " Arena Allocation Failed " };
#define THRESHOLD 10
struct T {
T prev;
char *avail;
char *limit;
};
union align {
#ifdef MAXALIGN
char pad[MAXALIGN];
#else
int i;
long l;
long *lp;
void *p;
void (*fp)( void);
float f;
double d;
long double ld;
#endif
};
union header {
struct T b;
union align a;
};
static T freechunks;
static int nfree;
T Arena_new( void) {
T arena = malloc( sizeof (*arena));
if (arena == NULL)
RAISE(Arena_NewFailed);
arena->prev = NULL;
arena->limit = arena->avail = NULL;
return arena;
}
void Arena_dispose(T *ap) {
assert(ap && *ap);
Arena_free(*ap);
free(*ap);
*ap = NULL;
}
void *Arena_alloc(T arena, long nbytes,
const char *file, int line) {
assert(arena);
assert(nbytes > 0);
nbytes = ((nbytes + sizeof (union align) - 1)/
( sizeof (union align)))*( sizeof (union align));
while (nbytes > arena->limit - arena->avail) {
T ptr;
char *limit;
if ((ptr = freechunks) != NULL) {
freechunks = freechunks->prev;
nfree--;
limit = ptr->limit;
} else {
long m = sizeof (union header) + nbytes + 10* 1024;
ptr = malloc(m);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Arena_Failed);
else
Except_raise(&Arena_Failed, file, line);
}
limit = ( char *)ptr + m;
}
*ptr = *arena;
arena->avail = ( char *)((union header *)ptr + 1);
arena->limit = limit;
arena->prev = ptr;
}
arena->avail += nbytes;
return arena->avail - nbytes;
}
void *Arena_calloc(T arena, long count, long nbytes,
const char *file, int line) {
void *ptr;
assert(count > 0);
ptr = Arena_alloc(arena, count*nbytes, file, line);
memset(ptr, ' \0 ', count*nbytes);
return ptr;
}
void Arena_free(T arena) {
assert(arena);
while (arena->prev) {
struct T tmp = *arena->prev;
if (nfree < THRESHOLD) {
arena->prev->prev = freechunks;
freechunks = arena->prev;
nfree++;
freechunks->limit = arena->limit;
} else
free(arena->prev);
*arena = tmp;
}
assert(arena->limit == NULL);
assert(arena->avail == NULL);
}
#include <stdlib.h>
#include < string.h>
#include " assert.h "
#include " except.h "
#include " arena.h "
#define T Arena_T
const Except_T Arena_NewFailed =
{ " Arena Creation Failed " };
const Except_T Arena_Failed =
{ " Arena Allocation Failed " };
#define THRESHOLD 10
struct T {
T prev;
char *avail;
char *limit;
};
union align {
#ifdef MAXALIGN
char pad[MAXALIGN];
#else
int i;
long l;
long *lp;
void *p;
void (*fp)( void);
float f;
double d;
long double ld;
#endif
};
union header {
struct T b;
union align a;
};
static T freechunks;
static int nfree;
T Arena_new( void) {
T arena = malloc( sizeof (*arena));
if (arena == NULL)
RAISE(Arena_NewFailed);
arena->prev = NULL;
arena->limit = arena->avail = NULL;
return arena;
}
void Arena_dispose(T *ap) {
assert(ap && *ap);
Arena_free(*ap);
free(*ap);
*ap = NULL;
}
void *Arena_alloc(T arena, long nbytes,
const char *file, int line) {
assert(arena);
assert(nbytes > 0);
nbytes = ((nbytes + sizeof (union align) - 1)/
( sizeof (union align)))*( sizeof (union align));
while (nbytes > arena->limit - arena->avail) {
T ptr;
char *limit;
if ((ptr = freechunks) != NULL) {
freechunks = freechunks->prev;
nfree--;
limit = ptr->limit;
} else {
long m = sizeof (union header) + nbytes + 10* 1024;
ptr = malloc(m);
if (ptr == NULL)
{
if (file == NULL)
RAISE(Arena_Failed);
else
Except_raise(&Arena_Failed, file, line);
}
limit = ( char *)ptr + m;
}
*ptr = *arena;
arena->avail = ( char *)((union header *)ptr + 1);
arena->limit = limit;
arena->prev = ptr;
}
arena->avail += nbytes;
return arena->avail - nbytes;
}
void *Arena_calloc(T arena, long count, long nbytes,
const char *file, int line) {
void *ptr;
assert(count > 0);
ptr = Arena_alloc(arena, count*nbytes, file, line);
memset(ptr, ' \0 ', count*nbytes);
return ptr;
}
void Arena_free(T arena) {
assert(arena);
while (arena->prev) {
struct T tmp = *arena->prev;
if (nfree < THRESHOLD) {
arena->prev->prev = freechunks;
freechunks = arena->prev;
nfree++;
freechunks->limit = arena->limit;
} else
free(arena->prev);
*arena = tmp;
}
assert(arena->limit == NULL);
assert(arena->avail == NULL);
}
第7章 链表
list.h
/*
$Id: H:/drh/idioms/book/RCS/list.doc,v 1.11 1997/02/21 19:46:01 drh Exp $
*/
#ifndef LIST_INCLUDED
#define LIST_INCLUDED
#define T List_T
typedef struct T *T;
struct T {
T rest;
void *first;
};
extern T List_append (T list, T tail);
extern T List_copy (T list);
extern T List_list ( void *x, ...);
extern T List_pop (T list, void **x);
extern T List_push (T list, void *x);
extern T List_reverse(T list);
extern int List_length (T list);
extern void List_free (T *list);
extern void List_map (T list,
void apply( void **x, void *cl), void *cl);
extern void **List_toArray(T list, void *end);
#undef T
#endif
#ifndef LIST_INCLUDED
#define LIST_INCLUDED
#define T List_T
typedef struct T *T;
struct T {
T rest;
void *first;
};
extern T List_append (T list, T tail);
extern T List_copy (T list);
extern T List_list ( void *x, ...);
extern T List_pop (T list, void **x);
extern T List_push (T list, void *x);
extern T List_reverse(T list);
extern int List_length (T list);
extern void List_free (T *list);
extern void List_map (T list,
void apply( void **x, void *cl), void *cl);
extern void **List_toArray(T list, void *end);
#undef T
#endif
list.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/list.doc,v 1.11 1997/02/21 19:46:01 drh Exp $
";
#include <stdarg.h>
#include <stddef.h>
#include " assert.h "
#include " mem.h "
#include " list.h "
#define T List_T
T List_push(T list, void *x) {
T p;
NEW(p);
p->first = x;
p->rest = list;
return p;
}
T List_list( void *x, ...) {
va_list ap;
T list, *p = &list;
va_start(ap, x);
for ( ; x; x = va_arg(ap, void *)) {
NEW(*p);
(*p)->first = x;
p = &(*p)->rest;
}
*p = NULL;
va_end(ap);
return list;
}
T List_append(T list, T tail) {
T *p = &list;
while (*p)
p = &(*p)->rest;
*p = tail;
return list;
}
T List_copy(T list) {
T head, *p = &head;
for ( ; list; list = list->rest) {
NEW(*p);
(*p)->first = list->first;
p = &(*p)->rest;
}
*p = NULL;
return head;
}
T List_pop(T list, void **x) {
if (list) {
T head = list->rest;
if (x)
*x = list->first;
FREE(list);
return head;
} else
return list;
}
T List_reverse(T list) {
T head = NULL, next;
for ( ; list; list = next) {
next = list->rest;
list->rest = head;
head = list;
}
return head;
}
int List_length(T list) {
int n;
for (n = 0; list; list = list->rest)
n++;
return n;
}
void List_free(T *list) {
T next;
assert(list);
for ( ; *list; *list = next) {
next = (*list)->rest;
FREE(*list);
}
}
void List_map(T list,
void apply( void **x, void *cl), void *cl) {
assert(apply);
for ( ; list; list = list->rest)
apply(&list->first, cl);
}
void **List_toArray(T list, void *end) {
int i, n = List_length(list);
void **array = ALLOC((n + 1)* sizeof (*array));
for (i = 0; i < n; i++) {
array[i] = list->first;
list = list->rest;
}
array[i] = end;
return array;
}
#include <stdarg.h>
#include <stddef.h>
#include " assert.h "
#include " mem.h "
#include " list.h "
#define T List_T
T List_push(T list, void *x) {
T p;
NEW(p);
p->first = x;
p->rest = list;
return p;
}
T List_list( void *x, ...) {
va_list ap;
T list, *p = &list;
va_start(ap, x);
for ( ; x; x = va_arg(ap, void *)) {
NEW(*p);
(*p)->first = x;
p = &(*p)->rest;
}
*p = NULL;
va_end(ap);
return list;
}
T List_append(T list, T tail) {
T *p = &list;
while (*p)
p = &(*p)->rest;
*p = tail;
return list;
}
T List_copy(T list) {
T head, *p = &head;
for ( ; list; list = list->rest) {
NEW(*p);
(*p)->first = list->first;
p = &(*p)->rest;
}
*p = NULL;
return head;
}
T List_pop(T list, void **x) {
if (list) {
T head = list->rest;
if (x)
*x = list->first;
FREE(list);
return head;
} else
return list;
}
T List_reverse(T list) {
T head = NULL, next;
for ( ; list; list = next) {
next = list->rest;
list->rest = head;
head = list;
}
return head;
}
int List_length(T list) {
int n;
for (n = 0; list; list = list->rest)
n++;
return n;
}
void List_free(T *list) {
T next;
assert(list);
for ( ; *list; *list = next) {
next = (*list)->rest;
FREE(*list);
}
}
void List_map(T list,
void apply( void **x, void *cl), void *cl) {
assert(apply);
for ( ; list; list = list->rest)
apply(&list->first, cl);
}
void **List_toArray(T list, void *end) {
int i, n = List_length(list);
void **array = ALLOC((n + 1)* sizeof (*array));
for (i = 0; i < n; i++) {
array[i] = list->first;
list = list->rest;
}
array[i] = end;
return array;
}
第8章 表格
table.h
/*
$Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $
*/
#ifndef TABLE_INCLUDED
#define TABLE_INCLUDED
#define T Table_T
typedef struct T *T;
extern T Table_new ( int hint,
int cmp( const void *x, const void *y),
unsigned hash( const void *key));
extern void Table_free(T *table);
extern int Table_length(T table);
extern void *Table_put (T table, const void *key,
void *value);
extern void *Table_get (T table, const void *key);
extern void *Table_remove(T table, const void *key);
extern void Table_map (T table,
void apply( const void *key, void **value, void *cl),
void *cl);
extern void **Table_toArray(T table, void *end);
#undef T
#endif
#ifndef TABLE_INCLUDED
#define TABLE_INCLUDED
#define T Table_T
typedef struct T *T;
extern T Table_new ( int hint,
int cmp( const void *x, const void *y),
unsigned hash( const void *key));
extern void Table_free(T *table);
extern int Table_length(T table);
extern void *Table_put (T table, const void *key,
void *value);
extern void *Table_get (T table, const void *key);
extern void *Table_remove(T table, const void *key);
extern void Table_map (T table,
void apply( const void *key, void **value, void *cl),
void *cl);
extern void **Table_toArray(T table, void *end);
#undef T
#endif
table.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $
";
#include <limits.h>
#include <stddef.h>
#include " mem.h "
#include " assert.h "
#include " table.h "
#define T Table_T
struct T {
int size;
int (*cmp)( const void *x, const void *y);
unsigned (*hash)( const void *key);
int length;
unsigned timestamp;
struct binding {
struct binding *link;
const void *key;
void *value;
} **buckets;
};
static int cmpatom( const void *x, const void *y) {
return x != y;
}
static unsigned hashatom( const void *key) {
return (unsigned long)key>> 2;
}
T Table_new( int hint,
int cmp( const void *x, const void *y),
unsigned hash( const void *key)) {
T table;
int i;
static int primes[] = { 509, 509, 1021, 2053, 4093,
8191, 16381, 32771, 65521, INT_MAX };
assert(hint >= 0);
for (i = 1; primes[i] < hint; i++)
;
table = ALLOC( sizeof (*table) +
primes[i- 1]* sizeof (table->buckets[ 0]));
table->size = primes[i- 1];
table->cmp = cmp ? cmp : cmpatom;
table->hash = hash ? hash : hashatom;
table->buckets = ( struct binding **)(table + 1);
for (i = 0; i < table->size; i++)
table->buckets[i] = NULL;
table->length = 0;
table->timestamp = 0;
return table;
}
void *Table_get(T table, const void *key) {
int i;
struct binding *p;
assert(table);
assert(key);
i = (*table->hash)(key)%table->size;
for (p = table->buckets[i]; p; p = p->link)
if ((*table->cmp)(key, p->key) == 0)
break;
return p ? p->value : NULL;
}
void *Table_put(T table, const void *key, void *value) {
int i;
struct binding *p;
void *prev;
assert(table);
assert(key);
i = (*table->hash)(key)%table->size;
for (p = table->buckets[i]; p; p = p->link)
if ((*table->cmp)(key, p->key) == 0)
break;
if (p == NULL) {
NEW(p);
p->key = key;
p->link = table->buckets[i];
table->buckets[i] = p;
table->length++;
prev = NULL;
} else
prev = p->value;
p->value = value;
table->timestamp++;
return prev;
}
int Table_length(T table) {
assert(table);
return table->length;
}
void Table_map(T table,
void apply( const void *key, void **value, void *cl),
void *cl) {
int i;
unsigned stamp;
struct binding *p;
assert(table);
assert(apply);
stamp = table->timestamp;
for (i = 0; i < table->size; i++)
for (p = table->buckets[i]; p; p = p->link) {
apply(p->key, &p->value, cl);
assert(table->timestamp == stamp);
}
}
void *Table_remove(T table, const void *key) {
int i;
struct binding **pp;
assert(table);
assert(key);
table->timestamp++;
i = (*table->hash)(key)%table->size;
for (pp = &table->buckets[i]; *pp; pp = &(*pp)->link)
if ((*table->cmp)(key, (*pp)->key) == 0) {
struct binding *p = *pp;
void *value = p->value;
*pp = p->link;
FREE(p);
table->length--;
return value;
}
return NULL;
}
void **Table_toArray(T table, void *end) {
int i, j = 0;
void **array;
struct binding *p;
assert(table);
array = ALLOC(( 2*table->length + 1)* sizeof (*array));
for (i = 0; i < table->size; i++)
for (p = table->buckets[i]; p; p = p->link) {
array[j++] = ( void *)p->key;
array[j++] = p->value;
}
array[j] = end;
return array;
}
void Table_free(T *table) {
assert(table && *table);
if ((*table)->length > 0) {
int i;
struct binding *p, *q;
for (i = 0; i < (*table)->size; i++)
for (p = (*table)->buckets[i]; p; p = q) {
q = p->link;
FREE(p);
}
}
FREE(*table);
}
#include <limits.h>
#include <stddef.h>
#include " mem.h "
#include " assert.h "
#include " table.h "
#define T Table_T
struct T {
int size;
int (*cmp)( const void *x, const void *y);
unsigned (*hash)( const void *key);
int length;
unsigned timestamp;
struct binding {
struct binding *link;
const void *key;
void *value;
} **buckets;
};
static int cmpatom( const void *x, const void *y) {
return x != y;
}
static unsigned hashatom( const void *key) {
return (unsigned long)key>> 2;
}
T Table_new( int hint,
int cmp( const void *x, const void *y),
unsigned hash( const void *key)) {
T table;
int i;
static int primes[] = { 509, 509, 1021, 2053, 4093,
8191, 16381, 32771, 65521, INT_MAX };
assert(hint >= 0);
for (i = 1; primes[i] < hint; i++)
;
table = ALLOC( sizeof (*table) +
primes[i- 1]* sizeof (table->buckets[ 0]));
table->size = primes[i- 1];
table->cmp = cmp ? cmp : cmpatom;
table->hash = hash ? hash : hashatom;
table->buckets = ( struct binding **)(table + 1);
for (i = 0; i < table->size; i++)
table->buckets[i] = NULL;
table->length = 0;
table->timestamp = 0;
return table;
}
void *Table_get(T table, const void *key) {
int i;
struct binding *p;
assert(table);
assert(key);
i = (*table->hash)(key)%table->size;
for (p = table->buckets[i]; p; p = p->link)
if ((*table->cmp)(key, p->key) == 0)
break;
return p ? p->value : NULL;
}
void *Table_put(T table, const void *key, void *value) {
int i;
struct binding *p;
void *prev;
assert(table);
assert(key);
i = (*table->hash)(key)%table->size;
for (p = table->buckets[i]; p; p = p->link)
if ((*table->cmp)(key, p->key) == 0)
break;
if (p == NULL) {
NEW(p);
p->key = key;
p->link = table->buckets[i];
table->buckets[i] = p;
table->length++;
prev = NULL;
} else
prev = p->value;
p->value = value;
table->timestamp++;
return prev;
}
int Table_length(T table) {
assert(table);
return table->length;
}
void Table_map(T table,
void apply( const void *key, void **value, void *cl),
void *cl) {
int i;
unsigned stamp;
struct binding *p;
assert(table);
assert(apply);
stamp = table->timestamp;
for (i = 0; i < table->size; i++)
for (p = table->buckets[i]; p; p = p->link) {
apply(p->key, &p->value, cl);
assert(table->timestamp == stamp);
}
}
void *Table_remove(T table, const void *key) {
int i;
struct binding **pp;
assert(table);
assert(key);
table->timestamp++;
i = (*table->hash)(key)%table->size;
for (pp = &table->buckets[i]; *pp; pp = &(*pp)->link)
if ((*table->cmp)(key, (*pp)->key) == 0) {
struct binding *p = *pp;
void *value = p->value;
*pp = p->link;
FREE(p);
table->length--;
return value;
}
return NULL;
}
void **Table_toArray(T table, void *end) {
int i, j = 0;
void **array;
struct binding *p;
assert(table);
array = ALLOC(( 2*table->length + 1)* sizeof (*array));
for (i = 0; i < table->size; i++)
for (p = table->buckets[i]; p; p = p->link) {
array[j++] = ( void *)p->key;
array[j++] = p->value;
}
array[j] = end;
return array;
}
void Table_free(T *table) {
assert(table && *table);
if ((*table)->length > 0) {
int i;
struct binding *p, *q;
for (i = 0; i < (*table)->size; i++)
for (p = (*table)->buckets[i]; p; p = q) {
q = p->link;
FREE(p);
}
}
FREE(*table);
}
wf程序来统计单词的频率
getword.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $
";
#include <ctype.h>
#include < string.h>
#include <stdio.h>
#include " assert.h "
#include " getword.h "
int getword(FILE *fp, char *buf, int size,
int first( int c), int rest( int c)) {
int i = 0, c;
assert(fp && buf && size > 1 && first && rest);
c = getc(fp);
for ( ; c != EOF; c = getc(fp))
if (first(c)) {
{
if (i < size - 1)
buf[i++] = c;
}
c = getc(fp);
break;
}
for ( ; c != EOF && rest(c); c = getc(fp))
{
if (i < size - 1)
buf[i++] = c;
}
if (i < size)
buf[i] = ' \0 ';
else
buf[size- 1] = ' \0 ';
if (c != EOF)
ungetc(c, fp);
return i > 0;
}
#include <ctype.h>
#include < string.h>
#include <stdio.h>
#include " assert.h "
#include " getword.h "
int getword(FILE *fp, char *buf, int size,
int first( int c), int rest( int c)) {
int i = 0, c;
assert(fp && buf && size > 1 && first && rest);
c = getc(fp);
for ( ; c != EOF; c = getc(fp))
if (first(c)) {
{
if (i < size - 1)
buf[i++] = c;
}
c = getc(fp);
break;
}
for ( ; c != EOF && rest(c); c = getc(fp))
{
if (i < size - 1)
buf[i++] = c;
}
if (i < size)
buf[i] = ' \0 ';
else
buf[size- 1] = ' \0 ';
if (c != EOF)
ungetc(c, fp);
return i > 0;
}
wf.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $
";
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include " atom.h "
#include " table.h "
#include " mem.h "
#include " getword.h "
#include < string.h>
void wf( char *, FILE *);
int first( int c);
int rest ( int c);
int compare( const void *x, const void *y);
void vfree( const void *, void **, void *);
int main( int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
FILE *fp = fopen(argv[i], " r ");
if (fp == NULL) {
fprintf(stderr, " %s: can't open '%s' (%s)\n ",
argv[ 0], argv[i], strerror(errno));
return EXIT_FAILURE;
} else {
wf(argv[i], fp);
fclose(fp);
}
}
if (argc == 1) wf(NULL, stdin);
return EXIT_SUCCESS;
}
void wf( char *name, FILE *fp) {
Table_T table = Table_new( 0, NULL, NULL);
char buf[ 128];
while (getword(fp, buf, sizeof buf, first, rest)) {
const char *word;
int i, *count;
for (i = 0; buf[i] != ' \0 '; i++)
buf[i] = tolower(buf[i]);
word = Atom_string(buf);
count = Table_get(table, word);
if (count)
(*count)++;
else {
NEW(count);
*count = 1;
Table_put(table, word, count);
}
}
if (name)
printf( " %s:\n ", name);
{ int i;
void **array = Table_toArray(table, NULL);
qsort(array, Table_length(table), 2* sizeof (*array),
compare);
for (i = 0; array[i]; i += 2)
printf( " %d\t%s\n ", *( int *)array[i+ 1],
( char *)array[i]);
FREE(array); }
Table_map(table, vfree, NULL);
Table_free(&table);
}
int first( int c) {
return isalpha(c);
}
int rest( int c) {
return isalpha(c) || c == ' _ ';
}
int compare( const void *x, const void *y) {
return strcmp(*( char **)x, *( char **)y);
}
void vfree( const void *key, void **count, void *cl) {
FREE(*count);
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include " atom.h "
#include " table.h "
#include " mem.h "
#include " getword.h "
#include < string.h>
void wf( char *, FILE *);
int first( int c);
int rest ( int c);
int compare( const void *x, const void *y);
void vfree( const void *, void **, void *);
int main( int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
FILE *fp = fopen(argv[i], " r ");
if (fp == NULL) {
fprintf(stderr, " %s: can't open '%s' (%s)\n ",
argv[ 0], argv[i], strerror(errno));
return EXIT_FAILURE;
} else {
wf(argv[i], fp);
fclose(fp);
}
}
if (argc == 1) wf(NULL, stdin);
return EXIT_SUCCESS;
}
void wf( char *name, FILE *fp) {
Table_T table = Table_new( 0, NULL, NULL);
char buf[ 128];
while (getword(fp, buf, sizeof buf, first, rest)) {
const char *word;
int i, *count;
for (i = 0; buf[i] != ' \0 '; i++)
buf[i] = tolower(buf[i]);
word = Atom_string(buf);
count = Table_get(table, word);
if (count)
(*count)++;
else {
NEW(count);
*count = 1;
Table_put(table, word, count);
}
}
if (name)
printf( " %s:\n ", name);
{ int i;
void **array = Table_toArray(table, NULL);
qsort(array, Table_length(table), 2* sizeof (*array),
compare);
for (i = 0; array[i]; i += 2)
printf( " %d\t%s\n ", *( int *)array[i+ 1],
( char *)array[i]);
FREE(array); }
Table_map(table, vfree, NULL);
Table_free(&table);
}
int first( int c) {
return isalpha(c);
}
int rest( int c) {
return isalpha(c) || c == ' _ ';
}
int compare( const void *x, const void *y) {
return strcmp(*( char **)x, *( char **)y);
}
void vfree( const void *key, void **count, void *cl) {
FREE(*count);
}
第9章 集合
集合的实现
set.h
/*
$Id: H:/drh/idioms/book/RCS/set.doc,v 1.11 1996/06/26 23:02:01 drh Exp $
*/
#ifndef SET_INCLUDED
#define SET_INCLUDED
#define T Set_T
typedef struct T *T;
extern T Set_new ( int hint,
int cmp( const void *x, const void *y),
unsigned hash( const void *x));
extern void Set_free(T * set);
extern int Set_length(T set);
extern int Set_member(T set, const void *member);
extern void Set_put (T set, const void *member);
extern void *Set_remove(T set, const void *member);
extern void Set_map (T set,
void apply( const void *member, void *cl), void *cl);
extern void **Set_toArray(T set, void *end);
extern T Set_union(T s, T t);
extern T Set_inter(T s, T t);
extern T Set_minus(T s, T t);
extern T Set_diff (T s, T t);
#undef T
#endif
#ifndef SET_INCLUDED
#define SET_INCLUDED
#define T Set_T
typedef struct T *T;
extern T Set_new ( int hint,
int cmp( const void *x, const void *y),
unsigned hash( const void *x));
extern void Set_free(T * set);
extern int Set_length(T set);
extern int Set_member(T set, const void *member);
extern void Set_put (T set, const void *member);
extern void *Set_remove(T set, const void *member);
extern void Set_map (T set,
void apply( const void *member, void *cl), void *cl);
extern void **Set_toArray(T set, void *end);
extern T Set_union(T s, T t);
extern T Set_inter(T s, T t);
extern T Set_minus(T s, T t);
extern T Set_diff (T s, T t);
#undef T
#endif
set.c
static
char rcsid[] =
"
$Id: H:/drh/idioms/book/RCS/set.doc,v 1.11 1996/06/26 23:02:01 drh Exp $
";
#include <limits.h>
#include <stddef.h>
#include "
#include <limits.h>
#include <stddef.h>
#include "