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

第三篇

一.先贴题目
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同序前的 在前,最后就是按要求输出了。分离单词这一块应该可以再细分出一些情况,让空格转变成可以用来分隔单词的标志,也可以不是,这样就不会读到空串,在数组设置的时候也可以小一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值