TCPL——练习6.5 & 6.6

  这两道习题综合起来是利用散列表写个适用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
散列表实现文件:

hash.c
#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;
}
io.h: 只保留一个借口给main函数调用:

#ifndef IO_H
#define IO_H

int getword(char *word, int lim);

#endif
io.c : 输入输出实现文件:

io.c
#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];
}
最后是main.c文件,调试信息我都去掉了。

main.c
#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;
}
简单测试结果:

代码
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

 

posted @ 2010-11-23 01:13  Linjian  阅读(423)  评论(0编辑  收藏  举报