Bitte um Hilfe bei der Ausgabe von struct



  • Hallo,
    wenn ich mir einen Namen mittels struct anlege und anschließend einen weiteren struct mit dem vorher definierten Namen und zusätlich dem Alter usw...
    Wie kann ich das ausgeben lassen?
    cout mag mein compiler nicht und mit einer print Funktion komm ich auch nicht weiter..
    Hier mal mein Code:

    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <string>
    
    using std::cin;
    using std::cout;
    using std::vector;
    using std::string;
    
    struct name_type {
    	string first_name;
    	string last_name;
    };
    
    struct person_type {
    	name_type	name;
    	int		age;
    };
    
    struct human_type {
            person_type person;
            string email;
    };
    
    void print(string & x) {
    	for (int i(0); i < x.size(); ++i) {
    		cout << x[i];
    	}
    }
    
    void print2 (person_type const & x) {
    
    	for (int i(0); i < x.size(); ++i) {
    		cout << x[i];
    	}
    
    }
    
    void main() {
    
    	name_type namen;
    	namen.first_name = "Biene";
    	namen.last_name = "Maja";
    
    	person_type person;
    	person.name = namen;
    	person.age = 9;
    
    	print2(person);
    
    }
    

    Also es soll ein struct name_type geben in der zwei strings mit Vor-, und Nachname sind.
    Anschließend ein struct person_type welches das vorige name_type enthaltet und das Alter.
    Danach evtl wieder ein struct welcher evtl name_type und person_type enthält und zusätlich noch die E-Mail Adresse oder was auch immer.
    Es geht nur darum wie ich das auf der Konsole ausgeben kann bzw wie ich es ausgeben kann, dass ein struct im anderen liegt damit ich es nicht immer neu schreiben muss....
    cout klappt nicht und mit einer normalen print Funktion schaff ich es nicht.
    Bitte um Hilfe 😕

    Lg



  • Wenn ich diesen Code nehme:

    for (int i(0); i < x.size(); ++i) {
    		cout << x[i];
    	}
    

    sagt der compiler:
    class "person_type" has no member "size"

    und mit:

    void print2 (vector<person_type> const & x) {
    	for (int i(0); i < x.size(); ++i) {
    		cout << x[i];
    	}
    
    }
    

    steht da:
    'void print(std::string &)': cannot convert argument 1 from 'const name_type' to 'std::string &'



  • Naja du musst dir schon die einzelnen Member deines structs raussuchen und die ausgeben:

    void print2(person_type const & x) {
      cout << x.name.first_name << endl;
      cout << x.name.last_name << endl;
      // usw...
    }
    

    Man kann auch den operator<< so überladen, dass direkt ein name_type oder sowas per cout ausgeben kannst. Wenn du das möchtest dann frag nochmal.

    Warum hast du überall die Schleifen? Bei Funktionen wie

    void print(string & x) {
      for (int i(0); i < x.size(); ++i) {
        cout << x[i];
      }
    }
    

    frage ich mich ob dir bekannt ist, dass du std::string direkt per cout ausgeben kannst. Du brauchst nicht jedes Zeichen einzelnd auszugeben.



  • Vielen Dank für die schnelle Antwort.

    Ja mit cout << x.first_name...usw...
    klappt es, da first_name und last_name vom Typ String sind.

    Aber wie funktioniert das bei person_type?
    darin ist ja name_type und ein int (Alter) enthalten.
    Also wie kann ich person_type ausgeben lassen, so dass darin bereits name_type enthalten ist ohne nochmal alles neu eingeben zu müssen?

    Lg



  • Dann solltest du operator<< überladen für deine structs. Das sieht dann so aus:

    std::ostream& operator<<(std::ostream& s, name_type const& name)
    {
      s << name.first_name << endl;
      s << name.last_name << endl;
      return s;
    }
    

    Jetzt kannst du ein name_type genau wie std::string direkt per cout ausgeben. Das gleiche musst du dann auch für deine anderen structs machen. In der Version für person_type kannst du ja dann darauf aufbauen, dass du für name_type schon einen operator<< hast.



  • Wie wärs mit einer ausgabefunktion für alle drei typen, wobei die eine funktion neben dem tätigen der ausgaben auch die entsprechenden funktionen der inneren member aufruft.
    Premium wärs natürlich mit Ableiten, aber soweit bist du sicher noch nicht.



  • sebi707 schrieb:

    Dann solltest du operator<< überladen für deine structs. Das sieht dann so aus:

    std::ostream& operator<<(std::ostream& s, name_type const& name)
    {
      s << name.first_name << endl;
      s << name.last_name << endl;
      return s;
    }
    

    Jetzt kannst du ein name_type genau wie std::string direkt per cout ausgeben. Das gleiche musst du dann auch für deine anderen structs machen. In der Version für person_type kannst du ja dann darauf aufbauen, dass du für name_type schon einen operator<< hast.

    Wenn ich es nun so schreibe:

    struct name_type {
    	string first_name;
    	string last_name;
    };
    
    struct person_type {
    	name_type	name;
    	int			age;
    };
    
    std::ostream& operator<<(std::ostream& s, name_type const& name){
    	s << name.first_name << " ";
    	s << name.last_name << " ";
    	return s;
    }
    
    std::ostream& operator<<(std::ostream& s, person_type const& person) {
    	s << person.name << " ";
    	s << person.age << "\n";
    	return s;
    }
    
    void main() {
    
    	name_type namen;
    	namen.first_name = "Biene";
    	namen.last_name = "Maja";
    
    	person_type person;
    	person.name = namen;
    	person.age = 9;
    
    	cout << namen;
    	cout << "\n\n";
    
    	cout << person;
    	cout << "\n\n";
    
    }
    

    klappt alles einwandfrei 😮
    Vielen vielen Dank...hab damit bestimmt 20 Stunden verbracht und es nicht geschafft. DANKE 🙂 🙂
    Endlich funktionierts 🙂 aber ist es nun in Ordnung so wie ich es hab oder hab ich es jetzt etwas umständlich gemacht?

    Lg


  • Mod

    Goku++ schrieb:

    Endlich funktionierts 🙂 aber ist es nun in Ordnung so wie ich es hab oder hab ich es jetzt etwas umständlich gemacht?

    Ist ganz ok so. Bloß das Design deiner Personenklasse erinnert mich an dies hier 😃



  • SeppJ schrieb:

    Goku++ schrieb:

    Endlich funktionierts 🙂 aber ist es nun in Ordnung so wie ich es hab oder hab ich es jetzt etwas umständlich gemacht?

    Ist ganz ok so. Bloß das Design deiner Personenklasse erinnert mich an dies hier 😃

    Okay 😃 aber ist ja nur zum Üben 😉
    Wollte nur wissen ob ich

    std::ostream& operator<<(std::ostream& s, person_type const& person) {
        s << person.name << " ";
        s << person.age << "\n";
        return s;
    }
    

    immer in exakt dieser Form schreiben muss oder ob es nun auch anders geht weil der Operator << ja bereits überladen ist?

    Habs noch weiter ausgebaut und funktioniert alles prima.
    Vielen Dank nochmal 👍 🙂

    Lg



  • Hätte noch eine kleine Off-Topic Frage:
    Wenn ich das Ganze nun am Computer speichern möchte mache ich das ja mit:

    std::ofstream o("data.txt");
    	o << human;
    	o.close();
    

    aber dann speichert es nur eine Person in "data.txt".
    Wenn ich das nochmal mache mit anderen Daten, dann überschreibt es meine erste Person.
    Kann ich nun alles so abspeichern, dass z.B. die erste Person unter 01.txt speichert, die zweite unter 02.txt usw?
    Und kann ich auch den Speicherort ändern (also, dass es nicht immer alles im VS Ordner speichert sondern z.B. auf dem Desktop oder noch besser in einem Ordner der sich am Desktop befindet)?

    Lg



  • Natürlich geht das. Dann musst du aber dafür sorgen, dass sich der Dateiname ändert und nicht immer 'data.txt' heißt. Wenn du die Datei in einem anderen Ordner speichern möchtest kannst du auch einen Pfad angeben. Also etwa 'C:/Users/Sebi/Desktop/whatever/01.txt' oder so. Wobei das natürlich nicht sonderlich flexibel ist wenn man den Pfad so in seinen Quelltext schreibt. Zum testen oder wenn das Programm eh nur von dir verwendet wird kannst du das aber so machen.



  • Super, vielen Dank.
    Aber wie kann ich den Namen flexibel machen, wenn ich ihn ich ein doppeltes Hochkomma schreiben muss?
    Bzw wenn ich den ganzen Pfad angebe, dass sich nur das 01.txt am Ende ändert?
    Danke

    Lg



  • Leider funktioniert das bei vectoren nicht..
    Bsp.:

    struct name_type {
    	string first_name;
    	string last_name;
    };
    
    struct person_type {
    	name_type	name;
    	vector<int>	age;
    };
    

    Wie würde ich das nun auf der Konsole ausgeben lassen?
    Bzw auf der Konsole und in ein file?

    (Klar ist es nicht sinnvoll das Alter in einen vector zu legen, dient aber lediglich für Übungszwecke).

    Lg



  • Du überlädst den freien << operator, wie dus schon davor gemacht hast.



  • roflo schrieb:

    Du überlädst den freien << operator, wie dus schon davor gemacht hast.

    Dann kommt der Fehler:

    Error C2679 binary '<<': no operator found which takes a right - hand operand of type 'const std::vector<int,std::allocator<_Ty>>' (or there is no acceptable conversion)
    Error(active) no operator "<<" matches these operands

    oder stimmt das dann so nicht:

    std::ostream& operator<<(std::ostream& s, person_type const& person) {
    	s << person.name << "\n";
    	s << "age: " << person.age << "\n";
    	return s;
    }
    

    Und das nächste problem ist ja, dass ich einen vector nicht so leicht mit einem cin einlesen kann, oder?



  • Da age jetzt ein vector ist müsstest du schon eine Schleife haben die dann alle Werte in dem vector ausgibt. Man kann auch einen operator<< erstellen mit dem man beliebige vector ausgeben lassen kann aber dafür braucht man Templates und das ist schon etwas fortgeschrittenes Thema.



  • sebi707 schrieb:

    Da age jetzt ein vector ist müsstest du schon eine Schleife haben die dann alle Werte in dem vector ausgibt. Man kann auch einen operator<< erstellen mit dem man beliebige vector ausgeben lassen kann aber dafür braucht man Templates und das ist schon etwas fortgeschrittenes Thema.

    Aber wenn ich age in einen vector lege und ihn in einer Schleife ausgeben lasse, habe ich immer noch das Problem, dass bei vectoren eine Benutzereingabe über die Konsole etwas schwierig wird??



  • Die Benutzereingabe ist immer etwas schwieriger wenn man beliebig viele Elemente einließt. Da gibts verschiedene Möglichkeiten. Entweder man fragt vorher ab wie viele Elemente eingegeben werden sollen oder man ließt so lange Elemente ein bis ein "leeres" oder irgendwie spezielles Element eingelesen wird.



  • also mit push_back?

    oder wär es gleich besser die Eingabe mit ofstream einfach raus speichern und nachher den vector mit ifstream zu füllen?


Log in to reply