Weltraumvernichtungssimulator



  • ehm weiß nicht ob er deinen operator nimmt aber:

    std::ostream& operator<<(std::ostream&, const std::string&);
    
    int main()
    {
        std::string l("Hans");
        std::string m("Werner");
        std::string n("Uschi");
        std::cout << l << m << n;
    
        return 0;
    }
    
    std::ostream& operator<<(std::ostream& out, const std::string& str)
    {
        out << str << " ";
        return out;
    }
    


  • @(D)Evil: Dein Programm resultiert bei mir (MinGW) in "Process terminated with status -1073741819". Wenn man das ganze mit einer eigenen Klasse macht scheint das irgendwie besser zu gehen. Folgendes funktioniert bei mir:

    #include <iostream>
    #include <string>
    
    class MyString
    {
        friend std::ostream& operator<< (std::ostream& out, const MyString& obj);
    //  ^^^^^^ damit wir Zugriff auf private member haben
        public:
            MyString(const std::string& s) : data(s) {}
        private:
            std::string data;
    };
    
    std::ostream& operator<< (std::ostream& out, const MyString& obj)
    {
        out << obj.data << " ";
    //  ^^^
        return out;
    }
    
    int main()
    {
        MyString a("Hans");
        MyString b("Werner");
        MyString c("Uschi");
        std::cout << a << b << c << std::endl;
    }
    


  • hmm ... ist ja auch logisch 😃 Das verursacht eine Endlosschleife 😉 Im Code wird ja der streamoperator wieder von sich selbst aufgerufen!

    std::ostream& operator<<(std::ostream& out, const std::string& str)
    {
        out << str.c_str() << " ";
        return out;
    }
    

    würde es unter umständen tun 😉



  • Ah also was ich erst ma gelernt habe, is klar man leitet alles in das Objekt "out" rein und gibt dieses dann zurück. Ich hab da ja vorhin was mit cout gemacht....--> unsinn.
    Wie "ohnename" schon gesagt hat, funktionierts bei mir auch nicht. (hab auch MinGW). Hmm...warum geht das ganze dann nur wenn mans in eine Klasse schreibt?
    Mir fällt langsam auf, das ihr alle bei den Parametern (fast) IMMER Referenzen
    nutzt. Ich hab gedacht sowas macht man nur bei Objekten, bzw. wenn man Variablen übergibt und nicht wenn man was mit Hand reinschreibt. Aber okay, auch wenn man anscheinend was mit Handreinschreibt, wird mit diesem dann eine Variable\Objekt.. erzeugt....und somit wieder --> Kopie --> Zeitaufwand.
    Zumindestens nehm ich in Zukunft als Parameter dann halt auch immer Referenzen.

    MfG
    Stromberg



  • (D)Evil schrieb:

    ehm weiß nicht ob er deinen operator nimmt aber:

    std::ostream& operator<<(std::ostream&, const std::string&);
    
    int main()
    {
        std::string l("Hans");
        std::string m("Werner");
        std::string n("Uschi");
        std::cout << l << m << n;
    
        return 0;
    }
    
    std::ostream& operator<<(std::ostream& out, const std::string& str)
    {
        out << str << " ";
        return out;
    }
    

    Ich hab mal versucht das nachzuvollziehen...

    Baust du dir hier nicht eine Endlosrekursion? Du rufst dich ja mit deinem Operator immer wieder selber auf... 😕

    Bei mir funktioniert er so....

    std::ostream& operator<<(std::ostream&, const std::string&);
    
    int main()
    {
        std::string l("Hans");
        std::string m("Werner");
        std::string n("Uschi");
        std::cout << l << m << n;
    
        return 0;
    }
    
    std::ostream& operator<<(std::ostream& out, const std::string& str)
    {
        for(int i = 0; i < str.length(); i++)
            out.put(str[i]);
    
        out.put(' ');
    
        return out;
    }
    

    [Edit:]
    Ups, zu spät...
    Gruß
    zeigerzeiger


  • Mod

    std::ostream& operator<<(std::ostream&, const std::string&);
    

    Das ist ganz schön brutal.



  • Stromberg schrieb:

    Ich wollte eine Textadventure (was anderes kann ich net^^) machen, namens "weltraumvernichtungssimulator". Wie der Name schon sagt geht es darum den Weltraum zu vernichten. 😃

    Nette Idee. Klingt wie eine Space Quest Episode. 😃



  • Wenn es zu einer endloschlefie führt, warum führt das denn dann eigentlich nicht zu einer, ist doch so n ähnliches System: [ausm anfangs Code der von (D)Evil gepostet wurde]

    std::ostream& operator<< (std::ostream& out, const game::part& data) 
    { 
        out << data.question << "\n"; for (std::size_t i = 0; i < 3; ++i) out << data.answer[i] << "\n"; 
        return out; 
    }
    
    std::ostream& operator<<(std::ostream& out, const std::string& str)
    {
        out << str.c_str() << " ";
        return out;
    }
    

    Ah okay, ich glaub das verstehe ich, du hast halt keinen "string" mehr nach dem Operator "<<":

    out << str.c_str() << " ";
    

    sondern machst mit "str.c_str()" einen C-String draus, sodass der überladene Operator "<<" nicht mehr drauf anschlägt. Als was wird den eigentlich " " angesehen, als C-String, also char? Und was wäre wenn das noch "BLABLA" stände, würde das dann auch als char angesehen, oder wärs n string...? Weil wenns n string wäre, dann würde der Operator "<<" ja wieder anschlagen. Hab ich das richtig verstanden?

    Wies "zeigerzeiger" gemacht hat, hab ich glaub auch ungefähr verstanden, und zwar:

    std::ostream& operator<<(std::ostream& out, const std::string& str)
    {
        for(int i = 0; i < str.length(); i++)
            out.put(str[i]);
    
        out.put(' ');
    
        return out;
    }
    

    Du hast eine for Schleife vom Buchstaben anfang bis zum Buchstaben Ende vom string "str" runtergezählt, in dieser stopftst du die einzelnen Buchstaben in "out" mit "put" rein? Woher kommt "put" hab ich noch nie gehört davon.... 😕? Ist "put" sowas wie "<<"? Dann müsst ich glaub auch deine Funktion verstanden haben. Welche von beiden ist den nun schneller?

    @camper
    Warum ist das ganz schön burtal? Stimmts etwa doch nicht? Des hatt mich jetzt bissel verwirrt.

    MfG
    Stromberg



  • Woher kommt "put" hab ich noch nie gehört davon.... 😕? Ist "put" sowas wie "<<"?

    http://www.cplusplus.com/reference/iostream/ostream/put.html ... nein. std::ostream::put(char c) ist eine Funktion, std::ostream::operator<< ist ein Stream-Operator.

    warum führt das denn dann eigentlich nicht zu einer, ist doch so n ähnliches System

    Nope. Du überlädst da ja den operator<< für game::part und nicht für std::string. data.question ist aber ein std::string!

    Als was wird den eigentlich " " angesehen, als C-String, also char?

    er sollte es als const char* interpretieren: { ' ', '\0' } ...

    Und was wäre wenn das noch "BLABLA" stände

    { 'B', 'L', 'A', 'B', 'L', 'A', '\0' } => const char* ...


  • Mod

    Stromberg schrieb:

    @camper
    Warum ist das ganz schön burtal? Stimmts etwa doch nicht? Des hatt mich jetzt bissel verwirrt.

    Ist keine Frage von stimmen. Es verändert die Semantik einer bereits wohldefinierten Operation in nichttrivialer Weise. Das es überhaupt geht, ist nur dem Zufall geschuldet (hier: die normale Überladung für diesen Fall ist eine Templatefunktion).



  • Also bist du eher der Meinung das des schlechter Stil ist oder wie? Aber eigentlich macht des doch nix, weil es hätte doch sowieso nen Compilierfehler gegeben wenn man einfach nach dem "<<" ein game::part objekt hingesetzt hätte oder? Ich versteh jetzt net so ganz.

    MfG
    Stromberg



  • Noch kurz was, wie kann ich mir den das jetzt genau vorstellen, wenn da jetzt steht:

    .....
    game::part objekt;
    cout << objekt;
    .....
    std::ostream& operator<< (std::ostream& out, const game::part& data) 
    { 
        out << data.question << "\n"; for (std::size_t i = 0; i < 3; ++i) out << data.answer[i] << "\n"; 
        return out; 
    }
    

    was passiert dann jetzt genau bei "cout << objekt" und bei "return out", steht da dann zum schluss irgendwie dann des cout und das out?

    cout << out;
    

    Kann ich mir das so im Kopf vorstellen?

    MfG
    Stromberg



  • Du kannst dir

    cout << objekt
    

    als

    operator<<(cout, objekt)
    

    vorstellen, dann sollte es dir eigentlich klar werden.

    Das "return out;" erlaubt dir, Aufrufe des operator<< zu verketten:

    cout << objekt1 << objekt2; // ist das gleiche wie:
    operator<<(operator<<(cout, objekt1), objekt)
    


  • Noch eine Frage, (D)Evil hat am anfang gesagt ich soll die Initialisierungsliste nutzen, aber qrum hat er nur "question" in die Initialisierungsliste genommen?

    part(const std::string& question, const std::string answer_a, 
                const std::string& answer_b, const std::string& answer_c, 
                const std::string& effect_one, const std::string& effect_two, 
                const std::string& effect_three) : question(question)
    { 
                answer[0] = answer_a;    answer[1] = answer_b;    answer[2] = answer_c; 
                effect[0] = effect_one; effect[1] = effect_two; effect[2] = effect_three; 
    
    }
    

    [siehe Seite 2 oben)

    MfG
    Stromberg


  • Mod

    Stromberg schrieb:

    Noch eine Frage, (D)Evil hat am anfang gesagt ich soll die Initialisierungsliste nutzen, aber qrum hat er nur "question" in die Initialisierungsliste genommen?

    Weil du Arrays in Konstruktor-Initialisierungslisten nur default konstruiert werden können. Das ist mal ein Fall, wo du die Initialisierungsliste verzichten musst.



  • Kann mir jemand folgende Zeile aus (D)Evils Code erklären:

    while (!(std::cin >> answer) || answer < 1 || answer > 3) { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); }
    

    Den Anfang verstehe ich noch, das sind die Abfragen ob auch nichts anderes als eine Zahl zwischen 1 u. 3 gedrückt worden ist. Und das while wiederholt den Vorgang dann irgendwie solange bis eine richtige Taste gedrückt wurde. Aber was ist das alles mit dem cin? clear()? ignore()? numeric_limits? <streamsize>::max()?

    MfG
    Stromberg



  • std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
    

    Die Zeile sieht sehr verwirrend aus, ist aber eigentlich einfach 🙂
    Und zwar verwirft der Stream "cin" alle Daten, die im Moment anliegen. Dabei verwirft er Zeichen für Zeichen so lange, bis er auf ein '\n' (also neue Zeile) stößt, oder die angegebene Anzahl an zu verwerfenden Zeichen (in dem Fall std::numeric_limits<std::streamsize>::max() ) erreicht ist.

    std::numeric_limits<std::streamsize>::max() deshalb, weil das die größte "Zahl" ist, die man hier als Argument angeben kann



  • Habs ungefähr verstanden, aber hab mir trotzdem mal ein "cin" Tut angeschaut. In diesem hab ich gelernt, dass es bei "cin" einen unsichtbaren Buffer gibt. Und wenn man z.B. "cin >> answer;" macht dann wird alles gleich aus dem unsichtbaren Buffer in die Variable answer geschrieben. Stimmts soweit?
    Und wenn man nur "cin.get()" macht, dann wirds nur in den Buffer geschrieben. Und jetzt weiß ich nicht so genau wie man sich das Zeug aus dem Buffer anschaut. Ich glaub das geht so:

    #include <iostream>
    using namespace std;
    
    int main()
    {
        cin.get();
        cout << cin.get() << endl;
    
        return 0;
    }
    

    Da stehen jetzt aber nur komische Sachen drin. Bei der Eingabe von 1000 --> 48;
    Eingabe von 1-9 --> 10; Eingabe von 30 u. 40 --> 48; Eingabe von 11 --> 49;...
    bei Bcuhstaben: Bei einzelnen Bcuhstaben immer 10; Bei mehr als zwei Buchstaben --> unterschiedliche Sachen.

    Was genau passiert hier? Und wie kann ich aus dem Buffer nun den Inhalt bekommen?

    MfG
    Stromberg.



  • http://www.cplusplus.com/reference/iostream/istream/get.html

    Lies dir doch einfach mal die Referenz dazu durch.



  • Mh, ich verstehe jetzt den Code, verstehe aber nicht warum man das macht.

    while (!(std::cin >> answer) || answer < 1 || answer > 3) { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); }
    

    Warum löscht man Zeichen für Zeichen den Buffer bis er leer ist? Bei "std::cin >> answer" wird der Speicher doch automatisch in "answer" geleert. Also würde es ja reichen einfach das "cin" zu wiederholen wenn die Anweisung zutrifft "(std::cin >> answer) || answer < 1 || answer > 3)"...? Und bei nem neuen "cin" Aufruf is der Buffer ja wieder leer, weil ja alles in "answer" steht.

    MfG
    Stromberg


Anmelden zum Antworten