不知道 什么是 非实义单词,所有就没判断,我这个是统计所有单词,
#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);
}
}