Question

I am trying to write a program that takes lines from an input file, sorts the lines into 'signatures' for the purpose of combining all words that are anagrams of each other. I have to use a map, storing the 'signatures' as the keys and storing all words that match those signatures into a vector of strings. Afterwards I must print all words that are anagrams of each other on the same line. Here is what I have so far:

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <fstream>

using namespace std;

string signature(const string&);
void printMap(const map<string, vector<string>>&);

int main(){
string w1,sig1;
vector<string> data;
map<string, vector<string>> anagrams;
map<string, vector<string>>::iterator it;
ifstream myfile;
myfile.open("words.txt");

while(getline(myfile, w1))
{
  sig1=signature(w1);        
  anagrams[sig1]=data.push_back(w1); //to my understanding this should always work,
}                                    //either by inserting a new element/key or
                                     //by pushing back the new word into the vector<string> data
                                     //variable at index sig1, being told that the assignment operator
                                     //cannot be used in this way with these data types
myfile.close();

printMap(anagrams);

return 0;
}

string signature(const string& w)
{
string sig;
sig=sort(w.begin(), w.end());
return sig;
}

void printMap(const map& m)
{
for(string s : m)
{
  for(int i=0;i<m->second.size();i++)
     cout << m->second.at();
  cout << endl;
}
}

The first explanation is working, didn't know it was that simple! However now my print function is giving me: prob2.cc: In function âvoid printMap(const std::map<std::basic_string<char>, std::vector<std::basic_string<char> > >&)â: prob2.cc:43:36: error: cannot bind âstd::basic_ostream<char>::__ostream_type {aka std::basic_ostream<char>}â lvalue to âstd::basic_ostream<char>&&â In file included from /opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/iostream:40:0, Tried many variations and they always complain about binding

void printMap(const map<string, vector<string>> &mymap)
{
for(auto &c : mymap)
  cout << c.first << endl << c.second << endl;
}
Était-ce utile?

La solution

anagrams[sig1] will return a reference to a vector<string>. Rather than assign to it, you just want to push_back onto it.

sig1 = signature(w1);
anagrams[sig1].push_back(w1);

As your code is written right now, it's trying to replace the vector instead of add to it. For example, let's assume your input contains both was and saw, and that your signature sorts the letters of the string.

What you want for this case is:

  1. read "was"
  2. sort to get "asw"
  3. insert "was" to get: anagrams["asw"] -> ["was"]
  4. read "saw"
  5. Sort to get "asw" (again)
  6. insert "saw" to get: anagrams["asw"] -> ["was", "saw"]

With the code as you've tried to write it, however, in step 6, instead of adding to the existing vector, you'd overwrite the current vector with a new one containing only "saw", so the result would be just anagrams["asw"] -> ["saw"].

As far as printmap goes: the items in the map aren't std::strings, they're std::pair<std::string, std::vector<std::string>>, so when you try to do:

void printMap(const map& m)
{
    for(string s : m)

...that clearly can't work. I'd usually use:

for (auto s : m) 

...which makes it easy to get at least that much to compile. To do anything useful with the s, however, you're going to need to realize that it's a pair, so you'll have to work with s.first and s.second (and s.first will be a string, and s.second will be a std::vector<std::string>). To print them out, you'll probably want to print s.first, then some separator, then walk though the items in s.second.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top