Längstes Word in einem Array



  • Ich finde es immer schade, wenn sich jemand die Mühe gibt ausführliches Feedback zu geben, und der Großteil davon, wenn nicht alles wird einfach ignoriert. Wenn Du eigentlich garnicht C++ lernen möchtest, dann ist das hier das falsche Unterforum. Nicht einmal den strlen Fehler hast du behoben; Dir ist bewusst, dass strlen O(n) läuft, d.h. jedes Mal über jeden char im string iteriert, oder?

    Vgl.:

    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    
    int main()
    {
        std::vector<std::string> words;
        for (std::string word; std::cin >> word; )
            words.push_back(word);
    
        if (words.empty())
            std::cout << "No Input\n";
        else {
            // könnte man in eine eigene Funktion packen
            auto&& longest = *std::max_element(cbegin(words), cend(words), [](auto&& Lhs, auto&& Rhs) { return Lhs.size() < Rhs.size(); });
            std::cout << "The longest word is: " << longest << '\n';
            // falsch: std::cout << "The longest word is: " << *std::max_element(cbegin(words), cend(words)) << '\n';
        }
    }
    

    P.S.: Mir ist klar, dass man das an der Uni leider nicht lernt, ist bei uns ja auch so. Aber das bedeutet nicht, dass man deshalb nicht wissen darf, wie es besser geht.

    LG



  • HarteWare schrieb:

    *std::max_element(cbegin(words), cend(words))
    

    Das tut nicht, was du denkst. Dazu müsstest du noch ein , [](auto&& Lhs, auto&& Rhs){ return Lhs.size() < Rhs.size(); } anfügen.

    LG



  • Fytch schrieb:

    HarteWare schrieb:

    *std::max_element(cbegin(words), cend(words))
    

    Das tut nicht, was du denkst. Dazu müsstest du noch ein , [](auto&& Lhs, auto&& Rhs){ return Lhs.size() < Rhs.size(); } anfügen.

    LG

    Oh da hast Du aber recht, mein Fehler! Werde es korrigieren, danke. P.S.: Ich muss grad fragen, wieso

    (auto&& Lhs, auto&& Rhs)
    

    sind dass dann rvalue-Referenzen oder Universal-Referenzen?



  • HarteWare schrieb:

    P.S.: Ich muss grad fragen, wieso

    (auto&& Lhs, auto&& Rhs)
    

    sind dass dann rvalue-Referenzen oder Universal-Referenzen?

    Universal-Refs, binden also alle value types und bewahren CV-Qualifier. auto als Lambda-Parameter entspricht template< typename T > void Closure::operator()( T ) , und analog auto&& dem T&& . Anders würde das nicht kompilieren, denn die lvalue-Referenz, die std::vector::const_iterator::operator* zurückgibt, kannst du nicht implizit an eine rvalue-Referenz binden.

    PS: dein auto longest erzeugt eine Kopie des Strings, auch hier wäre ein auto const& oder auto&& angebracht. 😉

    LG



  • OK, danke für die ausführliche Erklärung. Mir war nicht bewusst, dass sich auto&& so verhält 👍



  • @alexxd_12
    Würdest du in deiner for-Schleife die Abbruchbedingung auf < ändern, würde nie das '\0' in der Schleife behandelt werden.
    Somit sind deine Ausnahmen überflüssig.

    for (int i = 0; i < strlen(str); i++) {
    

    Aber um gleich mal die richtige Bedingung zu zeigen:

    for (int i = 0; str[i] != '\0'; i++) { // einfach nur ;str[i]; reicht auch
    

    Was anderes macht strlen auch nicht.

    Und es gilt immer noch, das von SeppJ geschriebene!


  • Mod

    HarteWare schrieb:

    Ich finde es immer schade, wenn sich jemand die Mühe gibt ausführliches Feedback zu geben, und der Großteil davon, wenn nicht alles wird einfach ignoriert.

    Ich auch. Daher gibt es, statt konkreter Hilfe für den Threadersteller, nur eine weitere Stufe der von dir begonnenen Transformation zu einem C++-Einzeiler:

    auto&& longest = 
        *std::max_element(std::istream_iterator<std::string>(std::cin), 
                          std::istream_iterator<std::string>(), 
                          [](auto&& Lhs, auto&& Rhs) { return Lhs.size() < Rhs.size(); });
    

    Keine unnötigen Zwischenvektoren mehr.



  • SeppJ schrieb:

    auto&& longest = 
        *std::max_element(std::istream_iterator<std::string>(std::cin), 
                          std::istream_iterator<std::string>(), 
                          [](auto&& Lhs, auto&& Rhs) { return Lhs.size() < Rhs.size(); });
    

    Das funktioniert so leider nicht, da std::istream_iterator ein Input Iterator ist, std::max_element aber mindestens Forward Iteratoren benötigt, da er einen Iterator in der Mitte der Range zurückgeben kann. Selbst wenn der Code kompiliert, so erzeugt er UB, sofern die Eingabe nicht leer ist, da std::max_element jeweils zwei verschiedene Elemente aus der Range zu vergleichen versucht, was für Input Iteratoren nicht erlaubt ist.
    Ein besserer Einzeiler wäre:

    auto Longest = std::accumulate(std::istream_iterator<std::string>(std::cin),
                                   std::istream_iterator<std::string>(), 
                                   std::string{},
                                   [](auto&& Lhs, auto&& Rhs){ return Lhs.size() > Rhs.size() ? Lhs : Rhs; });
    


  • unnötige[] Zwischenvektoren [...]

    Aber wenn man dann eines Tages noch die Anzahl der Wörter wissen möchte, und vielleicht auch noch das kürzeste Wort, dann sieht es schon wieder anders aus 🙂


  • Mod

    HarteWare schrieb:

    unnötige[] Zwischenvektoren [...]

    Aber wenn man dann eines Tages noch die Anzahl der Wörter wissen möchte, und vielleicht auch noch das kürzeste Wort, dann sieht es schon wieder anders aus 🙂

    Da braucht man eine andere Mitzählfunktion, aber man braucht für keines davon braucht man eine vollständige Liste aller Werte zu speichern.



  • SeppJ schrieb:

    Da braucht man eine andere Mitzählfunktion, aber man braucht für keines davon braucht man eine vollständige Liste aller Werte zu speichern.

    Ok, stimmt auch wieder, so weit habe ich garnicht gedacht.



  • HarteWare schrieb:

    P.S.: Mir ist klar, dass man das an der Uni leider nicht lernt, ist bei uns ja auch so. Aber das bedeutet nicht, dass man deshalb nicht wissen darf, wie es besser geht.

    Da muss ich OP aber ein wenig in Schutz nehmen. Ich hab C++ von einem C Programmierer gelernt und hab ähnlichen Code geschrieben, bevor ich hier ins Forum gefunden habe :D. Man weiß es halt nicht besser und wenn man einen Lehrer hat der sagt, dass das so geht, dann vertraut man da auch ein wenig drauf. Ich schiebe hier den schwarzen Peter deutlich den Fakultäten zu.


Anmelden zum Antworten