Wortzusammensetzung über Pointer und getline() statt mit gets()



  • Hallo und guten Morgen liebe Gemeinde.

    Vor einigen Wochen habe ich folgenden Code gepostet:

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	char text1[80];
    	char text2[40];
    	char text3[40];
    
    	cout << "Erstes Wort eingeben: ";
    	gets(text2);
    
    	cout << "Zweites Wort eingeben: ";
    	gets(text3);
    
    	strcpy(text1, text2);
    	strcat(text1, text3);
    
    	cout << "Zusammengefuegt: " << text1 << endl;
    
    	return 0;
    }
    

    Da mir geschrieben wurde, dass dieser Code aufgrund der Verwendung von der Funktion gets() nicht so gut sein solle, habe ich heute versucht, über Pointer und getline() den gleichen Code zu schreiben.

    #include<iostream>
    #include<string>
    using namespace std;
    
    int main()
    {
    	char Text_1[160];
    	char *pText_1 = {&Text_1[160]};
    	char Text_2[80];
    	char *pText_2 = {&Text_2[80]};
    	char Text_3[80];
    	char *pText_3 = {&Text_3[80]};
    
    	cout << "Erstes Wort eingeben:\n";
    	getline(cin, &Text_2);
    
    	cout << "Zweites Wort eingeben:\n";
    	getline(cin, &Text_3);
    
    	strcpy(&Text_1, &Text_2);
    	strcat(&Text_1, &Text_3);
    
    	cout << "Zusammengefuegtes Wort:" << &Text_1 << "\n";
    	cout << "Speicheradresse vom ersten Wort:            " << &Text_2 << "\n";
    	cout << "Speicheradresse vom zweiten Wort:           " << &Text_3 << "\n";
    	cout << "Speicheradresse vom zusammengefuegten Wort: " << &Text_1 << "\n";
    
    	return 0;
    }
    

    Bei diesem Code bekomme ich jedoch die wüßten Fehlermeldungen.

    Auch habe ich in meinen Büchern nichts verwertbares dazu gefunden.

    Was habe ich falsch gemacht bzw. wo ist mein Denkfehler?

    Danke für die Antworten im Voraus.

    Gruß

    Max



  • Was habe ich falsch gemacht bzw. wo ist mein Denkfehler?

    Du benutzt C-Strings.
    Das geht nie gut. 🤡 ⚠

    #include <iostream>
    #include <string>
    
    int main()
    {
        std::string str, str2, strinst;
    
        std::cout << "Geben Sie bitte ein Wort ein: ";
        std::cin >> str;
        std::cout << "Geben Sie bitte ein zweites Wort ein: ";
        std::cin >> str2;
    
        strinst = str + str2;
        std::cout << "Zusammengesetztes Wort: " << strinst << '\n'
                  << "Speicheradresse vom ersten Wort: "            << reinterpret_cast<void const*>(str    .c_str()) << '\n'
                  << "Speicheradresse vom zweiten Wort: "           << reinterpret_cast<void const*>(str2   .c_str()) << '\n'
                  << "Speicheradresse vom zusammengesetzten Wort: " << reinterpret_cast<void const*>(strinst.c_str()) << '\n';
    }
    

    :xmas2:



  • was soll das denn alles werden ?
    benutze einfach std::string und du hast keine probleme mehr.
    aber wenn du es mit c-strings machen willst, brauchst du dafür keine pointer:

    #include <iostream>
    
    int main()
    {
        char c[50];
        std::cin.getline(c, 50);
        std::cout << c << "\n";
    }
    

    ich versteh aber immer noch nicht, warum du nicht std::string verwendest.



  • Sone schrieb:

    Du benutzt C-Strings.
    Das geht nie gut.

    Also kann ich es über Pointer auf chars vergessen oder gibt es einen Weg??



  • silent_max schrieb:

    Sone schrieb:

    Du benutzt C-Strings.
    Das geht nie gut.

    Also kann ich es über Pointer auf chars vergessen oder gibt es einen Weg??

    Natürlich gibt es Wege.

    Aber wozu das Leben schwer machen?



  • silent_max schrieb:

    Bei diesem Code bekomme ich jedoch die wüßten Fehlermeldungen.

    Welche? Und was verstehst du an den Fehlermeldungen nicht?

    silent_max schrieb:

    Auch habe ich in meinen Büchern nichts verwertbares dazu gefunden.

    Wonach hast du denn genau gesucht?

    silent_max schrieb:

    Was habe ich falsch gemacht bzw. wo ist mein Denkfehler?

    Eine ganze Menge. Dein aktueller C++-Lern-Ansatz scheint sehr ineffizient zu sein. Ich kann nicht glauben, dass du die Bücher, die du angeblich besitzt, richtig verwendest. Dein zweites Programm ergibt von vorne bis hinten keinen Sinn. Erzähl mal, was du dir dabei gedacht hast.



  • Sone schrieb:

    Aber wozu das Leben schwer machen?

    Was heißt schwer machen?

    Ich wollte einfach wissen, ob das klappt oder nicht. Und da mein Denkansatz wohl falsch ist, wollte ich euch Profis nach Tipps und Tricks fragen, wie ich über Pointer auf chars und der Funktion getline() ein Wort zusammen fügen kann, da ja die Funktion gets() verpönnt ist.

    Gruß



  • Was soll an getline mit char-Arrays besser sein?



  • silent_max schrieb:

    ... wollte ich euch Profis nach Tipps und Tricks fragen ...

    Die Tips und Tricks lauten ganz einfach:
    Benutze - wo immer es geht - std::string anstelle von C-Strings.



  • manni66 schrieb:

    Was soll an getline mit char-Arrays besser sein?

    Ne ganze Menge.



  • Sone schrieb:

    std::cout << "Zusammengesetztes Wort: " << strinst << '\n'
                  << "Speicheradresse vom ersten Wort: "            << reinterpret_cast<void const*>(str    .c_str()) << '\n'
                  << "Speicheradresse vom zweiten Wort: "           << reinterpret_cast<void const*>(str2   .c_str()) << '\n'
                  << "Speicheradresse vom zusammengesetzten Wort: " << reinterpret_cast<void const*>(strinst.c_str()) << '\n';
    }
    

    static_cast hätte es auch getan.



  • Belli schrieb:

    Die Tips und Tricks lauten ganz einfach:
    Benutze - wo immer es geht - std::string anstelle von C-Strings.

    Das würde ich noch einschränken. std::string braucht man nicht für Konstanten. const-char-Zeiger, die z.B. auf die Zeichenkettenliteral-Arrays zeigen, sind ja in Ordnung. Den Speicher, auf den sie zeigen, muss man nicht selbst verwalten und mit dem Read-Only-Zugriff kann man auch nicht viel Schaden anrichten.

    Ich denke da an solche Situationen:

    //im header
    
    string errormsg(int errorcode);
    
    //im cpp file
    
    const string emlist[] = {
      "foo", "bar"
    };
    
    string errormsg(int errorcode) {
      if (errorcode<0 || errorcode>=2) return "wtf";
      return emlist[errorcode];
    }
    

    wo std::string eine ziemlich blöde Idee ist. Besser:

    //im header
    
    const char* errormsg(int errorcode);
    
    //im cpp file
    
    const char*const emlist[] = {
      "foo", "bar"
    };
    
    const char* errormsg(int errorcode) {
      if (errorcode<0 || errorcode>=2) return "wtf";
      return emlist[errorcode];
    }
    


  • Warum nicht so?

    namespace
    {
      const std::array<std::string, 2> emlist = {{
        "foo", "bar"
      }};
    }
    
    const std::string &errormsg(unsigned errorcode) {
      assert(errorcode < emlist.size());
      return emlist[errorcode];
    }
    


  • TyRoXx schrieb:

    Warum nicht so?

    namespace
    {
      const std::array<std::string, 2> emlist = {{
        "foo", "bar"
      }};
    }
     
    const std::string &errormsg(unsigned errorcode) {
      assert(errorcode < emlist.size());
      return emlist[errorcode];
    }
    

    kk schrieb:

    std::string braucht man nicht für Konstanten. const-char-Zeiger, die z.B. auf die Zeichenkettenliteral-Arrays zeigen, sind ja in Ordnung. Den Speicher, auf den sie zeigen, muss man nicht selbst verwalten und mit dem Read-Only-Zugriff kann man auch nicht viel Schaden anrichten.



  • Sone schrieb:

    kk schrieb:

    std::string braucht man nicht für Konstanten. const-char-Zeiger, die z.B. auf die Zeichenkettenliteral-Arrays zeigen, sind ja in Ordnung. Den Speicher, auf den sie zeigen, muss man nicht selbst verwalten und mit dem Read-Only-Zugriff kann man auch nicht viel Schaden anrichten.

    Und was soll an dem Zeigergefrickel jetzt besser sein als string ?
    Die paar gesparten Bytes zählen nicht. Die gesparte Indirektion auch nicht, das spielt bei Fehlerbehandlung keine Rolle.



  • TyRoXx schrieb:

    Warum nicht so?

    namespace
    {
      const std::array<std::string, 2> emlist = {{
        "foo", "bar"
      }};
    }
     
    const std::string &errormsg(unsigned errorcode) {
      assert(errorcode < emlist.size());
      return emlist[errorcode];
    }
    

    Mach, was du willst. Mir passt da die dynamische Initialisierung nicht, in der Zeichenketten aus dem statischen Speicher (die Literal-Arrays) kurz vor der Ausführung von main sinnloserweise in den Freispeicher kopiert werden. Damit gewinnst du noch nicht mal etwas...

    std::string bzw const std::string& hier durch const char* zu ersetzen ist keine Pointer-Frickelei.



  • TyRoXx schrieb:

    Sone schrieb:

    kk schrieb:

    std::string braucht man nicht für Konstanten. const-char-Zeiger, die z.B. auf die Zeichenkettenliteral-Arrays zeigen, sind ja in Ordnung. Den Speicher, auf den sie zeigen, muss man nicht selbst verwalten und mit dem Read-Only-Zugriff kann man auch nicht viel Schaden anrichten.

    Und was soll an dem Zeigergefrickel jetzt besser sein als string ?

    Und was soll in diesem Fall an string besser sein?

    namespace
    {
      const std::array<char const*, 2> emlist = {{
        "foo", "bar"
      }};
    }
    
    char const* &errormsg(std::array<char const*, 2>::size_type errorcode) {
      assert(errorcode < emlist.size());
      return emlist[errorcode];
    }
    

    Edit:

    std::string bzw const std::string& hier durch const char* zu ersetzen ist keine Pointer-Frickelei.

    👍
    Wie kamst du darauf, Tyrox?

    Immer diese Vorurteile gegenüber Zeigern...



  • Auch dieser Code wird von meinem Compiler nicht angenommen:

    #include<iostream>
    using namespace std;
    
    int main()
    {
    	char Text_1[160];
    	char *pText_1 = {&Text_1[160]};
    	char Text_2[80];
    	char *pText_2 = {&Text_2[80]};
    	char Text_3[80];
    	char *pText_3 = {&Text_3[80]};
    
    	cout << "Erstes Wort eingeben:\n";
    	gets(&Text_2);
    
    	cout << "Zweites Wort eingeben:\n";
    	gets(&Text_3);
    
    	strcpy(&Text_1, &Text_2);
    	strcat(&Text_1, &Text_3);
    
    	cout << "Zusammengefuegtes Wort:" << &Text_1 << "\n";
    	cout << "Speicheradresse vom ersten Wort:            " << &Text_2 << "\n";
    	cout << "Speicheradresse vom zweiten Wort:           " << &Text_3 << "\n";
    	cout << "Speicheradresse vom zusammengefuegten Wort: " << &Text_1 << "\n";
    
    	return 0;
    }
    

    Dann kann ich die Idee ja völlig vergessen...



  • silent_max schrieb:

    Auch dieser Code wird von meinem Compiler nicht angenommen

    Was sagt er denn?



  • error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
     error C2664: 'strcpy': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    error C2664: 'strcat': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    


  • silent_max schrieb:

    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
     error C2664: 'strcpy': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    error C2664: 'strcat': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    

    Wieso nimmst du denn auch die Adressen der Arrays?
    Übergib' einfach direkt die Arrays, das array-to-pointer decay macht den Rest.


Anmelden zum Antworten