Multimap



  • ich soll eine multimap mit strings füllen, die ich vorher aus einer txt datei ausgelesen habe. der text soll beim einlesen mit hilfe der methode parseString in einzelne strings konvertiert werden (also Ignorieren von Punkten,Kommata usw.) neben dem string soll die jeweilige zeilennummer, in der der string (auch mehrmals) auftritt mit abgespeichert werden. Also als Beispiel beim Text

    Alle meine Entchen,
    schwimmen in dem See,
    schwimmen in dem See,

    soll als Ausgabe rauskommen:

    Alle 1
    Entchen 1
    See 2 3
    dem 2 3
    in 2 3
    meine 1
    schwimmen 2 3

    Dieses nennt man auch Cross Reference Liste. Mein erster Ansatz sieht so aus:

    #include <iostream>
    #include <stdlib.h>
    #include <map>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    struct ltstr
    {
        bool operator()(const char* s1, const char* s2) const
        {
             return strcmp(s1, s2) < 0;
        }
    };
    
    void MakeXRef(ifstream fin2, multimap <const char * const, ltstr > m2)
    {
        int tmp = 0; 
        while (!fin2.eof())
        {
              std::string s; 
              fin2 >> s;           
              m2.insert(pair<const char * const, int> (s,++tmp)); //Geht nicht
        }
    }
    
    void PrintXRef(ifstream fin3, multimap <const char * const, ltstr > m3, Iterator j2)
    {
    
       //Soll die Ausgabe durchführen  
    
    }
    
    int main()
    {
        typedef multimap <const char * const, int, ltstr > Mum;
        typedef Mum::iterator Iterator;
        Mum m;
        Iterator j;   
        char buffer [512];
        int line = 0;
        ifstream fin("uebung10.txt");   
        MakeXRef(fin,m);  
        PrintXRef(fin,m,j);   
        system("pause");
        return 0;    
    }
    

  • Mod

    und die frage?



  • s.c_str () sollte funktionieren, aber warum nimmst du nicht einfach generell std::string?
    Und solche großen Sachen wie eine Map sollten eigentlich nicht als Referenz übergeben werden.



  • camper schrieb:

    und die frage?

    Sorry, dieser Teil geht nicht. Ich kann das nicht in die Map einlesen.

    void MakeXRef(ifstream fin2, multimap <const char * const, ltstr > m2)
    {
        int tmp = 0; 
        while (!fin2.eof())
        {
              std::string s; 
              fin2 >> s;           
              m2.insert(pair<const char * const, int> (s,++tmp));
        }
    }
    

  • Mod

    .filmor schrieb:

    s.c_str () sollte funktionieren, aber warum nimmst du nicht einfach generell std::string?
    Und solche großen Sachen wie eine Map sollten eigentlich nicht als Referenz übergeben werden.

    stimmt, aber danach darfst du m2 nicht mehr anfassen. denn s wird zerstört und nimmt den speicher, auf den s.c_str zeigte, gleich mit.

    also:
    multimapstd::string,int
    oder evtl bequemer ist:
    map<std::string,std::vector<int> >



  • Ich habe das soweit umgeschrieben. Danke für Eure Hilfe. Nun habe aber noch ein Problem. Ich erhöhe die tmp Variable ja bei jedem Einlesen um 1. Die tmp Variable spiegelt ja die Zeilennummer wieder. Da heisst er soll diese nur erhöhen wenn er eine Zeile weiter geht und nicht bei jedem String.

    #include <iostream>
    #include <stdlib.h>
    #include <map>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        typedef multimap <std::string, int> Mum;
        typedef Mum::iterator Iterator;
        Mum m;
        Iterator j;   
        int line = 0;
        ifstream fin("uebung10.txt");  
        int tmp = 0; 
        while (!fin.eof())
        {
              std::string s; 
              fin >> s;           
              m.insert(pair<std::string, int> (s,++tmp));
        }
        for (j = m.begin(); j != m.end(); ++j)
                cout << " [" << (*j).first << ", " << (*j).second << "]" << endl;
        system("pause");
        return 0;    
    }
    

    Außerdem ignoriert noch nicht das Komma und den Punkt.

    Die Ausgabe ist bei meinem Programm.

    [, 12]
    [Alle, 1]
    [Entchen,, 3]
    [See,, 7]
    [See., 11]
    [dem, 6]
    [dem, 10]
    [in, 5]
    [in, 9]
    [mein, 2]
    [schwimmen, 4]
    [schwimmen, 8]



  • Wie wärs damit:

    std::vector<std::string> parse (const std::string& s)
    {
        std::vector<std::string> v;
    
        for (std::string::iterator j = s.begin (), i = s.begin (); i != s.end (); ++i)
        {
            if (*i == ' ' || *i == ',' || *i == '.')
            {
                if (j != i - 1)
                    v.push_back (std::string (j, i);
                j = i;
            }
        }
        return v;
    }
    
    // in der Schleife:
    
    std::string s;
    getline (fin, s);
    parse (s) // verarbeiten
    


  • Cool, danke für Deine Mühen. Gleichmal ausprobieren. 👍



  • Meintest Du das so? Da gibt es ein Kovertierungsfehler.

    #include <iostream>
    #include <stdlib.h>
    #include <map>
    #include <fstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    std::vector<std::string> parse (const std::string& s)
    {
        std::vector<std::string> v;
    
        for (std::string::iterator j = s.begin (), i = s.begin (); i != s.end (); ++i)
        {
            if (*i == ' ' || *i == ',' || *i == '.')
            {
                if (j != i - 1)
                    v.push_back (std::string (j, i));
                j = i;
            }
        }
        return v;
    }
    
    int main()
    {
        typedef multimap <std::string, int> Mum;
        typedef Mum::iterator Iterator;
        Mum m;
        Iterator k;   
        int line = 0;
        ifstream fin("uebung10.txt");  
        int tmp = 0; 
        while (!fin.eof())
        {
              std::string s; 
              getline(fin,s);
              parse(s);       
              m.insert(pair<std::string, int> (s,++tmp));
        }
        for (k = m.begin(); k != m.end(); ++k)
                cout << " [" << (*k).first << ", " << (*k).second << "]" << endl;
        system("pause");
        return 0;    
    }
    


  • Statt

    parse (s); m.insert //blabla
    

    das hier:

    std::vector<std::string> v = parse (s);
    for (std::vector<std::string>::iterator i = v.begin (); i != v.end (); ++i)
        m.insert (std::make_pair (*i, tmp);
    ++tmp;
    


  • Immer noch ein Kovertierungsfehler im stl iterator. Außerdem sagt er in der parse Methode im For Schleifen Kopf "instantiated from here" Kennt der Compiler überhaupt die Variable i in der parse Methode??

    #include <iostream>
    #include <stdlib.h>
    #include <map>
    #include <fstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    std::vector<std::string> parse (const std::string& s)
    {
        std::vector<std::string> v;
    
        for (std::string::iterator j = s.begin (), i = s.begin (); i != s.end (); ++i)
        {
            if (*i == ' ' || *i == ',' || *i == '.')
            {
                if (j != i - 1)
                    v.push_back (std::string (j, i));
                j = i;
            }
        }
        return v;
    }
    
    int main()
    {
        typedef multimap <std::string, int> Mum;
        typedef Mum::iterator Iterator;
        Mum m;
        Iterator k;   
        int line = 0;
        ifstream fin("uebung10.txt");  
        int tmp = 0; 
        while (!fin.eof())
        {
              std::string s; 
              getline(fin,s);
              std::vector<std::string> v = parse (s);
              for (std::vector<std::string>::iterator i = v.begin (); i != v.end (); ++i)
                  m.insert (std::make_pair (*i, tmp));
              ++tmp;
        }
        for (k = m.begin(); k != m.end(); ++k)
                cout << " [" << (*k).first << ", " << (*k).second << "]" << endl;
        system("pause");
        return 0;    
    }
    


  • Deine String referenz ist const. nimm einen const_iterator;

    Kurt



  • ZuK schrieb:

    Deine String referenz ist const. nimm einen const_iterator;

    Kurt

    Mann, bist du gut. Super, danke. Jetzt geht es. 😋



  • Die parse Methode macht mir noch Kopfschmerzen. Ich verstehe hier nicht wie die Strings getrennt werden. Wenn ein Punkt, Komma oder Leerzeichen kommt dann wird gefragt ob der string ungleich des strings - 1 ist. Falls ja wird die push_back Methode aufgerufen. Und was wird hier gemacht? Andersrum wenn der string gleich des string - 1 ist wird in j i gespeichert. Ich bin verwirrt. 😕

    Außerdem ist mir bei der Ausgabe der MultiMap aufgefallen, dass außer bei den ersten Wörtern der jeweiligen Zeile jeweils eine Leerzeichen am Anfang des Wortes steht. Beispiel:

    [Alle, 1] //Sieht gut aus
    [ meine, 1] // ?? Was macht dieses Leerzeichen dort?

    vector <string> parseString (string s)
                  {
                      vector <string> v;
    
                      for (string::iterator j = s.begin (), i = s.begin (); i != s.end (); ++i)
                      {
                          if (*i == ' ' || *i == ',' || *i == '.')
                          {
                             if (j != i - 1)
                                 v.push_back (string (j, i));
                             j = i;
                          }
                      }
                      return v;
                  }
    


  • Habs ein wenig umbebaut

    #include <iostream>
    #include <cstdlib>
    #include <map>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <iomanip>
    
    using namespace std;
    
    bool is_separator( string::const_iterator i ) {
        static string sepchars = " \t,.!?";
        return sepchars.find(*i) != string::npos;
    }
    
    std::vector<std::string> parse (const std::string& s){
    
        std::vector<std::string> ret_vect;
    
        for (std::string::const_iterator j = s.begin (), i = s.begin (); i != s.end (); ++i) {
            if ( is_separator( i )  ) {
                if (j != i - 1) {
    	        while ( j < i && is_separator(j) ) 
                        ++j;
                    string word = std::string (j, i);
                    ret_vect.push_back ( word );
                    j = i;
                }
            }
        }
        return ret_vect;
    }
    
    int main()
    {
        typedef multimap <std::string, int> Mum;
        typedef Mum::iterator Iterator;
        Mum m;
        Iterator k;  
        int line = 0;
        ifstream fin("uebung10.txt");  
        int tmp = 0;
        while (!fin.eof()) {
            std::string s;
            getline(fin,s);
            std::vector<std::string> v = parse (s);
            for (std::vector<std::string>::iterator i = v.begin (); i != v.end (); ++i)
                m.insert (std::make_pair (*i, tmp));
            ++tmp;
        }
    
        string prev_word = "";
        for (k = m.begin(); k != m.end(); ++k) {
            if ( (*k).first != prev_word ) {
               prev_word = (*k).first;
               cout << endl << setw( 20 ) << prev_word << " found at line " << setw(4) << (*k).second + 1;
            }
            else {
               cout << ", " << (*k).second;
            }
        }
        cout << endl << endl << "xref done." << endl;
        return 0;    
    }
    

Anmelden zum Antworten