C程序设计(第二版 新版)第六章 习题

1. 统计输入各个c语言关键字出现的次数(6.3)
其中: #define NKEYS (sizeof keytab / sizeof(struct key))
sizeof 是一个一元运算符   sizeof 对象    或者   sizeof  (类型名字)
sizeof 可以用在#define 中(预处理不计算#define语句中的表达式),但是不能用在#if条件编译中(预处理不对类型名进行分析),
利用结构数组:

#include<stdio.h>
#include<ctype.h>
#include<string.h>

#define MAXWORD 100
#define NKEYS (sizeof keytab / sizeof(struct key))

struct key
{
    char *word;
    int count;
}keytab[]={
    "auto", 0,
    "break",0,
    "case", 0,
    "char", 0,
    "const",0,
    "continue",0,
    "unsigned",0,
    "void", 0,
    "volatile", 0,
    "while",0
};

int getword(char *, int);
int binsearch(char *, struct key *, int);

int main()
{
    int n;
    char word[MAXWORD];
    while(getword(word,MAXWORD) != EOF)
   {
       if(isalpha(word[0]))
          if((n = binsearch(word,keytab,NKEYS)) >= 0)
              keytab[n].count++;
   }
   for(n = 0; n < NKEYS; n++)
     if(keytab[n].count> 0)
   printf("%4d %s\n",keytab[n].count,keytab[n].word);
     return 1;
}

int binsearch(char *word, struct key tab[], int n)
{
    int cond;
    int low, high,mid;
    low = 0;
    high = n -1;
    while(low < high)
    {
       mid = (low + high)/2;
       if((cond = strcmp(word,tab[mid].word)) < 0)
          high = mid -1;
       else if(cond > 0)
          low = mid + 1;
       else
          return mid;
     }
    return -1;
}

int getword(char *word, int lim)
{
    int c, getch();
    void ungetch(int);
    char *w = word;
    while((isspace(c = getch())))
       ;
    if( c != EOF)
       *w++ = c;
    if(!isalpha(c))
    {
       *w = '\0';
       return c;
    }
    for(; --lim > 0; w++)
    if(!isalnum(*w = getch()))
    {
       ungetch(*w);
       break;
    } 
    *w = '\0';
    return word[0];
}

#define BUFSIZE 1000
int buf[BUFSIZE];
int bufp = 0;

int getch()
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
     if(bufp >= BUFSIZE)
         printf("the stack of ungetch is full\n");
     else
         buf[bufp++] = c;
}


2. 上题中利用指向结构体的指针
mid = (low + high)/ 2  /* 错误 */  两个指针之间的假发运算是非法的
mid = low + (high - low) / 2
&tab[-1]  和 &tab[n] : 前者是错误的,后者是正确的,后者和 tab + n  是等价的,这个地址是真是存在的,但是对地址指向操作和运算操作都是非法的。

 
 
 
int main()
{
    struct key *p;
    char word[MAXWORD];
    while(getword(word,MAXWORD) != EOF)
    {
      if(isalpha(word[0]))
         if((p = binsearch(word,keytab,NKEYS)) != NULL)
		p->count++;
     }
     for(p = keytab; p < keytab + NKEYS; p++)
        if(p->count> 0)
	   printf("%4d %s\n",p->count,p->word);
     return 1;
}

struct key * binsearch(char *word, struct key tab[], int n)
{
     int cond;
     struct key *low, *high, *mid;
     low = &tab[0];
     high = &tab[n] -1;
     while(low < high)
     {
        mid = low + (high - low)/2;
        if((cond = strcmp(word,mid->word)) < 0)
	  high = mid -1;
        else if(cond > 0)
	  low = mid + 1;
        else
	  return mid;
     }
     return NULL;
}

3.统计单词出现的频率并俺字符顺序排序(6.5)
以下几个文件夹为常用函数文件夹:

GetchAndUngetch.c

#define BUFSIZE 1000
int buf[BUFSIZE];
int bufp = 0;

int getch()
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
    if(bufp >= BUFSIZE)
        printf("the stack of ungetch is full\n");
    else
        buf[bufp++] = c;
}

TallocAndStrdup.c
#include<malloc.h>

struct tnode *talloc()
{
    return (struct tnode *)malloc(sizeof(struct tnode));
}

char *strdp(char *s)
{
    char *p;
    p = (char *)malloc(strlen(s)+1);
    if(p != NULL)
        strcpy(p,s);
    return p;
}

getword.c
 int getword(char *word, int lim)
{
    int c, getch();
    void ungetch(int);
    char *w = word;
    //while((isspace(c = getch())) && c != '\n') //for 6-3.c
    while(isspace(c = getch()))
        ;
    if( c != EOF)
        *w++ = c;
    if(!isalpha(c))
    {
        *w = '\0';
        return c;
    }
    for(; --lim > 0; w++)
    if(!isalnum(*w = getch()))
    {
        ungetch(*w);
        break;
    }
    *w = '\0';
    return word[0];
}

主函数
#include<stdio.h>
#include<ctype.h>

#define MAXWORD 100
#define NDISTINCT 1000

struct tnode
{
    char *word;
    int count;
    struct tnode *left;
    struct tnode *right;
};

#include"GetchAndUngetch.c"
#include"TallocAndStrdup.c"
#include"getword.c"

struct tnode *addtree(struct tnode *p,char *p);
void treeprint(struct tnode *root);

int main()
{
    struct tnode *root;
    char word[MAXWORD];
    int i;
    root = NULL;
    while(getword(word,MAXWORD) != EOF)
        if(isalpha(word[0]))
            root = addtree(root,word);
   treeprint(root);
   return 0;
}

struct tnode *addtree(struct tnode *p, char *w)
{
    int cond;
    if(p == NULL)
    {
        p = talloc();
        p ->word = strdp(w);
        p ->count = 1;
        p ->left = p ->right = NULL;
    }
    else if((cond = strcmp(w,p->word)) < 0)
        p ->left = addtree(p->left,w);
    else if(cond > 0)
        p ->right = addtree(p->right,w);
    else 
        p->count++;
    return p;
}

void treeprint(struct tnode *p)
{
    if(p != NULL)
    {
        treeprint(p->left);
                printf("%4d %s\n",p->count, p->word);
        treeprint(p->right);
    }
}

4. 读取变量,并按字母是顺序打印变量名字,要求每一组内各变量名前6个字符相同,其余字符不同,6作为一个可以在命令行设定的参数。(6-2)
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>

struct tnode
{
    char *word;
    int match;
    struct tnode *left;
    struct tnode *right;
};

#define MAXWORD 100
#define YES 1
#define NO 0

#include"GetchAndUngetch.c"
#include"TallocAndStrdup.c"
#include"getword.c"

struct tnode *addtreex(struct tnode *, char *, int ,int *);
void treexprint(struct tnode*);

int main(int argc, char *argv[])
{
    struct tnode *root;
    char word[MAXWORD];
    int found = NO;
    int num;
    num = (--argv && (*++argv)[0] == '-') ? atoi(argv[0]+1) :6;
    root = NULL;
    while(getword(word,MAXWORD) != EOF)
    {
        if(isalpha(word[0]) && strlen(word) >= num)
        root = addtreex(root,word,num,&found);
        found = NO;
    }
    treexprint(root);
    return 1;
}

struct tnode *addtreex(struct tnode *p, char *w, int num, int *found)
{
    int cond;
    int compare(char* s, struct tnode *p,  int num, int *found);
    if(p == NULL)
    {
        p = talloc();
        p ->word = strdp(w);
        p ->match = *found;
        p -> left = p -> right = NULL;
    }
    else if((cond = compare(w,p,num,found)) < 0)
        p -> left = addtreex(p->left,w,num,found);
    else if(cond > 0)
        p -> right = addtreex(p->right,w,num,found);
    return p;
}

int compare(char *s, struct tnode *p, int num, int *found)
{
    int i;
    char *t = p->word;
    for(i = 0; *s == *t; i++,s++,t++)
        if(*s == '\0')
            return 0;
    if(i >= num )
    {
        *found = YES;
        p->match = YES;
    }
    return *s - *t;
}

void treexprint(struct tnode *p)
{
    if(p != NULL)
    {
        treexprint(p->left);
        if(p->match == YES)
        printf("%s\n",p->word);
        treexprint(p->right);
    }
}

5.编写一个程序,根据单词出现的频率俺降序打印输入的各个不同单词,并在每个单词的前面标上它的出现次数。
#include<stdio.h>
#include<ctype.h>

#define MAXWORD 100
#define NDISTINCT 1000

struct tnode
{
    char *word;
    int count;
    struct tnode *left;
    struct tnode *right;
};

#include"GetchAndUngetch.c"
#include"TallocAndStrdup.c"
#include"getword.c"

struct tnode *addtree(struct tnode *, char *);
void sortlist();
void treestore(struct tnode *);

struct tnode *list[NDISTINCT];
int ntn = 0;

int main()
{
    struct tnode *root;
    char word[MAXWORD];
    int i;
    root = NULL;
    while(getword(word,MAXWORD) != EOF)
        if(isalpha(word[0]))
            root = addtree(root,word);
    treestore(root);
    sortlist();
    for(i = 0; i < ntn; i++)
        printf("%2d:%20s\n", list[i]->count, list[i]->word);
    return 0;
}

struct tnode *addtree(struct tnode *p, char *w)
{
    int cond;
    if(p == NULL)
    {
        p = talloc();
        p ->word = strdp(w);
        p ->count = 1;
        p ->left = p ->right = NULL;
    }
    else if((cond = strcmp(w,p->word)) < 0)
        p ->left = addtree(p->left,w);
    else if(cond > 0)
        p ->right = addtree(p->right,w);
    else 
        p->count++;
    return p;
}

void treestore(struct tnode *p)
{
    if(p != NULL)
    {
        treestore(p->left);
        if(ntn < NDISTINCT)
           list[ntn++] = p;
        treestore(p->right);
    }
}

void sortlist()
{
    int gap, i, j;
    struct tnode *temp;
    for(gap = ntn/2; gap > 0; gap /=2)
        for(i = gap; i < ntn; i++)
            for(j = i-gap; j >= 0; j-=gap)
            {
                if((list[j]->count) >= (list[j+gap]->count))
                    break;
                temp = list[j];
                list[j] = list[j+gap];
                list[j+gap] = temp;
            }
}

6.表查找程序。比如:#define IN 1 就把文本IN 和 文本1都存起来,我采用散列表查找方法。
#include<stdio.h>
#include<string.h>
#include<malloc.h>

struct nlist
{
   struct nlist *next;
   char *name;
   char *defn;
};

#define HASHSIZE 101
struct nlist *hashtab[HASHSIZE];

//hash函数:为字符串s生成散列值
unsigned hash(char *s)
{
   unsigned  hashval;
   for(hashval = 0; *s != '\0'; s++)
      hashval = *s + 31 * hashval;
   return hashval % HASHSIZE;
}

// lookup函数:在hashtab中查找s
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;
}

// 将(name,defn)加入到hashtab中
struct nlist *install(char *name, char *defn)
{
   struct nlist *np;
   unsigned hashval;
   if((np = lookup(name)) == NULL)
   {
      np = (struct nlist *)malloc(sizeof(*np));
      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);
   if((np->defn = strdup(defn)) == NULL)
      return NULL;
   return np;
}

// 将删除字符串s以及其定义
void undef(char *s)
{
    int h;
    struct nlist *prev, *np;
    prev = NULL;
    h = hash(s);
    for(np = hashtab[h]; np != NULL; np = np ->next)
    {
       if(strcmp(s,np->name) == 0)
          break;
       prev = np;
    }
    if(np != NULL)
    {
       if(prev == NULL)
          hashtab[h]= np->next;
       else
       {
          prev->next = np->next;
          free((void *)np->name);
          free((void *)np->defn);
          free((void *)np);
       }
    }
}

void print()
{
    int i;
    for(i = 0; i < HASHSIZE; i++)
      if(hashtab[i] != NULL)
      {
         struct nlist *temp = hashtab[i];
         while(temp)
         {
            printf("%15s %5s\n",temp->name, temp->defn);
            temp = temp ->next;
         }
       }
}

int main()
{
    install("chenyiming","1");
    install("huangyazhen","2");
    install("xuyang","3");
    install("wangchao","4");
    install("zhengnan","5");
    print();
    return 1;
}

7.编写一个适合c语言程序使用的#define处理的简单版本(即无参数的情况)。(练习6-6)你会发现getch和ungetch函数非常有用。
#include<stdio.h>
#include<ctype.h>
#include<string.h>

#define MAXWORD 100

struct nlist
{
	struct nlist *next;
	char *name;
	char *defn;
};

#include"getword.c"
#include"TallocAndStrdup.c"
#include"GetchAndUngetch.c"

void error(int, char *);
struct nlist *install(char *,char *);
struct nlist *lookup(char *);
void skipblanks();
void getdef();
void undef(char *);

int main()
{
	char w[MAXWORD];
	struct nlist *p;
	
	while(getword(w,MAXWORD) != EOF)
	{
		if(strcmp(w,"#")== 0)
			getdef();
		else if(!isalpha(w[0]))
			printf("%s",w);
		else if((p = lookup(w)) == NULL)
			printf("%s",w);
		else
			ungets(p->defn);
	}
	return 0;
}

void getdef()
{
	void undef(char *);
	int c, i;
	char def[MAXWORD], dir[MAXWORD], name[MAXWORD];
	
	skipblanks();
	if(!isalpha(getword(dir,MAXWORD)))
		error(dir[0],"getdef:expecting a directive after #");
	else if(strcmp(dir,"define") == 0)
	{
		skipblanks();
		if(!isalpha(getword(name,MAXWORD)))
			error(name[0],"getdef: non-alpha - name expected");
		else
		{
			skipblanks();
			for(i = 0; i < MAXWORD - 1; i++)
				if((def[i] = getch()) == EOF || def[i] =='\n')
					break;
			def[i] = '\0';
			if(i <= 0)
				error('\n',"getdef: incomplete define");
			else
				install(name,def);
		}
	}
	else if( strcmp(dir, "undef") == 0)
	{
		skipblanks();
		if(!isalpha(getword(name,MAXWORD)))
			error(name[0],"getdef:non-alpha in undef");
		else	
			undef(name);
	}
	else
		error(dir[0],"getdef: expecting a directive after #");
}

void error(int c, char *s)
{
	printf("error: %s\n",s);
	while(c != EOF && c != '\n')
		c = getch();
}

void skipblanks()
{
	int c;
	while((c = getch())== ' ' || c == '\t')
		;
	ungetch(c);
}


#define HASHSIZE 101
struct nlist *hashtab[HASHSIZE];

//hash函数:为字符串s生成散列值
unsigned hash(char *s)
{
   unsigned  hashval;
   for(hashval = 0; *s != '\0'; s++)
      hashval = *s + 31 * hashval;
   return hashval % HASHSIZE;
}

// lookup函数:在hashtab中查找s
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;
}

// 将(name,defn)加入到hashtab中
struct nlist *install(char *name, char *defn)
{
   struct nlist *np;
   unsigned hashval;
   if((np = lookup(name)) == NULL)
   {
      np = (struct nlist *)malloc(sizeof(*np));
      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);
   if((np->defn = strdup(defn)) == NULL)
      return NULL;
   return np;
}

// 将删除字符串s以及其定义
void undef(char *s)
{
    int h;
    struct nlist *prev, *np;
    prev = NULL;
    h = hash(s);
    for(np = hashtab[h]; np != NULL; np = np ->next)
    {
       if(strcmp(s,np->name) == 0)
          break;
       prev = np;
    }
    if(np != NULL)
    {
       if(prev == NULL)
          hashtab[h]= np->next;
       else
       {
          prev->next = np->next;
          free((void *)np->name);
          free((void *)np->defn);
          free((void *)np);
       }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值