c 程序设计语言 第二版 练习题 6-3

不知道 什么是 非实义单词,所有就没判断,我这个是统计所有单词,

#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
static int line = 1;//全局变量,记录行号
typedef struct LineNumber { //定义个行结构
	int line;
	struct LineNumber *next;
}LineNumber;
typedef struct WordList {//定义个单词结构
	char *word;
	LineNumber *line;
	struct WordList *left;
	struct WordList *right;
}WordList;

LineNumber *createLineNumber(const int n); //创建节点
LineNumber *lookupLineNumber(LineNumber *line, const int n);//查找节点,没有上
LineNumber *addLineNumber(LineNumber *line, const int n);//添加节点
void freeLineNumber(LineNumber *line);//释放
void printLineNumber(LineNumber *line);//打印


WordList *createWordList(const char *word);//创建节点
WordList *lookupWordList(WordList *list, const char *word);//查找节点,没有上
WordList * addWordList(WordList *list, const char *word);//添加节点
void freeWordList(WordList *list);//释放
void printWordList(WordList *list);//打印

int fgetword(FILE *fp,char *word){ //按单词 ,读取文件
	if (fp == NULL)
		return -1;
	char c;
	int count = 0;//记录读取数量
	while (isspace(c=fgetc(fp))){ //跳过空字符
		if (c == '\n')//如果是'\n'说明该下一行了,line++
			++line;
	}
	if (c == EOF)
		return EOF;
	if (!isalpha(c)) { //判断第一个字符,是否是字母字符,如果不是则表示不是一个单词,跳过
		while (!(isspace(c = fgetc(fp)))&& c != EOF)//直到下个空字符结束
			;
		
		if (c == EOF)
			return EOF;
		if (c == '\n')//记录行号line++
			++line;		
		return 0;
	}
	if (isalpha(c)) { //读取单词
		word[count++] = c;
		while (isalpha(c = fgetc(fp)) && c != EOF &&(word[count++] = c))//读取连续的字母
			;

		word[count] = '\0';
		if (c == EOF)
			ungetc(c, fp);
		if (c == '\n')//记录行号
			++line;
	}
	return count;

}


int main() {	
	char *fileName = "t.txt";
	FILE *fp;
	fp = fopen(fileName, "r");
	if (fp == NULL)
		return 0;
	char buf[100];
	int ret;
	WordList *list=NULL;
	while ((ret = fgetword(fp, buf))!=EOF) {		
		if (ret) {
			if (list == NULL) {
				list = createWordList(buf);
			}
			else
			{
				addWordList(list, buf);
			}
			
		}
	}
	printWordList(list);

	freeWordList(list);
	return 0;
}



WordList *createWordList(const char *word) {
	WordList *list = (WordList*)calloc(1, sizeof(WordList));
	list->line = createLineNumber(line); //需要创建单词节点都是第一出现的单词,结着创建一个行节点
	if (word) {//判断非空指针,好像有点多余							
		list->word= (char*)malloc(strlen(word) + 1);
		strcpy(list->word, word);
	}
	return list;
}
WordList *addWordList(WordList *list, const char *word) {//递归添加节点
	int ret;
	if (list == NULL) { //结束递归 ,创建新节点
		return createWordList(word);
	}
	else if ((ret = strcmp(list->word, word) )== 0) {//判断当前节点单词,是否等于word
		addLineNumber(list->line, line);//等于 添加行节点
	}
	else if (ret < 0) {//小于 则递归left节点
		if(list->left)//下一节点如果不是NULL,测直接递归
			addWordList(list->left, word);
		else//书中的例题是给个返回值都赋值,我这里做了一下判断,下一个节点是空的时候才返回值才赋值,不知道会不好点
			list ->left = addWordList(list->left, word);//返回值用于添加新节点
	}
	else if (ret > 0) {//大于 则递归right节点
		if (list->right)
			addWordList(list->right, word);
		else
			list->right = addWordList(list->right, word);//返回值用于添加新节点
	}
	return list;


}

void freeWordList(WordList * list)
{
	if (list == NULL)
		return;	
	free(list->word);
	freeLineNumber(list->line);//释放 line节点
	freeWordList(list->left); //释放left节点
	freeWordList(list->right);//释放right节点		
	free(list); //最后释放当前节点
	
}

void printWordList(WordList * list)
{
	if (list) {
		printf("单词:%s\t行号:", list->word);
		printLineNumber(list->line);
		putchar('\n');
		printWordList(list->left);
		printWordList(list->right);
	}
}

WordList *lookupWordList(WordList *list, const char *word)//本来想添加节点的时候用于查找的,
{														  //写完之后发现,有点多余,查找完之后
	if (list == NULL || word == NULL)					//如果是新节点没办法添加了,还要查找
		return NULL;
	if (strcmp(list->word, word) < 0)
		return lookupWordList(list->left, word);
	else if (strcmp(list->word, word) > 0)
		return lookupWordList(list->right, word);
	else if (strcmp(list->word, word) == 0)
		return list;
	return NULL;
}
LineNumber *createLineNumber(const int n) { //创建行节点
	LineNumber *line = (LineNumber*)calloc(1, sizeof(LineNumber));
	line->line = n;
	line->next = NULL;
	return line;
}

LineNumber * lookupLineNumber(LineNumber *line, const int n)
{
	if (line->line == n)
		return line;
	else
	{
		if (line->next != NULL)
			return lookupLineNumber(line->next, n);
	}
	return NULL;
}

LineNumber *addLineNumber(LineNumber * line, const int n) //添加节点
{
	
	if (line == NULL) {//递归 结束,没有当前行
		return createLineNumber(n);//创建行节点
	}
	else if (line->line == n) {  //判断是否有当前行
		return line;
	}
	else {
		if (line->next)//下一节点如果不是NULL,测直接递归
			addLineNumber(line->next, n);
		else
			line->next= addLineNumber(line->next, n);//返回值用于当前节点的下一个节点
	}
	return line;

}
void freeLineNumber(LineNumber *list) {

	if (list == NULL)
		return;
	freeLineNumber(list->next);
	free(list);
	
}

void printLineNumber(LineNumber * line)
{
	if (line) {
		printf("%d ", line->line);
		printLineNumber(line->next);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值