7-3 词频统计 (30 分)

思路

使用java更简单,可以一次读取然后用split进行分割字符串,再进行判断
如果使用c的话只能曲线救国
代码思路:
这个题的难点在于什么时候停止输入,什么时候分割字符。
因为题目的输入可能有几行,不能使用gets,因为分割符号不止是空格和回车,所以scanf也不行。
c里面虽然有可以满足我们要求的输入方式,但是不常用,所有我们需要进行曲线救国:
因为题目要求除了字母和数字和下划线就认为是分隔符;
那么我不再找分割符号,而是只读取“单词”:

  • 我们每次读取一个字符,
    • 如果符合单词的要求,就加到单词中,字符长度+1;
  • -如果不是单词就重置我们单词的长度(长度重置就是认为该单词结束,需要读取下一个单词了)。
    • 如果为“#”就结束输入。

题解

#include <bits/stdc++.h>
using namespace std;
map<string, int> mp;
bool cmp(pair<string, int> a, pair<string, int> b)
{
    if (a.second == b.second)
        return a.first < b.first;
    return a.second > b.second;
}

int main()
{
    char c;
    string str;
    str.clear();
    while (scanf("%c", &c) != EOF)//不能用cin
    {

        if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_')
        {
            if (c >= 'A' && c <= 'Z')//将大写字母转换为小写
                c = c - 'A' + 'a';
            if (str.length() < 15)//只要没超过15个字母这个单词就可以继续存
            {
                str += c;
            }
        }
        else if (str.length() > 0)//如果不符合“单词”的要求就重置单词记录下一个单词。
        {
            mp[str]++;
            str.clear();
        }
//结束条件,结束条件要写在if (str.length() > 0)的下面
//原因:防止"adsda#"的情况,如果写在上面,这种情况“adsda”就无法读入了
        if (c == '#')
            break;
    }
    vector<pair<string, int>> vec(mp.begin(), mp.end());

    sort(vec.begin(), vec.end(), cmp); //排序
    int llen = vec.size() * 0.1;
    cout << vec.size() << endl;
    for (int i = 0; i < llen; i++)
    {
        cout << vec[i].second << ":" << vec[i].first << endl;
    }
    return 0;
}
posted @ 2021-12-01 15:57  kingwzun  阅读(216)  评论(0编辑  收藏  举报