这两道习题综合起来是利用散列表写个适用C语言的简单#define处理器,只能处理#define/#undef不带参数的情形,并且#define后面必须带值。不带值其实也就是加多一个处理,分辨#define语句是否已经结束。这里输入代码我用的是TCPL的getch, ungetch,其实本应该直接读入一个C文件,可是这里我偷懒了。读入文件的话处理代码差别也不大。我把代码分为几个模块:
hash.c:散列表相关代码
io.c:输入输出相关代码
main.c:测试
以下是代码hash.h:保留三个借口给其他模块调用
#ifndef HASH_H
#define HASH_H
struct nlist;
struct nlist * install( char * name, char * defn);
int undef( char * name);
void print( void );
#endif
#define HASH_H
struct nlist;
struct nlist * install( char * name, char * defn);
int undef( char * name);
void print( void );
#endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include
<
stdio.h
>
#include < stdlib.h >
#include < string .h >
struct nlist {
char * name; /* defined name */
char * defn; /* replaced value */
struct nlist * next; /* next node */
};
#define HASHSIZE 101
static struct nlist * hashtab[HASHSIZE];
void print( void )
{
struct nlist * np;
for ( int i = 0 ; i < HASHSIZE; ++ i) {
if (hashtab[i] != NULL) {
for (np = hashtab[i]; np != NULL; np = np -> next) {
printf( " name: %-10s defn: %-5s\n " , np -> name, np -> defn);
}
}
}
}
static char * strdup( char * s)
{
char * p;
p = ( char * )malloc(strlen(s) + 1 );
if (p != NULL) {
strcpy(p, s);
}
return p;
}
static unsigned int hash( char * s)
{
unsigned int hashval;
for (hashval = 0 ; * s != ' \0 ' ; ++ s) {
hashval = * s + 31 * hashval;
}
return hashval % HASHSIZE;
}
static struct nlist * lookup( char * s)
{
struct nlist * np;
for (np = hashtab[hash(s)]; np != NULL; np = np -> next) {
if (strcmp(s, np -> name) == 0 ) {
return np;
}
}
return NULL;
}
struct nlist * install( char * name, char * defn)
{
struct nlist * np;
unsigned int hashval;
if ( (np = lookup(name)) == NULL) {
np = ( struct nlist * )malloc( sizeof ( struct nlist));
if (np == NULL || (np -> name = strdup(name)) == NULL) {
return NULL;
}
hashval = hash(name);
np -> next = hashtab[hashval];
hashtab[hashval] = np;
} else {
free( ( void * )np -> defn); /* free the prev defn */
}
if ( (np -> defn = strdup(defn)) == NULL) {
return NULL;
}
return np;
}
int undef( char * name)
{
struct nlist * prev, * np;
unsigned int hashval;
if ( (np = lookup(name)) != NULL) {
hashval = hash(name);
prev = hashtab[hashval];
if (prev == np) {
printf( " only one node\n " );
free(np -> defn);
free(np -> name);
free(np);
} else {
printf( " more than one node\n " );
for ( ; prev -> next != np; prev = prev -> next)
;
prev -> next = np -> next;
free(np -> defn);
free(np -> name);
free(np);
}
return 0 ;
}
return - 1 ;
}
#include < stdlib.h >
#include < string .h >
struct nlist {
char * name; /* defined name */
char * defn; /* replaced value */
struct nlist * next; /* next node */
};
#define HASHSIZE 101
static struct nlist * hashtab[HASHSIZE];
void print( void )
{
struct nlist * np;
for ( int i = 0 ; i < HASHSIZE; ++ i) {
if (hashtab[i] != NULL) {
for (np = hashtab[i]; np != NULL; np = np -> next) {
printf( " name: %-10s defn: %-5s\n " , np -> name, np -> defn);
}
}
}
}
static char * strdup( char * s)
{
char * p;
p = ( char * )malloc(strlen(s) + 1 );
if (p != NULL) {
strcpy(p, s);
}
return p;
}
static unsigned int hash( char * s)
{
unsigned int hashval;
for (hashval = 0 ; * s != ' \0 ' ; ++ s) {
hashval = * s + 31 * hashval;
}
return hashval % HASHSIZE;
}
static struct nlist * lookup( char * s)
{
struct nlist * np;
for (np = hashtab[hash(s)]; np != NULL; np = np -> next) {
if (strcmp(s, np -> name) == 0 ) {
return np;
}
}
return NULL;
}
struct nlist * install( char * name, char * defn)
{
struct nlist * np;
unsigned int hashval;
if ( (np = lookup(name)) == NULL) {
np = ( struct nlist * )malloc( sizeof ( struct nlist));
if (np == NULL || (np -> name = strdup(name)) == NULL) {
return NULL;
}
hashval = hash(name);
np -> next = hashtab[hashval];
hashtab[hashval] = np;
} else {
free( ( void * )np -> defn); /* free the prev defn */
}
if ( (np -> defn = strdup(defn)) == NULL) {
return NULL;
}
return np;
}
int undef( char * name)
{
struct nlist * prev, * np;
unsigned int hashval;
if ( (np = lookup(name)) != NULL) {
hashval = hash(name);
prev = hashtab[hashval];
if (prev == np) {
printf( " only one node\n " );
free(np -> defn);
free(np -> name);
free(np);
} else {
printf( " more than one node\n " );
for ( ; prev -> next != np; prev = prev -> next)
;
prev -> next = np -> next;
free(np -> defn);
free(np -> name);
free(np);
}
return 0 ;
}
return - 1 ;
}
#ifndef IO_H
#define IO_H
int getword( char * word, int lim);
#endif
#define IO_H
int getword( char * word, int lim);
#endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include
<
stdio.h
>
#include < stdlib.h >
#include < string .h >
#include < ctype.h >
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0 ;
int getch( void )
{
return bufp > 0 ? buf[ -- bufp] : getchar();
}
void ungetch( int c)
{
if (bufp >= BUFSIZE) {
printf( " buffer is full.\n " );
}
buf[bufp ++ ] = c;
}
int getword( char * word, int lim)
{
int c;
char * w;
memset(word, 0x00 , lim);
w = word;
while (isspace(c = getch()) )
;
if (c != EOF) {
* w ++ = c;
} else {
return c;
}
for ( ; -- lim > 0 ; w ++ ) {
if ( ! isalnum( * w = getch()) ) {
ungetch( * w);
break ;
}
}
* w = ' \0 ' ;
return word[ 0 ];
}
#include < stdlib.h >
#include < string .h >
#include < ctype.h >
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0 ;
int getch( void )
{
return bufp > 0 ? buf[ -- bufp] : getchar();
}
void ungetch( int c)
{
if (bufp >= BUFSIZE) {
printf( " buffer is full.\n " );
}
buf[bufp ++ ] = c;
}
int getword( char * word, int lim)
{
int c;
char * w;
memset(word, 0x00 , lim);
w = word;
while (isspace(c = getch()) )
;
if (c != EOF) {
* w ++ = c;
} else {
return c;
}
for ( ; -- lim > 0 ; w ++ ) {
if ( ! isalnum( * w = getch()) ) {
ungetch( * w);
break ;
}
}
* w = ' \0 ' ;
return word[ 0 ];
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include
<
stdio.h
>
#include < stdlib.h >
#include < string .h >
#include " io.h "
#include " hash.h "
typedef enum _status {
NONE,
GET_NAME,
GET_VALUE,
UNGET_NAME
} Status;
#define MAXSIZE 100
int main( void )
{
struct nlist * np;
Status status = NONE;
char word[MAXSIZE] = { 0 };
char name[MAXSIZE] = { 0 };
char defn[MAXSIZE] = { 0 };
while (getword(word, MAXSIZE) != EOF) {
if (strcmp(word, " #define " ) == 0 ) {
status = GET_NAME;
continue ;
} else if (strcmp(word, " #undef " ) == 0 ) {
status = UNGET_NAME;
continue ;
}
if (status == GET_NAME) {
memset(name, 0x00 , sizeof (name));
strcpy(name, word);
status = GET_VALUE;
} else if (status == GET_VALUE) {
memset(defn, 0x00 , sizeof (defn));
strcpy(defn, word);
status = NONE;
if ( (np = install(name, defn)) == NULL) {
return - 1 ;
}
} else if (status == UNGET_NAME) {
undef(word);
}
}
print();
return 0 ;
}
#include < stdlib.h >
#include < string .h >
#include " io.h "
#include " hash.h "
typedef enum _status {
NONE,
GET_NAME,
GET_VALUE,
UNGET_NAME
} Status;
#define MAXSIZE 100
int main( void )
{
struct nlist * np;
Status status = NONE;
char word[MAXSIZE] = { 0 };
char name[MAXSIZE] = { 0 };
char defn[MAXSIZE] = { 0 };
while (getword(word, MAXSIZE) != EOF) {
if (strcmp(word, " #define " ) == 0 ) {
status = GET_NAME;
continue ;
} else if (strcmp(word, " #undef " ) == 0 ) {
status = UNGET_NAME;
continue ;
}
if (status == GET_NAME) {
memset(name, 0x00 , sizeof (name));
strcpy(name, word);
status = GET_VALUE;
} else if (status == GET_VALUE) {
memset(defn, 0x00 , sizeof (defn));
strcpy(defn, word);
status = NONE;
if ( (np = install(name, defn)) == NULL) {
return - 1 ;
}
} else if (status == UNGET_NAME) {
undef(word);
}
}
print();
return 0 ;
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ken@Linux:
~/
TCPL
/
chap6
/
hash$ .
/
main
#include < stdio.h >
#define A 100
#define B 200
#define C 300
#undef A
in #undef .
only one node
name: defn:
name: B defn: 200
name: C defn: 300
#include < stdio.h >
#define A 100
#define B 200
#define C 300
#undef A
in #undef .
only one node
name: defn:
name: B defn: 200
name: C defn: 300