初级-文件操作与字符处理

来源:互联网 发布:linux 安装ftp 编辑:程序博客网 时间:2024/06/03 22:39

第三篇

一.先贴题目
1109 综合实验:文件操作与字符处理

在当前目录中存在文件名为”case1.in”(其中case后为数字1,不是字母l,写错提交后会判错)的文本文件,
其内容为一篇英文文章(以EOF作为结束标志)。现要求读取该文本文件内容,统计文章中每个单词出现的次数,
并输出出现次数最多的前5个单词及其出现次数(按出现次数由多到少的顺序输出,次数相同时按字典顺序输出,
不足5个单词时,按序输出全部单词)。程序中注意如下细节:
(1) 空格、标点符号与回车符起到分隔单词的作用。
(2) 文章一行的末尾可能有连字符,出现连字符时,该行最末的字符串与下行最先出现的字符串构一个单词;
(3) 名词缩写算一个单词;
(4) 数字不算单词;
(5) 单词不区分大小写;
(6) 输出时单词全使用小写;

#include "stdio.h" #include "math.h" #include "string.h" #include "stdlib.h" _______________________ main() {          _______________________ } 

输入格式
文件case1.in中一篇英文文章,包含多段文字,单词数不超过10000,每个单词不超过20个字符

输出格式
按题意输出答案

输入样例
(如case1.in内容如下)
I am a student. My school is SCAU. It is a beau-
tiful university. I like it.

输出样例
a 2
i 2
is 2
it 2
am 1

二.思路分析
这是比较接近于最近写的一个实验题,也是第一个实验题。这道题的要求比较多,从题目的EOF开始,说明用fgetc 函数来读取文件好一点,一开始是用fgets来做,多设置了一个变量来存储有n行,但是还不如用fgetc,反正基本操作都差不多,少一个变量,也少一点思考量。
这道题大概要分成几个步骤或者说模块:

  1. 先 分离出单词来。
  2. 统计所有单词的全部出现个数(包括重复的也统计),用sum[i]存起来
  3. 去除掉同样的单词的个数并置为0
  4. 将单词为空串的个数置为0
  5. 对全部,排sum[i]序,把大的放在前面
  6. 找的非0的sum[i],那样就能知道总共有几个非0的有效的唯一单词的个数
  7. 再来对全部,将sum[i]相同的单词按序来排
  8. 按照题目条件,如果有效的唯一单词的个数大于等于5,就输出前5的word[i] 和sum[i];如果小于5就全部输出。

三。具体代码实现

#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){    FILE *fp = fopen("case1.in","r");    char ch;    char word[50100][21];      //这里设置的单词数组的大小要较大于10000,    int i=0;     int j=0;    int t,k;    int g;    int sum[10100]={0};    int nozerolen;  //代表非0的唯一单词的个数    int wordsum;    //代表单词的全部个数    /*          分离单词    */    while((ch=fgetc(fp))!=EOF)    {        if(ch<='Z'&&ch>='A')            ch+=32;        if(ch =='-')        {            ch = fgetc(fp);            if(ch=='\n')                continue;            else            {                i++;                j=0;                //continue;            }            /*            - 的情况比较多样,如果-后是\n 那么就和前面的是同一个单词,跳过就好,如果-后是其他东西,那就再开下一个单词来存,同时不忘记将j重置为0.            */        }        if(ch=='\n')            continue;           //回车不作为分离单词的因素。        if(ch==' '||ch==','||ch=='='||ch=='.')        {            i++;            j=0;            continue;            /*            其中 = . , ‘ ’作为分离单词的四大符号。            */        }        if(ch>='0'&&ch<='9')        {            continue;            //数字不作为单词的成分        }        word[i][j++]=ch;        //利用二维数组来存取字符    }    wordsum = i;    //获取单词的个数    wordsum++;    //由于从0开始,转化为常规操作从1开始数的 因此变大一个。/*统计所有出现的单词的出现的次数,即便重复也同样统计。*/    for(t=0;t<wordsum;t++)    {        for(k=0;k<wordsum;k++)        {            if(strcmp(word[t],word[k])==0)            {                sum[t]++;            }        }    }    /*    对于单词一样的其他单词将它们的单词出现次数置成0.    */    for(t=0;t<wordsum-1;t++)    {        for(k=t+1;k<wordsum;k++)        {            if(strcmp(word[t],word[k])==0)            {                sum[k]=0;            }        }    }    //将空串置成0    for(i=0;i<wordsum;i++)    {        if(strlen(word[i])==0)        {            sum[i] =0;        }    }      /*     进行冒泡排序,对于全部单词,从大到小进行排序。     这里注意在替换单词出现次数的时候,要将单词也一起替换。     */    for(t=0;t<wordsum-1;t++)    {        for(k=0;k<wordsum-1-t;k++)        {            if(sum[k]<sum[k+1])            {                int temp;                temp = sum[k+1];                sum[k+1] = sum[k];                sum[k] = temp;                char tt[30];                strcpy(tt,word[k+1]);                strcpy(word[k+1],word[k]);                strcpy(word[k],tt);            }        }    }    /*     计算出非0的唯一单词的个数。    */    for(t=0;t<wordsum;t++)    {        if(sum[t]==0)        {            break;        }    }    nozerolen = t+1;    //也是一样转化为常规的从1开始计算/*再对全部非0的单词数来排序,针对于 那些sum相同的但序在后的,排成同sum序在前*/    for(t=0;t<nozerolen-1;t++)    {        for(k=0;k<nozerolen-1-t;k++)        {            if(sum[k]==sum[k+1]&&strcmp(word[k],word[k+1])>0)            {                int temp;                temp = sum[k+1];                sum[k+1] = sum[k];                sum[k] = temp;                char tt[30];                strcpy(tt,word[k+1]);                strcpy(word[k+1],word[k]);                strcpy(word[k],tt);            }        }    } /*按题目要求的,非0数大于5,就输出前5,如果小于5,就输出全部。*/    if(nozerolen<5)    {        for(g=0;g<nozerolen;g++)        {            printf("%s %d\n",word[g],sum[g]);        }    }    else    {        for(t=0;t<5;t++)        printf("%s %d\n",word[t],sum[t]);    }    fclose(fp);}

四.总结反思
其实感觉这道题,还是没做好,因为只是处理了 ‘=’这种特殊情况,可是实际上还可以是其他的特殊字符。还有就是在分离单词那一块,实际上由于,空格并非能全部适用于全部的分离单词的情况,所以会读取到一些空串,才有后面的将空串置0的操作。这道题感觉最复杂的是分离出单词来,其他的就是一些操作,比如统计全部单词出现的次数,再对于出现过的单词的sum[i]置成0,然后是将空串的sum[i]置成0,再排sum[i]的序,再统计非0的个数,再排让sum同序前的 在前,最后就是按要求输出了。分离单词这一块应该可以再细分出一些情况,让空格转变成可以用来分隔单词的标志,也可以不是,这样就不会读到空串,在数组设置的时候也可以小一些。

阅读全文
0 0