Richtige Suchfunktion [gelöst]



  • @Richard_Wunsch sagte in Richtige Suchfunktion:

    Die Kategorien haben fix immer drei Werte - also sind immer so aufgebaut "Kategorie (Wert/Wert/Wert)". Aber ja, ein valueX kann auch mehrfach vorkommen: "Kategorie (value1/value2/value2)".

    Dann such doch nach der öffnenden und schließenden Klammer. Darin splittest du den String an /. Für jeden gesplitteten String schaust du in einer Map nach, wie der Wert ist.

    map<string, int> m = {{"value1", 1}, {"value2", 2}, {"value3", 3}};



  • @wob sagte in Richtige Suchfunktion:

    Dann such doch nach der öffnenden und schließenden Klammer. Darin splittest du den String an /.

    Genau daran habe ich auch schon gedacht. Lass mich kurz mein Hirn zermartern, wie ich das schaffe. Ich versuch bis heute Abend eine entsprechende Lösung zu posten.



  • @Richard_Wunsch sagte in Richtige Suchfunktion:

    Lass mich kurz mein Hirn zermartern, wie ich das schaffe.

    boost::split?
    absl::StrSplit?
    ...

    Oder von Hand jeweils das / suchen?



  • @wob Ist als blutiger Anfänger nicht so einfach, wie man sich das vielleicht vorstellen mag.

    Dachte nach kurzer Recherche eher an std::substr mit dem "(" als pos. Sieht auf den ersten Blick nachvollziehbarer aus als deine Verweise.

    Von Hand das "/" suchen, splittet mir aber noch nicht den String, oder wie meintest du das?

    Edit:

     #include <iostream>
     #include <string>
                    
    int main (){
        std::string category = "category (value1/value2/value3)";
        std::string firstValue = category.substr((category.find("("))+1, 6); 
        std::string secondValue = category.substr((category.find("/"))+1, 6);
        std::string thirdValue = category.substr((category.find(")"))-6, 6);
        return 0;
    }     
    

    Zu unsauber?



  • Geschafft! Sieht so aus, als ob ich einen funktionierenden Code zusammengebastelt hätte:

    #include <iostream>
     #include <string>
     #include <map>
                    
    int main (){
        
        std::map<std::string, int> m = {{"value1", 1}, {"value2", 2}, {"value3", 3}};
        std::string category [4] = {"category (value1/value2/value3)", "category2 (value2/value1/value3)", "category3 (value3/value2/value1)", "category4 (value1/value2/value3)"};
        std::string firstValueName[4] = {};
        std::string secondValueName[4]= {};
        std::string thirdValueName[4] = {};
        int answer;
        
        for (int i=0; i<4; i++){
            firstValueName[i] = category[i].substr((category[i].find("("))+1, 6); 
            secondValueName[i] = category[i].substr((category[i].find("/"))+1, 6);
            thirdValueName[i] = category[i].substr((category[i].find(")"))-6, 6);
        }
                        
        for (int i=0; i<4; i++){
            std::cout << i << ": " << category [i] <<std::endl <<std::endl;
        }
        std::cout <<"Eingabe: ";
        std::cin >> answer;
        std::cout << std::endl;
        
        for (int i=0; i<4;i++){
            if (answer == i){
                std::cout << category [i] << " = ("
                          << m.find(firstValueName[i])->second << "/"
                          << m.find(secondValueName[i])->second << "/"
                          << m.find(thirdValueName[i])->second << ")";
            }
        }
        return 0;
    }      
    

    Ich implementiere ihn später mal in die eigentliche Anwendung und gucke mal, wie er sich so schlägt. Danke noch einmal an alle Beitragende! Ohne euch hätte ich es sicher nicht geschafft 🙂

    Ansonsten...immer her mit eurer Kritik!



    • Kodiere die Array-Längen nicht fest in deinem Code!
    • Kodiere die 6 nicht fest, sondern errechne sie
    • firstValueName / secondValueName / thirdValueName würde ich nicht als Array vorberechnen
    • m.find(firstValueName[i])->second ist eine komplizierte Schreibweise von m.at(firstValueName[i]) (also nicht 100% identisch, verhält sich anders bei nicht gefundenen Schlüsseln) -> du solltest wohl doch m.find benutzen, aber das Ergebnis erstmal mit m.end() vergleichen, bevor du auf ->second zugreifst. Mit m.at kommt wenigstens dann wenigstens ein definierter Fehler, wäre einem find ohne check also vorzuziehen.
    • Benutze kurze Funktionen - nicht alles in einem langen main()


  • @wob Danke für deine Hilfe ❤



  • @wob ich muss doch noch mal nachhaken: Inwiefern die Array-Längen nicht fest kodieren? Im genannten Beispiel werden die Daten doch konstant initalisiert - wie sollte ich da die Array-Länge ersetzen?

    Und mit deinem 3. Punkt wolltest du darauf hinaus, richtig?

        for (int i=0; i<4;i++){
            if (answer == i){
                std::cout << category [i] << " = ("
                          << m.find(category[i].substr((category[i].find("("))+1, 6))->second << "/"
                          << m.find(category[i].substr((category[i].find("/"))+1, 6))->second << "/"
                          << m.find(category[i].substr((category[i].find(")"))-6, 6))->second << ")";
            }
        }
    


  • @Richard_Wunsch sagte in Richtige Suchfunktion [gelöst]:

    Inwiefern die Array-Längen nicht fest kodieren?

    Du hast x-Mal in deinem Programm "4" stehen. Was ist, wenn du auf einmal 3 oder 5 Elemente haben möchtest? Welche Vieren im Programm musst du ändern? Daher: nimm Konstanten oder bestimme die Länge mit .size() bei vector. Wenn du C++17 nutzen kannst, geht auch std::size - sowohl für Arrays als auch für Vectoren.

    Lies bitte https://de.wikipedia.org/wiki/Magische_Zahl_(Informatik)#Magische_Zahlen_in_Code



  • @wob Ah ja verstehe, ich dachte du beziehst dich mit Array Länge auf die "4" in std::string category [4]. Vielen Dank für deine Antwort und den sehr nützlichen Hinweis auf die Magischen Zahlen!