【问题标题】:Anagram solver in C++C ++中的字谜求解器
【发布时间】:2014-05-09 09:55:25
【问题描述】:

我正在为学校做一个项目,我被困在我认为只是一小部分的事情上,但我无法弄清楚。

这是我目前所拥有的:

#include <iostream>
#include <fstream>
#include <string>
#include <locale>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

int main(int argc, char* argv[])
{
    set<string> setwords;
    ifstream infile;
    infile.open("words.txt"); //reads file "words.txt"
    string word = argv[1]; // input from command line
    transform(word.begin(), word.end(), word.begin(), tolower); // transforms word to lower case.
    sort(word.begin(), word.end()); // sorts the word
    vector<string> str; // vector to hold all variations of the word

    do {
        str.push_back(word);
    }
    while (next_permutation(word.begin(), word.end())); // pushes all permutations of "word" to vector str         

    if (!infile.eof())
    {
        string items;
        infile >> items;
        setwords.insert(items); //stores set of words from file
    }

    system("PAUSE");
    return 0;
}

现在我需要比较文件中的单词和存储在向量 str 中的排列 并打印出真正的单词。

我知道我需要使用 set 类的 find 方法。我只是不知道该怎么做。我尝试这样的事情没有运气,但我的思维过程可能是错误的。

for (unsigned int i = 0; i < str.size(); i++)
    if (setwords.find(word) == str[i])
        cout << str[i] << endl;

如果你们能帮助或指出正确的方向,我将不胜感激。

【问题讨论】:

  • +1 表示努力并在您遇到困难的地方发布,而不是仅仅要求我们为您编写代码。它变得不寻常。

标签: c++ find anagram


【解决方案1】:

首先,我想说这是一个很好问的问题。感谢新用户花时间详细阐述他们的问题。

问题是std::set&lt;&gt;find() 方法返回一个指向它找到的值的迭代器对象,如果找不到,则返回容器的end()。当您将它与 str[i](字符串)进行比较时,它找不到合适的 operator==() 重载,它同时采用迭代器和字符串。

您可以将返回值与end() 进行比较,以确定它是否找到了字符串,而不是与字符串进行全面比较:

if (setwords.find(str[i]) != setwords.end())
//                ^^^^^^     ^^^^^^^^^^^^^^

如果表达式返回true,那么它成功地找到了集合中的字符串。

我还想在您的代码中解决另一个潜在问题。使用if (!file.eof()) 是调节输入的错误方法。您应该改为将提取部分作为条件的一部分,如下所示:

for (std::string item; infile >> item; )
{
    setwords.insert(item);
}

这是另一种方式,使用std::istream_iterator&lt;&gt;

setwords.insert(std::istream_iterator<std::string>(infile),
                std::istream_iterator<std::string>());

【讨论】:

    【解决方案2】:

    您实际上真的接近正确。

    set::find 方法如果在集合中找到,则不会返回值,而是返回an iterator object that points to the value。因此,您的 if 语句将当前字符串与返回的迭代器对象进行比较,而不是迭代器指向的值。

    要获取迭代器指向的值,您只需像使用指针一样取消引用它,方法是在它前面加上一个星号。这意味着您可能希望您的 if 声明如下所示:

    if (*(setwords.find(word)) == str[i])
    

    这适用于在集合中找到值的情况,但对于未找到值的情况会出现问题。如果未找到该值,则返回指向集合中最后一项之后 位置的迭代器 - 您不应尝试取消引用此类迭代器(因为它不指向一个有效的对象)。

    通常执行这些检查的方式是将返回的迭代器与指向集合末尾的迭代器进行比较(例如,在本例中为 set::end)。如果迭代器不匹配,则表示已找到该项目。

    if (setwords.find(word) != setwords.end())
        cout << word << endl;
    

    【讨论】:

      【解决方案3】:

      我认为你需要这样写:

      for (unsigned int i = 0; i < str.size(); i++)
          if (setwords.find(str[i]) != setwords.end())
              cout << str[i] << endl;
      

      但我认为您不需要存储所有排列。您可以存储带有排序字母的单词集。并将其与排序后的单词进行比较.....

      这里有更简单的解决方案

      #include <iostream>                                                                                 
      #include <fstream>                                                                                  
      #include <string>                                                                                   
      #include <locale>                                                                                   
      #include <vector>                                                                                   
      #include <algorithm>                                                                                
      #include <map>                                                                                      
      
      using namespace std;                                                                                
      
      int main(int argc, char* argv[])                                                                    
      {                                                                                                   
          map<string, string> mapwords;                                                                   
          ifstream infile;                                                                                
          infile.open("words.txt"); //reads file "words.txt"                                              
          string word = argv[1]; // input from command line                                               
          transform(word.begin(), word.end(), word.begin(), tolower); // transforms word to lower case.   
          sort(word.begin(), word.end()); // sorts the word                                               
      
          if (!infile.eof())                                                                              
          {                                                                                               
              string item;                                                                                
              infile >> item;                                                                             
              string sorted_item = item;                                                                  
              sort(sorted_item.begin(), sorted_item.end()); // sorts the word                             
              mapwords.insert(make_pair(sorted_item, item)); //stores set of words from file              
          }                                                                                               
      
          map<string, string>::iterator i = mapwords.find(word);                                          
          if(i != mapwords.end())                                                                         
              cout << i->second << endl;
          system("PAUSE");                                                                  
          return 0;                                                                                       
      }   
      

      【讨论】:

        猜你喜欢
        • 2015-09-23
        • 2011-11-02
        • 2015-10-31
        • 1970-01-01
        • 2012-05-17
        • 2019-07-10
        • 2013-05-28
        • 1970-01-01
        • 2011-03-27
        相关资源
        最近更新 更多