不要用螺丝刀钉钉子。 std::vector,对于这项任务的最基本形式并不是特别有用:简单的频率计算。来自标准输入的任意输入最好利用关联容器,其中键是输入字符串,值是累积频率。
无序频率计算
无序映射类std::unordered_map 键入std::string 并映射到该字符串的频率计数器,可用于跟踪基本频率。例如:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
int main()
{
std::unordered_map<std::string, unsigned> m;
std::string word;
while (std::cin >> word)
++m[word]; // increment the count for this word
for (auto const& pr : m)
std::cout << pr.first << ':' << pr.second << '\n';
}
按字典顺序排列的频率
注意:使用关联容器std::unordered_map(因此得名)没有特定的顺序。如果您需要字典顺序,您可以简单地使用常规的std::map。如:
#include <iostream>
#include <vector>
#include <string>
#include <map>
int main()
{
std::map<std::string, unsigned> m;
std::string word;
while (std::cin >> word)
++m[word];
for (auto const& pr : m)
std::cout << pr.first << ':' << pr.second << '\n';
}
位置留存频率计算
在计算频率计数器时维护输入流中出现单词的位置也是可能的,并且只需要多一点代码。像以前一样选择无序或有序关联容器,但不是映射到unsigned,而是映射到std::vector<unsigned>,我们在使用输入单词时累积一个单词计数器。每个向量的整体大小仍然保留频率计数器,但向量本身保留相关单词出现在输入流中的位置。例如:
#include <iostream>
#include <vector>
#include <string>
#include <map>
int main()
{
std::map<std::string, std::vector<unsigned int>> m;
std::string word;
unsigned ctr = 0;
while (std::cin >> word)
m[word].push_back(++ctr);
for (auto const& pr : m)
{
std::cout << pr.first << ':' << pr.second.size() << " { ";
for (auto pos : pr.second)
std::cout << pos << ' ';
std::cout << "}\n";
}
}
这将产生以下形式的输出:
word : frequency { n1 n2 n3... }
其中word 是一个不同的单词,frequency 是输入流中的总频率,n1,n2,n3,... 是处理过程中单词出现的位置(从 1 开始)。
希望其中一种方法有用。