题目:编写一个程序,用以读入一个C语言程序,并按字母表顺序分组打印变量名,要求每一组内各变量名的前6各字符相同,其余字符不同.字符串和注释中的单词不予考虑,请将6作为一个可在命令行中设定的参数.
个人分析:这里题目用到了树的结构
首先定义一个树的结构
struct tnode //树的节点
{
char *word; //指向单词的指针
int match; //是否打印
struct tnode *left; //左子节点
struct tnode *right; //右子节点
};
然后下面这是一个添加节点的子程序
struct tnode *addtreex(struct tnode *p, char *w, int num, int *found)
{
int cond;
if (p == NULL) //该单词是一个新单词
{
//p = talloc(); //创建一个新节点
p = (struct tnode *)malloc(sizeof(struct tnode));
p->word = strdup(w);
p->match = *found;
p->left = p->right = NULL;
}
else if ((cond = compare(w, p, num, found)) < 0) //首字母ASCALL比当前节点单词的首字母ASCALL的值小
{
p->left = addtreex(p->left, w, num, found);
}
else if (cond>0) //首字母ASCALL比当前节点单词的首字母ASCALL的值大 或者 前六个字母相同的新单词
{
p->right = addtreex(p->right, w, num, found);
}
return p;
}
调用这个子程序返回的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;
}
}
//单词长度>num 默认为6
if (i >= num)
{
*found = YES;
p->match = YES;
}
//返回首字母ASCII码之差
return *s - *t;
}
这个子程序的返回值是返回首字母ASCII码之差
按照这个就能实现首字母的比较
前面的子程序addtreex中
下面有一个判断语句,单独摘抄出来给大家看看
else if ((cond = compare(w, p, num, found)) < 0) //首字母ASCALL比当前节点单词的首字母ASCALL的值小
{
p->left = addtreex(p->left, w, num, found);
}
else if (cond>0) //首字母ASCALL比当前节点单词的首字母ASCALL的值大 或者 前六个字母相同的新单词
{
p->right = addtreex(p->right, w, num, found);
}
这个首先比较首字母
如果 首字母ASCALL比当前节点单词的首字母ASCALL的值小 则放在左树
如果 首字母ASCALL比当前节点单词的首字母ASCALL的值大 或者 前六个字母相同的新单词 则放在右树
而下面这个打印的子程序
void treexprint(struct tnode *p)
{
if (p != NULL)
{
treexprint(p->left);
if (p->match)
{
printf("%s\n", p->word);
}
treexprint(p->right);
}
}
它是先打印左树再打印右树
所以就能够按照字母排序打印出单词
![](https://i-blog.csdnimg.cn/blog_migrate/cf67d56cafbd0186afb4007f8af1c85b.jpeg)
完整的程序
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE
#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
struct tnode *addtreex(struct tnode *, char *, int, int *);
void treexprint(struct tnode *);
int getword(char *, int);
int main(int argc,char *argv[])
{
struct tnode *root;
char word[MAXWORD];
int found = NO;
int num;
num = (--argc && (*++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 0;
}
//返回出来永远是返回头节点
struct tnode *addtreex(struct tnode *p, char *w, int num, int *found)
{
int cond;
if (p == NULL) //该单词是一个新单词
{
//p = talloc(); //创建一个新节点
p = (struct tnode *)malloc(sizeof(struct tnode));
p->word = strdup(w);
p->match = *found;
p->left = p->right = NULL;
}
else if ((cond = compare(w, p, num, found)) < 0) //首字母ASCALL比当前节点单词的首字母ASCALL的值小
{
p->left = addtreex(p->left, w, num, found);
}
else if (cond>0) //首字母ASCALL比当前节点单词的首字母ASCALL的值大 或者 前六个字母相同的新单词
{
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;
}
}
//单词长度>num 默认为6
if (i >= num)
{
*found = YES;
p->match = YES;
}
//返回首字母ASCII码之差
return *s - *t;
}
void treexprint(struct tnode *p)
{
if (p != NULL)
{
treexprint(p->left);
if (p->match)
{
printf("%s\n", p->word);
}
treexprint(p->right);
}
}
int getch2(void);
void ungetch2(int);
int comment(void)
{
int c;
while ((c = getch2()) != EOF)
{
if (c == '*')
{
if ((c = getch2()) == '/')
{
break;
}
else
{
ungetch2(c);
}
}
}
return c;
}
//从输入中读取下一个单词或字符
//lim是限制最长的长度
int getword(char *word, int lim)
{
int comment(void);
int c, d;
char *w = word;
while (isspace(c = getch2()))
;
if (c != EOF)
{
*w++ = c;
}
if (isalpha(c) || c == '_' || c == '#')
{
for (; --lim; w++) //填充字符
{
if (!isalnum(*w = getch2()) && *w != '_')
{
ungetch2(*w);
break;
}
}
}
else if (c == '\'' || c == '"')
{
for (; --lim > 0; w++)
{
if ((*w = getch2()) == '\\') //???
{
*++w = getch2();
}
else if (*w == c) //碰到堆成的符号
{
w++;
break;
}
else if (*w == EOF)
{
break;
}
}
}
else if (c == '/')
{
if ((d = getch2()) == '*')
{
c = comment(); //忽略注释的内容
}
else
{
ungetch2(d);
}
}
*w = '\0';
return c;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch2(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch2(int c)
{
if (bufp >= BUFSIZE)
{
printf("ungetch:too many characters\n");
}
else
{
buf[bufp++] = c;
}
}