【SUFE】C++统计单词出现次数并按照输入顺序输出

本文介绍了一位初学者使用C++统计单词出现次数的方法,通过二维char数组存储单词,利用goto语句处理输入,将单词转换为string类型进行比较计数。尽管时间复杂度较高,达到了n^2,但通过控制输出对齐实现了按输入顺序展示单词及频次。作者欢迎对代码优化和改进的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         对于一个刚学c++不久的小白来说,实在是没有什么方法可以做出来。搜了一圈,不是用vector就是用map。作为一名只学到结构体的大学生,我直呼看不懂。

        所以,我来说说我的思路(高情商:由于我的逻辑还处于待成长阶段,前方会有逻辑不通之处,望指正)

        首先要解决输入的问题。题目规定了使用二维char数组储存words(其实我这里偷懒了,把它转化成了string)。受限于知识水平,我使用了最原始也是最直接的方法——规定输入,把输入结束的标准给它人为规定为“ .”(空格+.)。要让它能一个一个地储存单词,我使用goto语句来循环(递归也可以),终于解决了输入的问题。

        接下来是计数并输出的问题。这里我认为是最难的,因为对与数组的理解还不够,所以在尝试直接比较words[0]与words[1]发现怎样都是不相等后,放弃了比较字符数组的想法,转而把它们变成string类型来比较。

        计数思路:

                从第一个string开始取值,

  1. 比较它与前面所有的单词,如果有相同的,就跳过;如果没有,就说明它是一个新单词,记为真。
  2. 在保证它是新单词的前提下,比较它与后面所有的单词。如果有相同的,那么它出现的次数就加一,没有就接着往后比较。

                这样,就按照顺序记录好了各单词及其出现次数(对于每一个单词,有单词名字、是否为新单词、出现次数,可以理解为被拆散的结构体)。

        (如果我没算错的话,这一步的时间复杂度为n^2

        输出思路:

                这一步难度比前面小了很多,我直接用setw和\t来控制对齐,由于之前有储存过“是否为新单词”的操作,所以可以通过一遍遍历来输出单词及其出现次数。

注:goto语句可以替换成循环语句,例如,void readWords()函数可以改为:

void readWords(){
    cin >> words[i];
    while (words[i][0] != '.') {
    	i++;
    	cin >> words[i];
    }
}

代码(做了一点点修改,可能编译不通过):

#include <iostream>
#include<iomanip>

using namespace std;

int i=0;
char words[1001][21];//定义全局变量,方便直接操作

void readWords(){
    rd://GOTO 此处极易踩雷!
    cin>>words[i];
    if(words[i][0]!='.'){//判断输入是否结束
        i++;
        goto rd;
    }
}

void countAndPrintWords(){
    string wd[i];
    for(int j=0;j<i;j++){
        for(int m=0;m<20;m++){
            if(words[j][m]>=65&&words[j][m]<=90)
                words[j][m]+=32;//大小写转换
            if(words[j][m]>=97&&words[j][m]<=122||words[j][m]=='\'')//convert and remove the punctuation 去除标点
                wd[j]+=words[j][m];
        }
    }
    //cout<<(wd[0]==wd[1])<<"P\n";//debug用
    int k,l,a[i];
    for(k=0;k<i;k++)    a[k]=1;//initialize 初始化为1
    bool newWord[i]={false};//用于判断是否为新单词
    newWord[0]=true;
    for(k=0;k<i;k++){
        l=k-1;
        for(;l>=0;l--){ //in the left of wd[k],if same,it's not a new word 与前面比较
            if(wd[k]==wd[l])
                goto wei;  //GOTO (此处极易踩雷,慎用)
            else if(l==0)     
                newWord[k]=true; //is a new word
        }
        for(l=k+1;l<i;l++){   //in the right of wd[k] 与后面比较
            if(wd[k]==wd[l])
                a[k]++;
        }
        wei: ;//GOTO 最后分号不能掉

    }
    int b=0;
    //cout<<newWord[0]<<endl;
    for(k=0;k<i;k++){   //the cout module
        if(newWord[k]){//if it's a new word,it will be cout
            cout<<setw(10)<<wd[k]<<"\t"<<a[k]<<'\t';
            b++;
            if(b%5==0)//五个换一行
                cout<<'\n';
        }
    }
}

int main()
{
    cout<<"Please input some sentences(you can't enter any Chinese characters.And in the end of all your inputs, you should input a space and input a '.'):\n";
    readWords();
    countAndPrintWords();
    return 0;
}

我们学校使用的是codeblocks,不能用中文注释,而我英文还处于学习阶段(高情商),所以出现了一些Chinglish,见谅。

说在最后:由于时间比较紧,没有时间去优化一下。希望大家能提出一些修改意见,不管是文章的缺点还是代码的优化都可以。

Progress everyday!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值