Frage zu struct



  • Ich hab mich mal für die diese Lösung entschieden da ich dort noch ein paar Implementierungsprobleme habe.

    std::vector<DATEN> datenVec;
    
    DATEN neueDaten;
    neueDaten.vorname = "hans";
    neueDaten.nachname = "wurst"
    neueDaten.ort = "wursthausen";
    
    datenVec.push_back(neueDaten);
    

    Mein Problem ist jetzt die Ausgabe anscheind muss ich dort ja mit Operator Überladung arbeiten.

    Weil wenn ich schreibe:

    cout<<datenVec[0];
    

    Dann sagt mein Compiler: [C++ Fehler] t.cpp(76): E2094 'operator<<' ist im Typ 'ostream' für Argumente des Typs 'DATEN' nicht implementiert

    Daher hab ich folgendes gemacht:

    ostream &operator << ( ostream &os, DATEN &daten )
    {
    
            return os << daten.vorname << " "<<daten.nachname << " "<<daten.ort;
    }
    

    Nur das nützt mir ja jetzt auch nichts, wie kann ich mir jetzt die einzelnen Elemente ausgeben lassen?

    Für Element zugriff gibt es ja operator[] aber ich hab kp wie ich das hier verwenden soll in diesem Fall.



  • s_tr schrieb:

    Nur das nützt mir ja jetzt auch nichts, wie kann ich mir jetzt die einzelnen Elemente ausgeben lassen?

    meinst du, der Code funktioniert nicht? Oder willst du dir von deinen Daten jeweils nur den Vornamen ausgeben lassen?



  • Funktionieren tut der Code schon ich bekomme alles ausgeben (vorname,nachname und den ort)

    Nur ich dachte ich könnte sowas machen:

    cout<<datenVec[0];  // Gibt vorname aus
    cout<<datenVec[1];  // Gibt nachname aus
    cout<<datenVec[2];  // Gibt ort aus
    


  • cout<<datenVec[0].vorname ;  // Gibt vorname aus
    cout<<datenVec[0].nachname ;  // Gibt nachname aus
    cout<<datenVec[0].ort;  // Gibt ort aus
    


  • s_tr schrieb:

    Nur ich dachte ich könnte sowas machen:

    cout<<datenVec[0];  // Gibt vorname aus
    cout<<datenVec[1];  // Gibt nachname aus
    cout<<datenVec[2];  // Gibt ort aus
    

    du hast da etwas völlig missverstanden. datenVec ist ein std::vector, der mehrer Instanzen von deinem DATEN-struct enthält. mit datenVec[0] greifst du auf das erste Element zu. Was du willst, ist dann wohl

    cout<<datenVec[0].vorname;  // Gibt vorname aus
    cout<<datenVec[0].nachname;  // Gibt nachname aus
    cout<<datenVec[0].ort;  // Gibt ort aus
    

    edit: Mist, hab zu lange fürs Tippen gebraucht 😉



  • Du könntest auch einfach ostream& operator<<(ostream&, const DATEN&) definieren, dann ginge auch

    cout << datenVec[0]; // rufe die Funktion auf und gib darin Vor-, Nachname und Ort aus
    


  • ostreamer schrieb:

    Du könntest auch einfach ostream& operator<<(ostream&, const DATEN&) definieren, dann ginge auch

    lesen, verstehen, posten

    genau das hat er bereits gemacht. Jetzt möchte er die einzelnen Elemente des structs getrennt ausgeben



  • #include <string>
    #include <vector>
    
    struct Daten
    {
        std::string vorname;
        std::string nachname;
        std::string ort;
    };
    
    int main()
    {
        std::vector<Daten> VecDaten;
        Daten d = {"Pipi", "Langstrumpf", "Tackatuckaland"};
        VecDaten.push_back(d);
    }
    

    Und wenn 'nen halbwegs aktuellen und vernünftigen Compiler hast, kannste auch

    #include <string>
    #include <utility>
    #include <vector>
    
    struct Daten
    {
        std::string vorname;
        std::string nachname;
        std::string ort;
    };
    
    int main()
    {
        std::vector<Daten> VecDaten;
        Daten d = {"Pipi", "Langstrumpf", "Tackatuckaland"};
        VecDaten.push_back(std::move(d));
    }
    

    schreiben. Das std::move kannst du verwenden, um zu sagen "Der Wert dieser Variable interessiert mich nicht mehr", was u.U. die eine oder andere Operation beschleunigt. In diesem Fall müssten die Strings nicht in den Vektor kopiert werden. Sie müssten nur "umziehen". Nach so einer Aktion solltest du nicht erwarten, dass d unverändert bleibt. Allerdings ist der Microsoft-Compiler noch nicht soweit, dass er es in diesem Fall wirklich gebacken bekommt.

    Edit: Oops... Es hat sich wohl schon erledigt, mit dem Füllen des Vektors...



  • krümelkacker schrieb:

    Und wenn 'nen halbwegs aktuellen und vernünftigen Compiler hast, kannste auch

    #include <string>
    #include <utility>
    #include <vector>
    
    struct Daten
    {
        std::string vorname;
        std::string nachname;
        std::string ort;
    };
    
    int main()
    {
        std::vector<Daten> VecDaten;
        Daten d = {"Pipi", "Langstrumpf", "Tackatuckaland"};
        VecDaten.push_back(std::move(d));
    }
    

    Wenn man einen halbwegs aktuellen und vernünftigen Compiler hat, schafft man die main() in einer sauberen Zeile:

    int main()
    {
        std::vector<Daten> VecDaten{{"Pipi", "Langstrumpf", "Tackatuckaland"}};
    }
    

    🤡

    Edit: Ich seh schon, macht nicht dasselbe wie deins, hier muss schließlich kopiert werden... initializer_list kann keine RValue-Referenzen aufnehmen.



  • DER HAMMER 🙂

    Sone schrieb:

    krümelkacker schrieb:

    Und wenn 'nen halbwegs aktuellen und vernünftigen Compiler hast, kannste auch

    #include <string>
    #include <utility>
    #include <vector>
    
    struct Daten
    {
        std::string vorname;
        std::string nachname;
        std::string ort;
    };
    
    int main()
    {
        std::vector<Daten> VecDaten;
        Daten d = {"Pipi", "Langstrumpf", "Tackatuckaland"};
        VecDaten.push_back(std::move(d));
    }
    

    Wenn man einen halbwegs aktuellen und vernünftigen Compiler hat, schafft man die main() in einer sauberen Zeile:

    int main()
    {
        std::vector<Daten> VecDaten{{"Pipi", "Langstrumpf", "Tackatuckaland"}};
    }
    

    🤡

    Edit: Ich seh schon, macht nicht dasselbe wie deins, hier muss schließlich kopiert werden... initializer_list kann keine RValue-Referenzen aufnehmen.



  • Allerdings geht dasselbe trotzdem kürzer, weil vector laut Standard eine push_back-Überladung mit RValue-Referenz anbieten muss (siehe N3337, 23.3.6.5, Deklarationen):

    std::vector<Daten> VecDaten;
        VecDaten.push_back({"Heiko", "Blonder", "Sachsen"});
    


  • Ja, das dass geht weiss ich aber ich dachte halt es könnte auch anders gehen. 🤡

    cout<<datenVec[0].vorname;  // Gibt vorname aus 
    cout<<datenVec[0].nachname;  // Gibt nachname aus 
    cout<<datenVec[0].ort;  // Gibt ort aus
    

    Das mit dem std::move teste ich nachher mal ich hab hier gerade nur so einen veralteten Compiler. Wird Zeit mal was neueres.^^

    Btw. kann die aktuelle MS Visual Studio Express Version schon C++11?



  • s_str schrieb:

    Btw. kann die aktuelle MS Visual Studio Express Version schon C++11?

    Jup, ich denke schon. Zwar nicht sehr gut (afair noch nichtmal variadic templates), aber für Details musste warten bis jemand der damit arbeitet mehr rausrückt.



  • Noch eine Frage:

    Kann man das so erklären das der Compiler hier selber einen Konstruktor in die Struktur baut?

    Daten d = {"Pipi", "Langstrumpf", "Tackatuckaland"};

    #include <utility> 
     #include <vector> 
    
    struct Daten 
     { 
         std::string vorname; 
         std::string nachname; 
         std::string ort; 
     }; 
    
    int main() 
     { 
         std::vector<Daten> VecDaten; 
         Daten d = {"Pipi", "Langstrumpf", "Tackatuckaland"}; 
         VecDaten.push_back(std::move(d)); 
     }
    


  • s_tr schrieb:

    Kann man das so erklären das der Compiler hier selber einen Konstruktor in die Struktur baut?

    Ja, genau so kann man das erklären. Wenn man ganz akribisch ist, wird man noch hinzufügen, dass das nur geschieht wenn kein anderer, user-definierter Ctor existiert.

    Aber bei solchen PODs wie Daten gelten einige Member als implizit definiert:

    Daten(Daten const&)
    Daten(Daten&& )
    Daten()
    ~Daten()
    Daten& operator=(Daten const&)
    Daten& operator=(Daten&&)
    


  • Deine Art von Initialisierung ist allerdings in 12.6.1, Klausel 2/3 definiert. Es ist eine spezielle Art von Initialisierung: Man initialisiert hierbei ein Objekt nicht durch den Konstruktor, sondern durch eine braced-init-list, die dann entweder die einzelnen Member nacheinander initialisiert, oder einen entsprechenden Ctor aufruft. Das nennt sich Listen-Initialisierung (engl. "list-initialization"), und funktioniert nur bei Klassen die entweder keinen Konstruktor definieren, oder die einen definieren, bei dem die Elemente der init-list ohne narrowing-conversion in die Konstruktor-Parameter konvertiert werden können.



  • Sone schrieb:

    Deine Art von Initialisierung ist allerdings in 12.6.1, Klausel 2/3 definiert. Es ist eine spezielle Art von Initialisierung: Man initialisiert hierbei ein Objekt nicht durch den Konstruktor, sondern durch eine braced-init-list, die dann entweder die einzelnen Member nacheinander initialisiert, oder einen entsprechenden Ctor aufruft. Das nennt sich Listen-Initialisierung (engl. "list-initialization"), und funktioniert nur bei Klassen die entweder keinen Konstruktor definieren, oder die einen definieren, bei dem die Elemente der init-list ohne narrowing-conversion in die Konstruktor-Parameter konvertiert werden können.

    Das hier ist aber keine list-initialization sondern eine aggregate-initialization, oder? Seit C++1 ist das irgendwie verwirrend.


  • Mod

    out schrieb:

    Sone schrieb:

    Deine Art von Initialisierung ist allerdings in 12.6.1, Klausel 2/3 definiert. Es ist eine spezielle Art von Initialisierung: Man initialisiert hierbei ein Objekt nicht durch den Konstruktor, sondern durch eine braced-init-list, die dann entweder die einzelnen Member nacheinander initialisiert, oder einen entsprechenden Ctor aufruft. Das nennt sich Listen-Initialisierung (engl. "list-initialization"), und funktioniert nur bei Klassen die entweder keinen Konstruktor definieren, oder die einen definieren, bei dem die Elemente der init-list ohne narrowing-conversion in die Konstruktor-Parameter konvertiert werden können.

    Das hier ist aber keine list-initialization sondern eine aggregate-initialization, oder? Seit C++1 ist das irgendwie verwirrend.

    Aggregat-Initialisierung durch Initialisierungsliste ist (eine spezielle Form der) List-Initialisierung. Leider reflektiert die Gliederung des neuen Standards das nicht.



  • camper schrieb:

    out schrieb:

    Sone schrieb:

    Deine Art von Initialisierung ist allerdings in 12.6.1, Klausel 2/3 definiert. Es ist eine spezielle Art von Initialisierung: Man initialisiert hierbei ein Objekt nicht durch den Konstruktor, sondern durch eine braced-init-list, die dann entweder die einzelnen Member nacheinander initialisiert, oder einen entsprechenden Ctor aufruft. Das nennt sich Listen-Initialisierung (engl. "list-initialization"), und funktioniert nur bei Klassen die entweder keinen Konstruktor definieren, oder die einen definieren, bei dem die Elemente der init-list ohne narrowing-conversion in die Konstruktor-Parameter konvertiert werden können.

    Das hier ist aber keine list-initialization sondern eine aggregate-initialization, oder? Seit C++1 ist das irgendwie verwirrend.

    Aggregat-Initialisierung durch Initialisierungsliste ist (eine spezielle Form der) List-Initialisierung. Leider reflektiert die Gliederung des neuen Standards das nicht.

    Schade. Ich habe mich an eben dem orientiert.


Anmelden zum Antworten