计算每个不同单词在其输入C ++中出现的次数

时间:2011-03-19 17:22:49

标签: c++

#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,即使它出现两次。可能是什么问题呢?我不确定我对迭代器的测试是否为空是正确的。

2 个答案:

答案 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;