文本文件英文单词的计数

来源:互联网 发布:究极风暴4官方优化补丁 编辑:程序博客网 时间:2024/04/25 21:49

大二课程设计中的一次小练习:
设计
 C  C++ 程序,统计英文文本文件中,出现了多少个单词,每个单词出现了几次。连续的英文字符都认为单词 (不包括数字 ) ,单词之间用空格或标点符号分隔。

单词解析部分应该可以用正则表达式的,之后会进行补充。

第一次发博文,大家多来指点下哇!


/*********************************************************************** * File Name: WordsCount.cpp * Author: 夜阳Version: 1.0 * Created: 2012-6-18 23:28:22 * Last Change: 2012-6-20 9:04:44 * Discription: 统计英文文本文件中,出现了多少个单词,每个单词出现了几次 * *  运行WordsCount.cpp *  第一步输入待检索文件名(如TUT.txt) *  第二步输入输出的文件名(如result.txt) *  检索结果保存在result.txt中 ***********************************************************************/#include <stdio.h>#include "SqList.h"// 线性表的存储与操作int pickword ( FILE *f, char *fword );int main(){    FILE *f1, *f2;    // 指定默认文件名,用字符串保存文件名,便于操作    const int MAX_FILENAME = 20;// 文件名长度    char fname1[MAX_FILENAME] = "TUT.txt";    char fname2[MAX_FILENAME] = "result.txt";    // 用户指定源文件名    printf ( "请指定源文件名(不超过%d个字符):", MAX_FILENAME );    scanf ( "%s", fname1 );    // 用户指定输出文件名    printf ( "请指定要输出结果的文件名(不超过%d个字符):", MAX_FILENAME );    scanf ( "%s", fname2 );    //打开文件    if ( ( f1 = fopen ( fname1, "r" ) ) == NULL )// 异常处理    {        printf ( "打开文件%s失败!\n", fname1 );        return 0;    }    else        printf ( "打开文件%s成功!\n", fname1 );    SqList L;// 建立线性表    SqListInit ( &L );// 初始化线性表    char fword[MAX_CHARACTER];// 使用fword数组保存文件中的单词    fword[MAX_CHARACTER - 1] = '\0';    int i = -1;// 设置i为插入位置    while ( !feof ( f1 ) )// 读文件未结束    {        int judge = pickword ( f1, fword );// 从f指向的文件中提取单词到fword中        if ( -1 == judge )// 数组越界时提示并退出        {            printf ( "存在单词字符长度超过数组界限\n" );            return -1;        }        if ( SqListBSearch ( &L, fword, i ) )// i返回插入位置或单词在线性表中位置        {            // 在线性表中找到该单词            L.elem[i].count++;// 单词出现次数加1        }        else        {            // 线性表中未找到该单词            SqListInsert ( &L, i, fword );// 在第i个位置上插入        }    }    // 打开文件fname2,将内容写入    if ( ( f2 = fopen ( fname2, "w" ) ) == NULL )// 异常处理    {        printf ( "写入文件%s失败!\n", fname2 );        return 0;    }    else        printf ( "文件已写入%s!\n", fname2 );    // 将结果写入f2指向的文件中    SqListPrint ( f2, fname1, &L );    // 关闭文件    fclose ( f1 );    fclose ( f2 );}int pickword ( FILE *f, char *fword )// 从f指向的文件中提取单词到fword中{    char ch;// ch储存待检测字符    for ( int j = 0 , flag = 0 ; !feof ( f ) ; )// 逐个对字符进行检测,flag用于标记,为0时表示单词中无字母    {        if ( j >= MAX_CHARACTER )// 判断数组是否越界        {            return -1;        }        ch = fgetc ( f );// 获取字符        if ( ch >= 'A' && ch <= 'Z' )// 大写字符转小写保存在fword数组中        {            fword[j++] = ch + 32;            flag = 1;        }        if ( ( ch >= 'a' && ch <= 'z' ) )// 小写字符保存在fword数组中        {            fword[j++] = ch;            flag = 1;        }        if ( '-' == ch && fword[j - 1] >= 'a' && fword[j - 1] <= 'z' )// 若单词中带连字符,将连字符保存在fword数组中        {            fword[j++] = ch;        }        if ( ! ( ( ch >= 'A' && ch <= 'Z' ) || ( ch >= 'a' && ch <= 'z' ) || '-' == ch )                && flag == 1 )// 过滤单词中的非字母字符        {            if ( fword[j - 1] == '-' )// 排除类似于 a- 的单词                fword[j - 1] = '\0';            fword[j] = '\0';// fword数组以'\0'结尾            return 0;        }    }}

/*********************************************************************** * File Name: SqList.h * Author: 夜阳Version: 1.0 * Created: 2012-6-18 10:25:27 * Last Change: 2012-6-19 21:36:53 * Discription: 顺序表的初始化,建立,插入,查找,相关结果输出 ***********************************************************************/#include <stdio.h>#include <malloc.h>#include <string.h>const int MAX_CHARACTER = 50;// 单词最大长度定为50(TUT.txt文中最长单词为production-education-researching)//函数结果状态代码#define TRUE1#define FALSE0#define OK1#define ERROR0#define OVERFLOW -2// 线性表的动态分配顺序存储结构#define LIST_INIT_SIZE 100// 线性表存储空间的初始分配量#define LISTINCREMENT 10// 线性表存储空间的分配增量// 顺序存储结构的线性表类型typedef struct{    char word[MAX_CHARACTER];// 存储单词,不超过50个字符    int count;// 单词出现次数} ElemType;typedef struct{    ElemType *elem;// 存储空间基址    int length;// 当前长度    int listsize;// 当前分配的存储容量(以sizeof(ElemType)为单位)} SqList;// 线性表的初始化int SqListInit ( SqList *L ){    // 构造一个空的线性表L    L->elem = ( ElemType * ) malloc ( LIST_INIT_SIZE * sizeof ( ElemType ) );    if ( !L->elem ) return OVERFLOW;// 存储分配失败    L->length = 0;    L->listsize = LIST_INIT_SIZE;    return OK;}// 线性表的插入int SqListInsert ( SqList *L, int i, char *fword ){    // 在顺序线性表L中第i个位置之前插入新的元素e    // i的合法值为1≤i≤L.Length + 1    if ( i < 0 || i > L->length )    {        printf ( "i的值不合法!" );        return ERROR;// i的值不合法    }    if ( L->length >= L->listsize )    {        // 当前存储空间已满,增加分配        ElemType *newbase = ( ElemType * ) realloc ( L->elem,                            ( L->listsize + LISTINCREMENT ) * sizeof ( ElemType ) );        if ( !newbase )            return OVERFLOW;// 存储分配失败        L->elem = newbase;// 新基址        L->listsize += LISTINCREMENT;// 增加存储容量    }    ElemType *p, *q;    q = &L->elem[i];    for ( p = &L->elem[L->length - 1]; p >= q; p-- )// 插入位置之后元素逐个右移    {        * ( p + 1 ) = *p;    }    strcpy ( q->word, fword );// 复制fword中的字符到L->elem[i-1].word中    L->elem[i].count = 1;// 设置计数初值为1    L->length++;// 表长增1    return OK;}// 线性表二分法查找int SqListBSearch ( SqList *L, char *sword, int &i ){    if ( L->length == 0 )// 当线性表为空时    {        i = 0;// i返回单词插入位置        return ERROR;    }    // 线性表不空时,在线性表L中查找元素sword,用i返回其在线性表中的位置    int low = 0, high = L->length - 1, mid = L->length;    while ( low <= high )    {        mid = ( low + high ) / 2;        int k = strcmp ( L->elem[mid].word, sword );        if ( k == 0 )// 待查单词sword等于中间值,找到待查元素        {            i = mid;            return OK;// 查找成功,函数返回值为1,用i返回所查元素在线性表中的位置        }        else if ( k > 0 )// 待查单词sword小于中间值,继续在前半区间进行查找        {            high = mid - 1;            i = low;        }        else// 待查单词sword大于中间值,继续在后半区间进行查找        {            low = mid + 1;            i = high + 1;        }    }    return ERROR;// 线性表中不存在待查元素,函数返回值为0,i返回单词插入位置}void SqListPrint ( FILE *f, char fname[], SqList *L ){    fprintf ( f, "文档 %s 中总计有%d个单词\n", fname, L->length );// 输出统计信息,L->length为单词个数    fprintf ( f, "序号  单词                 个数\n" );    for ( int i = 0, j = 1 ; i < L->length ; i++, j++ )// j-序号        fprintf ( f, "%-5d %-20s %d\n", j, L->elem[i].word, L->elem[i].count );}

结果显示:


原创粉丝点击