zoukankan      html  css  js  c++  java
  • 《征服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=0; 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(1); } } buf[len]=''; //给字符串添加结束标志 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=1;
        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))<0)
            {
                pre=pos;
                pos=pos->next_word;
            }
            else break;
        }
    
        /*找到同样的单词*/
        if(word_head!=NULL&&result==0)
        {
            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=1;
        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))<0)
            {
                pre=pos;
                pos=pos->next_word;
            }
            else break;
        }
    
        /*找到同样的单词*/
        if(word_head!=NULL&&result==0)
        {
            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!
    ");
                exit(1);
            }
        }
    
        /*处理输出文件名*/
        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!=0)
            {
                add_word(buf);
            }
        }
    
        /*输出单词出现的频率*/
        dump_word(fp_out);
    
        word_finalize();
       return 0;
    }

    4、新的东西

      在add_word.c中,利用create_word函数创建新的单词结构体时,不可以直接将所传入单词的指针复制给新建的单词,只能将字符串值复制过去。因为所传入单词的指针所指向的内容是每次读取的单词,而不是某一次读取的单词。

  • 相关阅读:
    c#中==和equals的比较
    原型指向改变如何添加方法和访问
    把随机数对象暴露给window成为全局变量
    内置对象Array的原型对象中添加方法
    构造函数可以实例化对象
    原型
    无刷新评论
    大量字符串拼接案例
    元素隐藏占位与不占位
    导航栏切换效果案例
  • 原文地址:https://www.cnblogs.com/xmkk/p/3270301.html
Copyright © 2011-2022 走看看