首页 > 解决方案 > 如何使用两个向量打印给定输入字符串中每个单词的频率?

问题描述

这是我尝试将字符串拆分为单词然后继续前进的方法,但这不起作用。例如,输入是:hey hi Mark hi mark 那么输出应该是:hey-1 hi-2 Mark-1 hi-2 mark-1

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main() 
{
    vector<vector<string> > strs;
    string str;
    cout<<"Enter your strings"<<endl;
    getline(cin, str);
    int len=str.length();
    int j=0;
    string s="";
    for(int i=0; i<len; i++){
      s+=str[i];
      if(str[i+1]==' ' || i+1==len){
        strs[0][j]=s;
        s="";
        j++;
        i++;
      }
    }
    strs[0][j]="NULL";
    int freq;
    vector<int> frequency;
    for(int n=0; strs[0][n]!="NULL" ;n++){
      freq=1;
      for(int m=0; strs[0][m]!="NULL"; m++){
        if(strs[0][n]==strs[0][m]){
          freq++;
        }
        frequency.push_back(freq);
      }
    }
    for(int x=0; strs[0][x]!="NULL"; x++){
      cout<<strs[0][x]<<" - "<<frequency[x]<<endl;
    }
    return 0;
}

标签: c++stringvector

解决方案


所以,我认为你使用 2 的方法std::vectors很遗憾是错误的。您不完全了解 和 之间的char区别std::string

你需要了解一下。

有一种或多或少的标准方法来计算容器中的东西,比如字符串或一般情况。

我们可以使用关联容器,例如 astd::map或 a std::unordered_map。在这里,我们将“键”(在本例中为要计数的“单词”)与一个值(在本例中为特定单词的计数)相关联。

幸运的是,这些地图有一个非常好的索引运算符[]。这将查找给定的键,如果找到,则返回对该值的引用。如果未找到,则它将使用密钥创建一个新条目并返回对新条目的引用。因此,在这两种情况下,我们都会获得对用于计数的值的引用。然后我们可以简单地写:

std::map<std::string, int> counter{};
counter[word]++;

就是这样。更多是不必要的。请参见:

#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>

int main() {
    // Our test String
    std::string text{"hey hi Mark hi mark"};
    
    // Here, we will store the result of the counting
    std::unordered_map<std::string, unsigned int> counter;
    
    // Now count all words. This one line does all the counting
    for (std::istringstream iss{text}; iss >> text; counter[text]++);
    
    // Show result to user
    for (const auto& [word, count] : counter) std::cout << word << '-' << count << ' ';
}

似乎拆分字符串对您来说有些困难。这里还有许多可用的可能解决方案。

更复杂和更先进的解决方案之一是使用std::sregex_token_iterator. 有了它,您可以轻松地迭代std::regex字符串中的模式(由 a 描述)。

最终的代码看起来几乎相同,但结果会更好,因为例如可以排除标点符号。

例子:

#include <iostream>
#include <string>
#include <unordered_map>
#include <regex>
#include <iterator>

using Iter = std::sregex_token_iterator;
const std::regex re{R"(\w+)"};

int main() {
    // Our test String
    std::string text{"hey hi Mark, hi mark."};
    
    // Here, we will store the result of the counting
    std::unordered_map<std::string, unsigned int> counter;
    
    // Now count all words. This one line does all the counting
    for (Iter word(text.begin(), text.end(), re); word != Iter(); counter[*word++]++);
    
    // Show result to user
    for (const auto& [word, count] : counter) std::cout << word << '-' << count << ' ';
    
}

推荐阅读