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的更多相关文章

  1. C++中的智能指针、轻量级指针、强弱指针学习笔记

    一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...

  2. Git学习笔记(二) · 非典型性程序猿

    远程库的使用 前面说到的都是git在本地的操作,那么实际协作开发过程中我们肯定是要有一个远程版本库作为项目的核心版本库,也就是投入生产使用的版本.这里我们以 Github为例.Github是一个开放的 ...

  3. 【Python自然语言处理】第一章学习笔记——搜索文本、计数统计和字符串链表

    这本书主要是基于Python和一个自然语言工具包(Natural Language Toolkit, NLTK)的开源库进行讲解 NLTK 介绍:NLTK是一个构建Python程序以处理人类语言数据的 ...

  4. 《征服 C 指针》笔记6:练习——挑战那些复杂的声明

    应该是小试牛刀的时候了. 在 ANSI C 的标准库中,有一个 atexit()函数.如果使用这个函数,当程序正常结束的时候,可以回调一个指定的函数. atexit()的原型定义如下: int ate ...

  5. 【视频编解码·学习笔记】11. 提取SPS信息程序

    一.准备工作: 回到之前SimpleH264Analyzer程序,找到SPS信息,并对其做解析 调整项目目录结构: 修改Global.h文件中代码,添加新数据类型UINT16,之前编写的工程中,UIN ...

  6. 【视频编解码·学习笔记】13. 提取PPS信息程序

    PPS结构解析 与之前解析SPS方式类似 一.定义PPS类: 在3.NAL Unit目录下,新建PicParamSet.cpp和PicParamSet.h,在这两个文件中写入类的定义和函数实现. 类定 ...

  7. JZ2440学习笔记之通过J-Link单步裸机程序(Keil+J-Link)

    我们还是使用JZ2440学习笔记之第一个裸机程序(Keil-MDK)里面的程序,但是把延时拿掉,要不然单步的时候一直在delay里面: int main(void) { // Set GPF4/5/6 ...

  8. 广师大学习笔记之文本统计(jieba库好玩的词云)

    1.jieba库,介绍如下: (1) jieba 库的分词原理是利用一个中文词库,将待分词的内容与分词词库进行比对,通过图结构和动态规划方法找到最大概率的词组:除此之外,jieba 库还提供了增加自定 ...

  9. web前端学习笔记:文本属性

    今天的web前端笔记主要讲述文本属性,希望能帮助到正在学习web前端开发的初学者们,废话不多说了,一起来看看文本属性的相关内容吧. 文本属性 文本缩进 将Web页面上的一个段落第一行缩进,这是一种最常 ...

随机推荐

  1. sbrk and coreleft

    一.sbrk 函数来源:TC2.0.Linux 函数名: sbrk 功 能: 增加程序可用数据段空间,增加大小由参数 incr决定 . 返回值:函数调用成功返回一指针,指向新的内存空间.函数调用失败则 ...

  2. 更改Keil工程名

    假设原工程名为A,需要改成B. 1, 在工程目录下,把A.vuopt和A.uvproj改成B.uvopt和B.uvproj. 2,删除其他A文件. 3,打开工程B.然后修改下面位置: Project ...

  3. C#中如何按字节数截取字符串?

    http://www.cnblogs.com/xuejie/archive/2012/12/14/2818452.html

  4. ExtJS4加载FormPanel数据的几种方式

    我们做web应用最多的就是处理表单,extjs为我们提供了很多处理表单的功能,很多初学者疑惑怎么加载表单数据,到底能用什么方式加载?本文中,我将我自己实验过的进行一下总结,自己备忘,也希望能帮助到其他 ...

  5. python 下载安装及setuptools应用

    1.首先下载python安装程序,下载地址:https://www.python.org/download/releases/2.7.8/ 如下图: 因为我的机器是32位的就选择了Windows x8 ...

  6. css3创建动画

    @keyframes ico{ 0% { top: -100%; } 100%{ top:4%; } } @-webkit-keyframes ico{ 0% { top: -100%; } 100% ...

  7. python join字符连接函数的使用方法

    就是把一个list中所有的串按照你定义的分隔符连接起来,比如: >>> import string >>> >>> >>> li ...

  8. BZOJ 3997 [TJOI 2015 组合数学] 解题报告

    这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2 ...

  9. 开启CURL扩展,让服务器支持PHP curl函数(远程采集)

    关于开启Curl的方法模板天下小编在此给大家简单说一下 curl().file_get_contents().snoopy.class.php这三个远程页面抓取或采集中用到的工具,默迹还是侵向于用sn ...

  10. loadrunner http协议put模式脚本编写

    web_submit_data("rest", "Action=http://www.test.com/111ojhjh.do", "Method=P ...