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;
}