《征服c指针》学习笔记-----统计文本单词数目的程序word_count
1、程序的要求:对用户指定的英文文本文件(包括标准输入),将英文单词按照字母顺序输出到用户指定的文本文件中(包括标准输出),并且在各单词后面显示单词的出现次数。
2、模块设计:
主要分为:1.从输入流获取单词部分 2.管理单词的部分 3.主程序部分:统一管理以上两部分
3、代码
第1部分:get_word.c 主要是利用isalnum()函数判断单词的开始与结束
- /*get_word.c*/
#include<stdio.h>- #include<stdlib.h>
- #include<ctype.h>
- /*
- 这个函数从输入文件fp获取单词,参数buf指向获取的单词,返回值返回单词长度或是EOF提示
- */
- int get_word(char *buf,int buf_size,FILE *fp)
- {
- int ch,len;
- len=;
- while((ch=getc(fp))!=EOF&&isalnum(ch)) //isalnum(int c)函数在c是数字或字母时返回ture
- {
- buf[len]=ch; //buf[len] is a syntax sugar of *(buf+len)
- len++;
- if(len>=buf_size)
- {
- printf("error:word too long!"); //单词长度大于buf_size时发出警报并退出程序
- exit();
- }
- }
- buf[len]='\0'; //给字符串添加结束标志
- if(ch==EOF)
- {
- return EOF;
- }
- else
- {
- return len;
- }
- }
- /*get_word.h*/
#ifndef GET_WORD_H- #define GET_WORD_H
- /*这个函数用于读取fp所指向文件的单词,读取成功则返回单词长度,到达文件尾部返回EOF*/
- int get_word(char *buf,int buf_size,FILE *fp);
- #endif
第2部分:管理单词
word_manage.h:声明单词管理部分所有的函数,及存储单词用的结构体
- #ifndef WORD_MANAGE_H
- #define WORD_MANAGE_H
- #include<stdio.h>
- typedef struct word_tag
- {
- char *word;
- int count; //单词数目
- struct word_tag *next_word;
- }WORD;
- extern WORD *word_head; //引用了word_initialize中定义的word_head变量
- void word_initialize(void); //初始化管理单词部分,一开始必须先调用这个函数
- void add_word(char *word); //添加单词到单词管理部分
- void dump_word(FILE *fp); //输出统计数据,fp指向输出文件流
- void word_finalize(void); //结束使用单词管理部分时调用该函数
- #endif
word_initialize.c:这个函数主要声明了word_head变量,再由word_manage引用它,这样一来,要使用word_head变量之前都要先调用这个函数。
- #include"word_manage.h"
- WORD *word_head; //这个变量将在word_manage.h中被引用
- void word_initialize(void)
- {
- word_head=NULL;
- }
add_word.c:
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include"word_manage.h"
- /*创建一个新的结点*/
- static WORD *create_word(char *word)
- {
- char *temp;
- WORD *new_word;
- new_word=malloc(sizeof(WORD));
- temp=strdup(word); //char *strdup(const char *str)用于返回str字符串的副本,这个副本和str具有不同的内存地址空间
- new_word->word=temp; //此处不可以直接将word的指针地址赋给新建的单词
- new_word->count=;
- new_word->next_word=NULL;
- return new_word;
- }
- void add_word(char *word)
- {
- WORD *pos,*pre,*new_word; //pos指向当前结构体,pre指向当前结构体的上一个结构体
- pos=word_head;
- pre=NULL;
- int result;
- /*如果不是第一个,则循环直到找到插入点或同样的单词*/
- while(pos!=NULL)
- {
- if((result=strcmp(pos->word,word))<)
- {
- pre=pos;
- pos=pos->next_word;
- }
- else break;
- }
- /*找到同样的单词*/
- if(word_head!=NULL&&result==)
- {
- pos->count++;
- }
- else
- {
- /*插入到第一个单词结点*/
- if(pre==NULL)
- {
- new_word=create_word(word);
- new_word->next_word=word_head;
- word_head=new_word;
- }
- /*插入到其他点*/
- else
- {
- new_word=create_word(word);
- new_word->next_word=pos;
- pre->next_word=new_word;
- }
- }
- }
dump_word:
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include"word_manage.h"
- /*创建一个新的结点*/
- static WORD *create_word(char *word)
- {
- char *temp;
- WORD *new_word;
- new_word=malloc(sizeof(WORD));
- temp=strdup(word); //char *strdup(const char *str)用于返回str字符串的副本,这个副本和str具有不同的内存地址空间
- new_word->word=temp; //此处不可以直接将word的指针地址赋给新建的单词
- new_word->count=;
- new_word->next_word=NULL;
- return new_word;
- }
- void add_word(char *word)
- {
- WORD *pos,*pre,*new_word; //pos指向当前结构体,pre指向当前结构体的上一个结构体
- pos=word_head;
- pre=NULL;
- int result;
- /*如果不是第一个,则循环直到找到插入点或同样的单词*/
- while(pos!=NULL)
- {
- if((result=strcmp(pos->word,word))<)
- {
- pre=pos;
- pos=pos->next_word;
- }
- else break;
- }
- /*找到同样的单词*/
- if(word_head!=NULL&&result==)
- {
- pos->count++;
- }
- else
- {
- /*插入到第一个单词结点*/
- if(pre==NULL)
- {
- new_word=create_word(word);
- new_word->next_word=word_head;
- word_head=new_word;
- }
- /*插入到其他点*/
- else
- {
- new_word=create_word(word);
- new_word->next_word=pos;
- pre->next_word=new_word;
- }
- }
- }
word_finalize.c:
- #include<stdlib.h>
- #include"word_manage.h"
- void word_finalize(void)
- {
- WORD *temp;
- temp=word_head;
- while(temp!=NULL)
- {
- word_head=word_head->next_word;
- free(temp->word);
- free(temp);
- temp=word_head;
- }
- }
第3部分:主程序部分
main.c:
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include "get_word.h"
- #include "word_manage.h"
- #define BUF_SIZE 1024
- /*这个程序将输出文件的每个单词的频率,该文件名将从用户输入读取
- */
- int main()
- {
- char file_input[BUF_SIZE],file_output[BUF_SIZE],buf[BUF_SIZE];
- int word_len;
- FILE *fp_in,*fp_out;
- printf("请输入一个被统计的文件的文件名(包括文件后缀),stdin表示从命令行读入:");
- scanf("%s",file_input);
- printf("请输入统计数据的输出文件的文件名(包括文件后缀),stdout表示从命令行输出:");
- scanf("%s",file_output);
- /*处理输入的文件名*/
- if(!strcmp(file_input,"stdin")) //strcmp函数在两个字符串相同时返回0
- {
- fp_in=stdin;
- }
- else
- {
- if((fp_in=fopen(file_input,"r"))==NULL)
- {
- printf("open input file error!\n");
- exit();
- }
- }
- /*处理输出文件名*/
- if(!strcmp(file_output,"stdout"))
- {
- fp_out=stdout;
- }
- else
- {
- fp_out=fopen(file_output,"w");
- }
- /*初始化单词管理数据库*/
- word_initialize();
- /*读取单词并加入单词管理数据库*/
- while((word_len=get_word(buf,BUF_SIZE,fp_in))!=EOF)
- {
- if(word_len!=)
- {
- add_word(buf);
- }
- }
- /*输出单词出现的频率*/
- dump_word(fp_out);
- word_finalize();
- return ;
- }
4、新的东西
在add_word.c中,利用create_word函数创建新的单词结构体时,不可以直接将所传入单词的指针复制给新建的单词,只能将字符串值复制过去。因为所传入单词的指针所指向的内容是每次读取的单词,而不是某一次读取的单词。
《征服c指针》学习笔记-----统计文本单词数目的程序word_count的更多相关文章
- C++中的智能指针、轻量级指针、强弱指针学习笔记
一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...
- Git学习笔记(二) · 非典型性程序猿
远程库的使用 前面说到的都是git在本地的操作,那么实际协作开发过程中我们肯定是要有一个远程版本库作为项目的核心版本库,也就是投入生产使用的版本.这里我们以 Github为例.Github是一个开放的 ...
- 【Python自然语言处理】第一章学习笔记——搜索文本、计数统计和字符串链表
这本书主要是基于Python和一个自然语言工具包(Natural Language Toolkit, NLTK)的开源库进行讲解 NLTK 介绍:NLTK是一个构建Python程序以处理人类语言数据的 ...
- 《征服 C 指针》笔记6:练习——挑战那些复杂的声明
应该是小试牛刀的时候了. 在 ANSI C 的标准库中,有一个 atexit()函数.如果使用这个函数,当程序正常结束的时候,可以回调一个指定的函数. atexit()的原型定义如下: int ate ...
- 【视频编解码·学习笔记】11. 提取SPS信息程序
一.准备工作: 回到之前SimpleH264Analyzer程序,找到SPS信息,并对其做解析 调整项目目录结构: 修改Global.h文件中代码,添加新数据类型UINT16,之前编写的工程中,UIN ...
- 【视频编解码·学习笔记】13. 提取PPS信息程序
PPS结构解析 与之前解析SPS方式类似 一.定义PPS类: 在3.NAL Unit目录下,新建PicParamSet.cpp和PicParamSet.h,在这两个文件中写入类的定义和函数实现. 类定 ...
- JZ2440学习笔记之通过J-Link单步裸机程序(Keil+J-Link)
我们还是使用JZ2440学习笔记之第一个裸机程序(Keil-MDK)里面的程序,但是把延时拿掉,要不然单步的时候一直在delay里面: int main(void) { // Set GPF4/5/6 ...
- 广师大学习笔记之文本统计(jieba库好玩的词云)
1.jieba库,介绍如下: (1) jieba 库的分词原理是利用一个中文词库,将待分词的内容与分词词库进行比对,通过图结构和动态规划方法找到最大概率的词组:除此之外,jieba 库还提供了增加自定 ...
- web前端学习笔记:文本属性
今天的web前端笔记主要讲述文本属性,希望能帮助到正在学习web前端开发的初学者们,废话不多说了,一起来看看文本属性的相关内容吧. 文本属性 文本缩进 将Web页面上的一个段落第一行缩进,这是一种最常 ...
随机推荐
- 关于《一步步学习ASP.NET MVC3》系列发布时间的说明
在写这个系列的时候,老魏也是下了很大的决心,因为平时基本上没有时间写文章,这回我要挑战我自己的意志力,决定要把这个系列写完整. 再次呢,老魏不能向大家保证什么时间结束,但基本上要保持一天一篇的进度,如 ...
- hibernate持久化操作注意
15:05 2014/5/21 1.设置lazy为false可以立即加载配合get,lazy默认true,配合load使用. 2.把pojo类定义为final的类.为最终就可以不使用代理 3.pojo ...
- C++练习题
1. 用面向对象的程序描述员工拥有的股票,股票有公司,价格,数量属性,且拥有展现基本数据,更新价格,买进,卖出操作,并具有比较两个股票对象股值大小的比较方法. 2. 用面向对象的程序描述一个栈的操作, ...
- python 读写文本文件
本人最近新学python ,用到文本文件的读取,经过一番研究,从网上查找资料,经过测试,总结了一下读取文本文件的方法. 1.在读取文本文件的时无非有两种方法: a.f=open('filename', ...
- CSS的绝对定位和相对定位
css定位标签position包括两个值:relative(相对定位)和absolute(绝对定位),position样式一般都是和top.bottom.left.right一起使用来确定一个标签的位 ...
- PHP与最丑的后台管理系统
第二天阿Q到公司还是比较早,同事只有阿梅在,阿Q坐在椅子上旋转来旋转去,有点像个小孩子.公司有书柜,书柜上放了好几本很新的php的书,.net的书反倒比较少而且显得老旧.阿Q起身走过去拿了本php翻了 ...
- .NET事件的指导原则
C#允许编写所需的各种类型的事件.但是,为了与.NET Framwork的组件相兼容,开发人员必须遵循微软为此建立的一系列指导原则.这些指导原则的核心是,事件处理程序必须拥有两个参数.第一个参数是一个 ...
- ActionBar官方教程(10)ActionBar的下拉列表模式
Adding Drop-down Navigation As another mode of navigation (or filtering) for your activity, the acti ...
- Form表单中的三种查询方法
1.使用:parameter.G_query_find参数: IF (NAME_IN('PO_HEADERS.PO_HEADER_ID') IS NOT NULL) THEN :paramete ...
- Android开发UI之Fragment-Tabbed Activity的使用
使用ADT新建的时候,可以选择Tabbed Activity,选择新建一个工程. 新建的工程中,选择不同的Tab页显示不同的内容,主要是通过SectionsPagerAdapter类中的Fragmen ...