有文本文件wordlist.txt,统计各个公司出现的频次。
运行环境vc++6.0。
代码如下:
/* * 功能:统计文本文件中字符串的频率 * * 说明:pHeadG -> WordItem 1 -> WordItem 2 -> ... -> WordItem n -> NULL */ #include <stdio.h> #include <stdlib.h> #include <string.h> /**********************数据结构与全局变量*************************/ struct WordItem { char *word; int count; struct WordItem *next; }; struct WordItem *pHeadG = NULL; /*******************将链表数据输出到文件上************************/ void OutputResult(WordItem *pHead) { FILE *fOut = NULL; WordItem *pMove = pHead; WordItem *pTobeFree = NULL; fOut = fopen("rslt.txt","w+"); while(pMove->next != NULL) { fprintf(fOut, "%s %d\n", pMove->word, pMove->count); pTobeFree = pMove; pMove = pMove->next; free(pTobeFree->word); free(pTobeFree); } fclose(fOut); } /*************将新串与链表中串比较,插入或更新计数****************/ void Compare(WordItem *pHead, char *s) { WordItem *pMove = pHead; if(pHead ==NULL) //插入第一个串 { struct WordItem *wi = (struct WordItem *)malloc(sizeof(struct WordItem)); wi->word = (char *)malloc(100); strcpy(wi->word, s); wi->count = 1; wi->next=NULL; pHeadG=wi; } else { while(pMove != NULL) { //找到相同串,计数加1,并将pMove往链表尾部移动,直到pMove的值等于NULL为止 if(!strcmp(pMove->word, s)) { pMove->count++; break; } else //未找到相同串 { if(pMove->next != NULL) //本链表节点还有下一节点,继续往下走 pMove = pMove->next; else //本链表节点已经是最后一个节点,表明是新增的串 { struct WordItem *wi = (struct WordItem *)malloc(sizeof(struct WordItem)); wi->word = (char *)malloc(100); strcpy(wi->word, s); wi->count = 1; wi->next=NULL; pMove->next=wi; break;
} } } } } /********************************主程序***************************/ void main(void) { char ch; int i=0; char temp[100]; memset(temp, '\0', 100); FILE *fpIn = fopen("wordlist.txt", "r"); ch = fgetc(fpIn); while (ch != EOF) { while(ch != 0xa && ch != 0xd) { temp[i] = ch; i++; ch = fgetc(fpIn); } Compare(pHeadG, temp); ch = fgetc(fpIn); i=0; memset(temp, '\0', 100); } OutputResult(pHeadG); fclose(fpIn); }
去掉重复代码后(注:函数参数是单指针,功能错误):
/* * 功能:统计文本文件中字符串的频率 * * 说明:pHeadG -> WordItem 1 -> WordItem 2 -> ... -> WordItem n -> NULL */ #include <stdio.h> #include <stdlib.h> #include <string.h> /**********************数据结构与全局变量*************************/ struct WordItem { char *word; int count; struct WordItem *next; }; struct WordItem *pHeadG = NULL; /*******************将链表数据输出到文件上************************/ void OutputResult(WordItem *pHead) { FILE *fOut = NULL; WordItem *pMove = pHead; WordItem *pTobeFree = NULL; fOut = fopen("rslt.txt","w+"); while(pMove->next != NULL) { fprintf(fOut, "%s %d\n", pMove->word, pMove->count); pTobeFree = pMove; pMove = pMove->next; free(pTobeFree->word); free(pTobeFree); } fclose(fOut); } /************创建一个新的WordItem并用指定的指针指向它*************/ void MakeNewNode(WordItem *pWordItem, char *s) { struct WordItem *wi = (struct WordItem *)malloc(sizeof(struct WordItem)); wi->word = (char *)malloc(100); strcpy(wi->word, s); wi->count = 1; wi->next = NULL; pWordItem = wi; } /*************将新串与链表中串比较,插入或更新计数****************/ void Compare(WordItem *pHead, char *s) { WordItem *pMove = pHead; if(pHead ==NULL) //插入第一个串 { MakeNewNode(pHeadG, s); } else { while(pMove != NULL) { //找到相同串,计数加1,并将pMove往链表尾部移动,直到pMove的值等于NULL为止 if(!strcmp(pMove->word, s)) { pMove->count++; break; } else //未找到相同串 { if(pMove->next != NULL) //本链表节点还有下一节点,继续往下走 pMove = pMove->next; else //本链表节点已经是最后一个节点,表明是新增的串 { MakeNewNode(pMove->next, s); break;
} } } } } /********************************主程序***************************/ void main(void) { char ch; int i=0; char temp[100]; memset(temp, '\0', 100); FILE *fpIn = fopen("wordlist.txt", "r"); ch = fgetc(fpIn); while (ch != EOF) { while(ch != 0xa && ch != 0xd) { temp[i] = ch; i++; ch = fgetc(fpIn); } Compare(pHeadG, temp); ch = fgetc(fpIn); i=0; memset(temp, '\0', 100); } OutputResult(pHeadG); fclose(fpIn); }
改成双指针后,代码正确:
/* * 功能:统计文本文件中字符串的频率 * * 说明:pHeadG -> WordItem 1 -> WordItem 2 -> ... -> WordItem n -> NULL */ #include <stdio.h> #include <stdlib.h> #include <string.h> /**********************数据结构与全局变量*************************/ struct WordItem { char *word; int count; struct WordItem *next; }; struct WordItem *pHeadG = NULL; /*******************将链表数据输出到文件上************************/ void OutputResult(WordItem *pHead) { FILE *fOut = NULL; WordItem *pMove = pHead; WordItem *pTobeFree = NULL; fOut = fopen("rslt.txt","w+"); while(pMove->next != NULL) { fprintf(fOut, "%s %d\n", pMove->word, pMove->count); pTobeFree = pMove; pMove = pMove->next; free(pTobeFree->word); free(pTobeFree); } fclose(fOut); } /************创建一个新的WordItem并用指定的指针指向它*************/ // doubleStarP -> &P,此处不用双指针,无法将值返回到调用函数的实参 void MakeNewNode(WordItem **pWordItem, char *s) { struct WordItem *wi = (struct WordItem *)malloc(sizeof(struct WordItem)); wi->word = (char *)malloc(100); strcpy(wi->word, s); wi->count = 1; wi->next = NULL; *pWordItem = wi; } /*************将新串与链表中串比较,插入或更新计数****************/ void Compare(WordItem *pHead, char *s) { WordItem *pMove = pHead; if(pHead ==NULL) //插入第一个串 { MakeNewNode(&pHeadG, s); } else { while(pMove != NULL) { //找到相同串,计数加1,并将pMove往链表尾部移动,直到pMove的值等于NULL为止 if(!strcmp(pMove->word, s)) { pMove->count++; break; } else //未找到相同串 { if(pMove->next != NULL) //本链表节点还有下一节点,继续往下走 pMove = pMove->next; else //本链表节点已经是最后一个节点,表明是新增的串 { MakeNewNode(&pMove->next, s); break;
} } } } } /********************************主程序***************************/ void main(void) { char ch; int i=0; char temp[100]; memset(temp, '\0', 100); FILE *fpIn = fopen("wordlist.txt", "r"); ch = fgetc(fpIn); while (ch != EOF) { while(ch != 0xa && ch != 0xd) { temp[i] = ch; i++; ch = fgetc(fpIn); } Compare(pHeadG, temp); ch = fgetc(fpIn); i=0; memset(temp, '\0', 100); } OutputResult(pHeadG); fclose(fpIn); }
结果如下: