#include <iostream>
#include <string>
#include <sstream>
#include <map>
int main()
{
std::string input;
std::cout << "Enter input: ";
std::getline(std::cin, input);
std::map<std::string, int> m;
std::map<std::string, int>::iterator it;
std::istringstream iss(input);
std::string words;
do {
iss >> words;
it = m.find(words);
if(it != m.end())
{
m.insert(it, std::pair<std::string, int>(words, m[words] + 1));
}
else
{
m.insert(std::pair<std::string, int>(words, 1));
}
}while(iss);
for(std::map<std::string, int>::iterator it = m.begin(); it != m.end(); ++it)
{
std::cout << it->first << " - " << it->second << std::endl;
}
return 0;
}
问题在于它为每个单词打印1,即使它出现两次。可能是什么问题呢?我不确定我对迭代器的测试是否为空是正确的。
答案 0 :(得分:2)
因为map
使用默认构造函数自动构造项,所以当您访问尚不存在的键时,您可以简单地说:
while (iss >> words) {
++m[words];
}
新项目的默认值为0(请参阅this question)。
你以前的地图逻辑很好,只是你的情况已经逆转了;它应该是if (it == m.end())
而不是!=
,因为find()
会在找不到时返回end()
。正如GWW在他的回答中指出的那样,当项目已经在地图中时,insert
无效,这是您唯一使用它的时间。
另外,你的循环没有正确处理输入;您需要在读取值后检查流的状态是否无效,但在之前使用它(因为如果流在其末尾,则值为垃圾) 。处理输入的惯用方法是使用while (is >> value)
构造;如果你想自己做,那么这是等价的:
while (true) {
iss >> words;
if (!iss) {
break;
}
// Process words...
}
最后,将变量“单词”命名为一次只包含一个单词时,会有点误导; - )
答案 1 :(得分:1)
我将引用cplusplus.com。
因为地图容器不允许 对于重复的键值, 插入操作检查每个 元素插入是否另一个 元素已存在于 具有相同键值的容器,如果 所以,元素没有插入和 它的映射值不会改变 方式。
在您的代码中,您尝试在地图中已有的元素上插入。你应该改变
m.insert(it, std::pair<std::string, int>(words, m[words] + 1));
到
it->second+=1;