Map mit Indexen oder Vectoren mit keys



  • Hallo,

    ich will mir ein kleines Vokabeltrainerprogramm schreiben (dazu hatte ich schonmal einen Thread eröffnet) Anfangs wollte ich dazu einen vector<voc> verwenden mit:

    struct voc
    {
     string word;
     vector<string> meanings;
     char diff;
    }
    

    naja, da hatte ich jetzt das Problem, dass der Vector nach Möglichkeit sortiert vorliegen soll (natürlich nach dem "word" sortiert), da unter Umständen ein Wort mehrmals vorkommen kann und sich so beim Abfragen recht leicht kontrollieren lässt, ob die Eingabe vielleicht einer anderen, aber gleichlautenden Vokabel entspricht.

    Das lässt sich hier ja aber nicht so einfach realisieren, da ich ja quasi nach vector[i].word ordnen muss. Darum hab ich mir dann mal die multymap angesehen, und die schien recht gut zu passen. Ist bereits nach keys sortiert, ich kann ganz banal über das Wort direkt zugreifen...
    naja, bis ich dann daran dachte dass ich beim zusammenstellen einer Abfrage ja die ganze map durchlaufen muss, und ergo einen index brauche... den sie aber nicht zu haben scheint.

    Lässt sich das ganze jetzt irgendwie "einfach" realisieren, oder muss ich mir doch eine eigene sortedVector Klasse schreiben, die dann immer zum vergleichen halt vector[i].word nimmt?

    Danke im vorraus.



  • Hi!

    Nimm doch die Map der STL:

    std::map< std::string, std::string > bla; // key = englisches wort, value = deutsches wort
    

    Zugreifen kannst du dann einfach per:

    std::cout << bla[ "englischeswort" ];
    

    grüße



  • Shinja schrieb:

    naja, da hatte ich jetzt das Problem, dass der Vector nach Möglichkeit sortiert vorliegen soll (natürlich nach dem "word" sortiert), da unter Umständen ein Wort mehrmals vorkommen kann und sich so beim Abfragen recht leicht kontrollieren lässt, ob die Eingabe vielleicht einer anderen, aber gleichlautenden Vokabel entspricht.

    Warum defnierst du dir keinen Vergleichs-Operator für deine Vokabeln?

    bool operator<(const voc& l,const voc& r)
    {
      return l.word<r.word;
    }
    

    Dann packst du die Vokabeln in einen vector<>, sortierst sie über std::sort() und kannst je nach Bedarf über den Index (Auswahl nach Position) oder über std::equal_range() und Kollegen (Auswahl nach Inhalt) auf deine Elemente zugreifen.
    (der umgekehrte Weg wäre es, durch eine map<> per advance zu navigieren - aber das ist deutlich langsamer)

    ob die Eingabe vielleicht einer anderen, aber gleichlautenden Vokabel entspricht.

    Wie kommt es überhaupt daß du mehrere gleichlautende Vokabeln erhältst? Nach deiner Vorgabe sieht es so aus, als ob alle Übersetzungen eines Begriffs in voc::meanings gespeichert werden.



  • hiho

    vielen Dank CStoll, das klingt schonmal gut. Nur kurz als Frage: wohin kommt diese Operatorueberladung? Einfach global, oder muss ich voc zu ner Klasse umfunktionnieren und sie darein stellen? Oder muss ich den Comperator irgendwie an den vector uebergeben?

    Dass ich gleichlautende Vokabeln habe liegt an den Homophonen (im Deutschen> sein als Possessivpronomen (sein Pferd) und als Verb (ich bin...)) Und da ich den voctrainer fuer japanisch brauche ist es noch viel wichtiger, da es dort extrem viele Homophone gibt, die aber eigentlich unabhaengige Woerter sind (mit verschiedenen Kanji geschrieben, aber in Roomaji eben dann gleich, leider...)

    Achja, OT Frage: Ich kenne mich mit Iteratoren noch gar nicht aus und hab mir jetzt mal aus der www.cppreference.com Beschreibung was zusammengebastelt, weil ich fuer vector.insert(loc,term) nen Iterator als erstes Argument brauche. Ist folgendes korrekt:

    vector<int> a(10,20);
    int index=5;
    vector<int>::iterator it=a.begin();
    it+=index;
    a.insert(it,7);
    

    Vielen Dank nochmal!



  • Shinja schrieb:

    hiho

    vielen Dank CStoll, das klingt schonmal gut. Nur kurz als Frage: wohin kommt diese Operatorueberladung? Einfach global, oder muss ich voc zu ner Klasse umfunktionnieren und sie darein stellen? Oder muss ich den Comperator irgendwie an den vector uebergeben?

    Die kannst du global unter die Definition deiner Klasse stellen.
    (übrigens ist der Vector überhaupt nicht in der Lage, Comparatoren anzunehmen. Wenn, dann müsstest du ihn an sort() etc weitergeben - diese Algorithmen übernehmen jedoch automatisch den op<, wenn sie ihn finden).

    Dass ich gleichlautende Vokabeln habe liegt an den Homophonen (im Deutschen> sein als Possessivpronomen (sein Pferd) und als Verb (ich bin...)) Und da ich den voctrainer fuer japanisch brauche ist es noch viel wichtiger, da es dort extrem viele Homophone gibt, die aber eigentlich unabhaengige Woerter sind (mit verschiedenen Kanji geschrieben, aber in Roomaji eben dann gleich, leider...)

    OK, das ist deine Entscheidung. Ich würde ja ausnutzen, daß die voc-Struktur einen vector<> für die möglichen Übersetzungen mitschleppt und dort alle möglichen Homomorphe reinpacken.

    Achja, OT Frage: Ich kenne mich mit Iteratoren noch gar nicht aus und hab mir jetzt mal aus der www.cppreference.com Beschreibung was zusammengebastelt, weil ich fuer vector.insert(loc,term) nen Iterator als erstes Argument brauche. Ist folgendes korrekt:

    vector<int> a(10,20);
    int index=5;
    vector<int>::iterator it=a.begin();
    it+=index;
    a.insert(it,7);
    

    Ja, sieht korrekt aus, könntest du eventuell noch abkürzen:

    a.insert(a.begin()+index,7);
    


  • Ok, vielen Dank! Das heisst einfach global hinstellen und der sollte das dann finden. Hatte auch noch nirgendwo gesehen dass ein vector nen Comporator uebergeben bekommen koennte, aber da ich noch net soviel gesehen habe bisher heisst das eben net viel...

    Das mit den Vokabeln ist halt so, dass ich spaeter die Kanji dazu lernen werde. Und da sich dann die Schreibweise unterscheidet ist es wichtig, dass ich die Bedeutungen getrennt im Kopf hab.

    Im Deutschen wuerde ich auch alles unter eine Vokabel packen, weil es da eigentlich egal ist.,.. Aussprache gleich, Schreibweise gleich, dann kann mans sich auch zusammen merken, kein Problem.

    Oh, glatt was vergessen: kann man auch z.B das vector.insert ueberladen, um z.B die Sortierung des Vektors permanent aufrecht zu halten ohne dafuer gleich die ganze Klasse neu bauen zu muessen?

    Entschuldigt die vielen Fragen.



  • Shinja schrieb:

    Ok, vielen Dank! Das heisst einfach global hinstellen und der sollte das dann finden.

    Ja, genau so funktioniert die Operator-Überladung 😉

    Hatte auch noch nirgendwo gesehen dass ein vector nen Comporator uebergeben bekommen koennte, aber da ich noch net soviel gesehen habe bisher heisst das eben net viel...

    Da ein vector seine Elemente nicht sortieren will, braucht er sie auch nicht vergleichen. Einen zusätzlichen Comparator kannst du bei (multi)set und (multi)map angeben, um deren Sortierungen zu beeinflussen ( set<string> sortiert lexikogafisch, set<string,my_comp> verwendet den Funktor 'my_comp' dafür).

    Oh, glatt was vergessen: kann man auch z.B das vector.insert ueberladen, um z.B die Sortierung des Vektors permanent aufrecht zu halten ohne dafuer gleich die ganze Klasse neu bauen zu muessen?

    Direkt geht das nicht, ohne die STL aufzubohren. aber du kannst dir problemlos die "richtige" Einfügeposition mit lower_bound() oder upper_bound() besorgen:

    vector<string> data;
    string text;
    data.insert(upper_bound(data.begin(),data.end(),text),text);
    


  • tausend dank fuer die Hilfe (und Geduld)

    upper_bound kannte ich noch nicht, das erleichtert das ganze wesentlich.

    Ich meld mich dann beim naechsten Problem, hehe (irgendwie haben Programme das so an sich, dass man noch soviel drueber nachdenken kann und trotzdem immer unerwartete Probleme auftreten... und sobald man das Problem geloest hat funktionniert eine andere Idee in dem netten Konstrukt wieder nicht...



  • Shinja schrieb:

    upper_bound kannte ich noch nicht, das erleichtert das ganze wesentlich.

    Tja, da gibt es einige hilfreiche Algorithmen in der STL 😉 (da ist die Beschreibung in meinen Artikeln vermutlich etwas kurz gekommen, aber eventuell kannst du dich auf C++ Referenz umsehen, was es noch so nützliches gibt)



  • auf cppreference hatte ich mich umgesehen... nur net unter den Basis algorithmen, ich Depp.

    btw hab ich jetzt das Problem:

    struct voc
    {
     std::string word;
     std::vector<std::string> meanings;
     char diff;
    }
    
    bool operator<(const voc& l,const voc& r)
    {return l.word<r.word;}
    

    nicht funktionnieren will, netterweise mit ner Fehlermeldung, die mir sagt, es sei kein Typenspezifizierer fuer l angegeben...

    also, verstehen tu ichs net, ich denk aber noch drueber nach (mein Internet hier in Japan schaltet sich gleich durch ne hoehere Macht namens "Gastfamilie will schlafen gehen" ab)



  • Da fehlt ein kleines Zeichen: ";" (am Ende von Zeile 6)



  • Ishildur ist bestimmt ein 14 jähriges, CS spielendes Kiddy.



  • 15 schrieb:

    Ishildur ist bestimmt ein 14 jähriges, CS spielendes Kiddy.

    Und was bist du? Ein zehnjähriger Möchtegern-Troll mit schweren Orientierungsstörungen? *scnr*



  • hi cstoll.

    das war ein tppfehler meinserseits, das ; hatte ich schon... nur saudumm, dass ich vielleicht const voc& l und nicht const &voc l schreiben sollte, rofl...

    Naja, morgen in der Schule guck ich mal ob ich mir cppreference nicht ausdrucken kann. Sollte das ganze nochmal wesentlich erleichtern.

    Danke soweit.

    Next Step: get used to Visual 2005 Express... da es ne Win Api werden soll. Bisher hab ich dafuer mit Delphi gearbeitet und auch da nur mit 1 Form, hier brauch ich min 3. Naja, sollte ich es wirklich nicht hinkriegen melde ich mich im WinApi forum

    Vielen Dank

    Shinja



  • So, jetzt habe ich ein ganz anderes Problem (fahre aber trotzdem unter dem thread hier weiter, ok? Oder sollte ich ab jetzt fuer "neue" Probleme auch neue Themen eroeffnen?)

    Also, mein Programm besteht aus:
    vocableconsole.cpp (hier befindet sich die main funktion)
    vocstruct.cpp
    vocstruct.h
    finout.cpp
    finout.h

    So, das ganze laesst ich dann auch schoen kompilieren (Visual C++ Express 2005)... aber wenn ich das Programm nun starte wird es mit nem fehler beendet (keine Fehlermeldung, nur das schoene Fenster mit Problembericht senden von Windows)
    Ok, wollte ich mal mit dem Debugger druebergehen und habe gleich an den Eintrittsspunkt von main nen Breakpoint gesetzt.. tja, und da gibt mir der debugger jetzt nen fehler, dass auf eine unerlaubte Adresse geschrieben werden soll, BEVOR dieser Breakpoint erreicht wird.
    Ein cin.get() direkt am Anfang der main Funktion bestaetigt mir, dass dieser Fehler scheinbar VOR dem Eintritt in die main Funktion geschieht...

    Es ist wohl wie immer ne Dummheit, aber ich habe wirklich keine Ahnung (bisher) woran so etwas liegen koennte...



  • In C++ passiert vor Eintritt in die main-Funktion eine ganze Menge. Hast du zufällig irgendwelch globalen/statischen Variablen?



  • hmm, nein, eigentlich nicht.

    in vocstruct.h befindet sich ein struct und die Koepfe 2er Funtkionen
    in vocstruct.cpp befinden sich diese beiden Funktionen
    in finout.h wieder 2 Funktionskoepfe
    und in finout.cpp halt diese 2 Funktionen
    In vocableconsole.cpp befindet sich dann halt die main Funktion.
    alle cpp dateien mit den noetigen inkludierungen (fuer vocstruct.cpp is es vocstruct.h, iostream, vector und string, fuer finout.cpp fstream, vector, string und vocstruct.h und fuer vocableconsole.cpp iostream, vector, string, vocstruct.h und finout.h)

    Ehm, mir faellt geradeauf: kann ein Fehler daraus entstehen, dass ich finout.h nicht in finout.cpp inkludiere? Man liest immer man soll das "sicherheitshalber" tun...



  • Shinja schrieb:

    Ehm, mir faellt geradeauf: kann ein Fehler daraus entstehen, dass ich finout.h nicht in finout.cpp inkludiere? Man liest immer man soll das "sicherheitshalber" tun...

    Ja, es könnte Probleme geben, wenn die Prototypen im Header nicht mit den zugehörigen Funktionen im CPP zusammenpassen.

    Ansonsten: Kannst du mal dein Programm etwas kürzen (entweder bis der Fehler nicht mehr auftritt oder bis es klein genug ist, um es anderen Usern zuzumuten) und hier vorstellen?



  • Das dumme ist ja, dass es noch nicht sonderlich lang ist...

    Das inzige was ich gerade machen wollte, war die ein-ausgabe testen. Ich habe vor die Vokabeln in 2 Dateien zu speichern, eine fuer fremde Sprache-eigene Sprache und die andere halt umgekehrt. Die Vokabeln sind gespeichter als
    Vokabel D Bedeutung1,Bedeutung2,Bedeutung3,
    (D ist ein Char der die Schwierigkeit angeben wird)
    Die Datei soll durchgelaufen werden bis zum Ende, immer Zeile fuer Zeile eingelesen werden, der String wird verarbeitet und in einer voc-Variable gespeichert, diese wird in nen vector von Vocs gehauen.

    Naja, danach werden mit nem ueberladenen Operator<< die vocs in der Konsole ausgegeben und anschliessend wird das in die files schreiben getestet (also alle vocs in die beiden Dateien schreiben), ende des Programmes.

    Wo koennte der Fehler denn liegen, wenn VOR dem Eintritt in die main funktion ein Fehler auftritt? Dann versuche ich die entsprechenden Stellen schoen zu kuerzen und dann hier reinzustellen.
    Ich habe leider keine Ahnung was vor dem Eintritt in main() alles passiert...

    Vielen Dank,

    Shinja

    PS: sehr nette Community hier, mit sehr viel geduld. freut mich!



  • Wo koennte der Fehler denn liegen, wenn VOR dem Eintritt in die main funktion ein Fehler auftritt?

    Naja, alles was statisch initialisiert wird, also wenn du Klassen hast die irgendwo statisch instanziert werden, dann check mal deren Konstruktoren.


Log in to reply