getline-Problem



  • Hallo,

    ich wollte eigentlich nur eine Funktion erstellen, die auch Leerzeichen in einem String auswertet. Eigentlich wird nur die Funktion getline aufgerufen.
    Ich will aber nicht immer

    getline (cin,VARIABLE);
    

    eingeben, sondern

    in VARIABLE;
    

    , was das gleiche Ergebnis erzielt.

    Das komplette Programm mit der Funktion (namens "in") sieht so aus:

    /* Header-Dateien inkludieren */
    
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    #include <windows.h>
    using namespace std;
    
    /* allgemeine Variablen deklarieren und definieren */
    
    #define container struct
    #define out cout<<
    typedef short int INT16;	// 16 Bit
    typedef int INT32;		// 32 Bit
    typedef long long int INT64;	// 64 Bit
    typedef string STR32;	// 32 Bit
    
    /* programmspezifische Variablen deklarieren. */
    
    container data {
    	STR32 test0;
    } data;
    
    /* Programmcode */
    
    void clear () {
    	system ("cls");
    };
    void in (STR32 x) {
    	getline (cin,x);
    };
    void pause () {
    	system ("pause > NUL");
    };
    void sleep (INT32 msec) {
    	Sleep (msec);
    };
    INT32 main () {
    	in data.test0;
    	out data.test0;
    	pause();
    	return 0;
    };
    

    Warum meckert hier der Compiler mit folgendem Text:

    TEST.cpp: In function 'INT32 main()':
    TEST.cpp:45:5: error: expected ';' before 'data'
    *

    Danke im Voraus!

    Seikuassi



  • Von welcher Programmiersprache zum Teufel kommst du? oO

    Seikuassi schrieb:

    ich wollte eigentlich nur eine Funktion erstellen, die auch Leerzeichen in einem String auswertet. Eigentlich wird nur die Funktion getline aufgerufen.
    Ich will aber nicht immer

    getline (cin,VARIABLE);
    

    eingeben, sondern

    in VARIABLE;
    

    , was das gleiche Ergebnis erzielt.

    Wieso? Was hast du davon? Keiner kann dann deinen Code lesen, oder weiß was da passiert ohne vorher alle komischen Makros auswendig zu lernen.
    Außerdem sind Makros mit kurzen Namen ziemlich "gefährlich". Stell dir vor, du deklarierst eine Variable mit Namen in, was denkst du was der Compiler dir da für eine völlig komische Fehlermeldung geben kann.
    Edit: Ok, ich nehme jetzt gerade an, in sollte irgendwie ein Makro werden.

    #include <math.h>
    #include <stdlib.h>
    

    Bitte die C++-Versionen der C-Header einbinden: <cmath> und <cstdlib> .

    Die Makros sind nutzlos.

    #define container struct // Nein! Wieso? Was soll das? Wem bringt das was?
    #define out cout<<       // Ok, das haben wir alle mal gemacht. :D
    
    typedef short int INT16;	// 16 Bit
    typedef int INT32;		// 32 Bit
    typedef long long int INT64;	// 64 Bit
    typedef string STR32;	// 32 Bit
    

    Und die hier sind alle falsch. Statt INT16 zu benutzen, binde <cstdint> ein und nutze int16_t , dasselbe für alle anderen Typedefs - außer dem auf String, was soll das werden?
    32-Bit char-Typen gibt es erst seit C++11, und auch da muss man tierisch vorsichtig sein weil die noch ziemlich nutzlos sind (außer man benutzt bestimmte facets).

    Warum meckert hier der Compiler mit folgendem Text:

    Weil man in C++ Funktionen anders aufruft, wie du sicher weißt. Mit zwei runden Klammern ( und ), in denen optional (je nach Funktionssignatur) noch Argumente für die Parameter stehen.



  • INT32 main () {
        in data.test0;
        out data.test0;
        pause();
        return 0;
    };
    

    Das sieht noch zu sehr nach C++ aus. Erst mal die Klammern um den Funktionsrumpf weg.

    #define BEGIN {
    #define END }
    
    INT32 main ()
    BEGIN
        in data.test0;
        out data.test0;
        pause();
        return 0;
    END
    


  • #define container struct // Nein! Wieso? Was soll das? Wem bringt das was?

    Das bringt keinem was 😉 .

    Ich habe allerdings nochmal eine andere Frage: Warum kann man einen

    const char *
    

    ändern (s.Code)?

    /* Header-Dateien inkludieren */
    
    #include <iostream>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    using namespace std;
    
    /* allgemeine Variablen deklarieren und definieren */
    
    #define container struct
    #define out cout<<
    typedef short int INT16;	// 16 Bit
    typedef int INT32;		// 32 Bit
    typedef long long int INT64;	// 64 Bit
    typedef const char* STR8;	// 8 Bit
    
    /* programmspezifische Variablen deklarieren. */
    
    container data {
    	STR8 x0;
    } data;
    
    /* Programmcode */
    
    void clear () {
    	system ("cls");
    };
    void pause () {
    	system ("pause > NUL");
    };
    void sleep (INT32 msec) {
    	Sleep (msec);
    };
    INT32 main () {
    	data.x0 = "Hallo!";
    	out (data.x0);
    	data.x0 = "Ballo!";
    	out (data.x0);
    	pause();
    	return 0;
    };
    

    Bitte die C++-Versionen der C-Header einbinden: <cmath> und <cstdlib>.

    Würde ich gerne machen, aber scheinbar habe ich diese Bibliotheken nicht. Ich benutze MinGW32 g++.exe Version 4.7.x. Vielleicht fehlt diese...

    Danke im Voraus!

    Seikuassi



  • Ach, hätten wir bloß Whitespace-Overloading... :träum: (Pst: danke Volkard!)

    Und dann weiter:

    INT32 main ()
    ??<
        IN data.test0;
        OUT data.test0;
        PAUSE
    ??>
    

    Und das ganze kompiliert mit den richtigen Mitteln sogar:

    #include <iostream>
    #include <cstdint>
    
    typedef int32_t INT32;
    
    struct IN
    {
        template<typename T>
        IN( T&& t )
        {
            std::cin >> std::forward<T>(t); // Ich hab keine Ahnung, wieso ich perfect forwarding benutze. Keine.
        }
    };
    
    struct OUT
    {
        template<typename T>
        OUT( T&& t )
        {
            std::cout << std::forward<T>(t);
        }
    };
    
    #define IN (IN)
    #define OUT (OUT)
    
    INT32 main()
    ??<
        INT32 A;
        IN A; // Wahnsinnig idiomatisch. Volkard wäre stolz auf mich.
        OUT A;
    ??>
    


  • Hätte nicht gedacht, dass man sich so schnell in einem Forum unbeliebt machen kann... 😞 Tut mir Leid deswegen.

    Also gut, hier ein "normaler lesbarer" Code. Und noch mal die Frage: Warum kann man einen

    const char*
    

    verändern?

    #include <iostream>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    using namespace std;
    
    int main () {
    	const char* x0;
    	x0 = "Hallo0!";
    	cout << x0;
    	x0 = "Hallo1!";
    	cout << x0;
    	system ("pause > NUL");
    	return 0;
    };
    

    Danke im Voraus!

    Seikuassi



  • Ach, das war doch nur Gescherzle, nimm mich nicht ernst.

    Übrigens, dein Code funktioniert, weil das const sich auf den Pointee (sprich: Auf das Objekt auf das der Zeiger zeigt) bezieht, und nicht auf den Zeiger. Ob du den Wert den der Zeiger beinhaltet ändern kannst, oder den Wert auf den der Zeiger zeigt, das bestimmt die genaue Qualifizierung und ob der cv-qualifier vor oder nach dem * kommt:

    int const * ptr; // Der Zeiger ist variabel, der Pointee ist unveränderbar
    int * const ptr2; // Der Zeiger ist konstant, der Pointee ist veränderbar - gibt übrigens einen Compilerfehler (keine Initialisierung bei konstantem Objekt), da sieht man es auch nochmal, worauf sich das const bezieht
    int const * const ptr3; // Du darfst raten
    

    Siehe auch hier.



  • Ach, das war doch nur Gescherzle, nimm mich nicht ernst.

    Danke!

    int const * ptr; // Der Zeiger ist variabel, der Pointee ist unveränderbar
    

    Beim

    const char *
    

    funktioniert das. Warum gibt der Compiler aber ein Fehler aus, wenn ich

    const int * x = 39;
    cout << x;
    

    schreibe?

    const char * x ="39";
    cout << x;
    

    würde aber gehen. Warum ist das denn jetzt so?
    Der Fehler vom oberen Code sieht so aus:

    **
    TEST.cpp: In function 'INT32 main()':
    TEST.cpp:43:19: error: invalid conversion from 'int' to 'const int*' [-fpermissive]
    **

    Danke im Voraus!

    Seikuassi



  • Sone schrieb:

    Ach, hätten wir bloß Whitespace-Overloading... :träum: (Pst: danke Volkard!)

    Ach, du meinst wahrscheinlich lexical operator overloading aus C++27.

    #include <iostream>
    #include <operator> //für std::prefix, std::postfix
    #include <singleton>
    
    struct out [[std::singleton]]
    {
    	template <class T>
    	this &operator ' ' (T const &value) const
    	{
    		std::cout << value;
    	}
    };
    
    struct lexical_operators_demo
    {
    	this &operator ' ' () const
    	{
    		out 'h';
    	}
    
    	this &operator ' ' (std::prefix) const
    	{
    		out 'e';
    	}
    
    	this &operator '\t' () const
    	{
    		out 'l';
    	}
    
    	this &operator '\t' (std::prefix) const
    	{
    		out 'o';
    	}
    
    	this &operator '\n' () const
    	{
    		out '\n';
    	}
    
    	this &operator '(' (std::prefix) const {}
    	this &operator ')' (std::postfix) const {}
    
    	void operator ';' (std::postfix) const {}
    };
    
    int main(std::initializer_list<std::string>)
    {
    	(	(( (lexical_operators_demo{} ))		)
    );
    }
    

    (Das Beispiel erfordert GCC 11.2 oder Clang 3.56 mit der Option --std=c++2z.)



  • [[std::singleton]]
    

    Was zum Teufel soll denn das sein? oO
    Attribute sollen nicht so einen Quark machen. Die legen nur die Threading-Policy fest, die dann vom Compiler automatisch ergänzt wird.

    Und deine Funktionen haben kein return -Statement - aber warte, das wird in C++32 gefixt. Referenzen auf this werden natürlich automatisch zurückgegeben.

    Das wird zeitgleich mit variadic variadic templates eingeführt, mit denen man endlich die bis dahin fehlende Generizität in seinem Code hat. Wer wollte nicht schon mal beliebig viele template parameter packs haben? Wie sonst soll man bei partieller Spezialisierung eines Klassentemplates mit template parameter pack generisch bleiben?

    Schade nur, dass sich keiner mehr für C++ interessiert. D ist der Renner. :p



  • Sone schrieb:

    Und deine Funktionen haben kein return -Statement - aber warte, das wird in C++32 gefixt. Referenzen auf this werden natürlich automatisch zurückgegeben.

    Du benutzt wahrscheinlich Visual C++. Microsoft hat das automatische return noch nicht implementiert. Versuch mal GCC oder den neuen Clang.

    Sone schrieb:

    Das wird zeitgleich mit variadic variadic templates eingeführt, mit denen man endlich die bis dahin fehlende Generizität in seinem Code hat. Wer wollte nicht schon mal beliebig viele template parameter packs haben? Wie sonst soll man bei partieller Spezialisierung eines Klassentemplates mit template parameter pack generisch bleiben?

    #include <cstdint>
    #include <algorithm>
    
    //neue "uniform parameterization syntax" und variadic variadic template
    template {class ...Args1, ...{any ...Args2}}
    class A;
    
    //neue Typen
    using B{A{{std::uint512_t}, {tribool, <html><body>Hello, world!</body></html>}}};
    
    //Argument-Packs sind jetzt endlich richtige Ranges
    template {class ...Args}
    using C{A{
    	std::sort{
    		std::next{std::begin{Args}, 2},
    		std::end{Args}
    	}}};
    


  • <html><body>Hello, world!</body></html>
    

    YMMD! 😃



  • Seikuassi schrieb:

    Warum gibt der Compiler aber ein Fehler aus, wenn ich

    const int * x = 39;
    cout << x;
    

    schreibe?

    Weil 39 ein Integer ist und kein Zeiger auf einen Integer.

    Seikuassi schrieb:

    const char * x ="39";
    cout << x;
    

    würde aber gehen. Warum ist das denn jetzt so?

    Das geht, weil "39" ein String-Literal ist. Und String-Literals sind const char-Arrays. Und Arrays können implizit zu einem Zeiger auf ihr erstes Element umgewandelt werden.

    Ein char-Literal wäre '3', und const char * x ='3'; geht genau so wenig wie const int * x = 39; .


Anmelden zum Antworten