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函数创建新的单词结构体时,不可以直接将所传入单词的指针复制给新建的单词,只能将字符串值复制过去。因为所传入单词的指针所指向的内容是每次读取的单词,而不是某一次读取的单词。

  • 相关阅读:
    June. 26th 2018, Week 26th. Tuesday
    June. 25th 2018, Week 26th. Monday
    June. 24th 2018, Week 26th. Sunday
    June. 23rd 2018, Week 25th. Saturday
    June. 22 2018, Week 25th. Friday
    June. 21 2018, Week 25th. Thursday
    June. 20 2018, Week 25th. Wednesday
    【2018.10.11 C与C++基础】C Preprocessor的功能及缺陷(草稿)
    June.19 2018, Week 25th Tuesday
    June 18. 2018, Week 25th. Monday
  • 原文地址:https://www.cnblogs.com/xmkk/p/3270301.html
Copyright © 2011-2022 走看看