Wortzusammensetzung über Pointer und getline() statt mit gets()
-
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_casthä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::stringbzwconst std::string&hier durchconst 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
stringbesser 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öglichWieso nimmst du denn auch die Adressen der Arrays?
Übergib' einfach direkt die Arrays, das array-to-pointer decay macht den Rest.
-
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öglichVerstehst du diese Fehlermeldungen? Weißt du, was char(*)[80] ist?
-
Sone schrieb:
Und was soll in diesem Fall an
stringbesser 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]; }[...]
Immer diese Vorurteile gegenüber Zeigern...
In Zeile 8 sehe ich ein falsches
&. Beim Umgang mit Zeigern hast du also schon in so einem simplen Beispiel einen Flüchtigkeitsfehler gemacht. Mitstringwäre das nicht passiert.Ich sehe ja ein, dass die Speicheranforderung durch
stringverschwenderisch ist. Aberconst char *ist eindeutig die falsche Alternative. Die Idee von C++ ist nicht, dass man bei jedem kleinen Hindernis in prähistorisches Verhalten zurückfällt.Die Vorteile von
stringohne die Nachteile:#include <utility> #include <iostream> #include <array> #include <cassert> #include <cstring> template <class C> class basic_string_ref { public: typedef C value_type; typedef C &reference; typedef C *iterator; typedef iterator const_iterator; typedef std::size_t size_type; basic_string_ref(); basic_string_ref(iterator begin, iterator end); template <std::size_t N> basic_string_ref(value_type (&data)[N]); basic_string_ref(iterator c_string) : m_begin(c_string) , m_end(c_string + std::strlen(c_string)) { } size_type size() const { return std::distance(m_begin, m_end); } iterator data() const { return m_begin; } bool empty() const; iterator begin() const { return m_begin; } iterator end() const { return m_end; } //... private: iterator m_begin; iterator m_end; }; template <class C> std::basic_ostream<typename std::remove_const<C>::type> &operator << ( std::basic_ostream<typename std::remove_const<C>::type> &os, basic_string_ref<C> const &str) { std::copy(str.begin(), str.end(), std::ostreambuf_iterator<typename std::remove_const<C>::type>(os)); return os; } typedef basic_string_ref<char> string_ref; typedef basic_string_ref<const char> cstring_ref; namespace { const std::array<cstring_ref, 2> emlist = {{ "foo", "bar" }}; } cstring_ref const &errormsg(unsigned errorcode) { assert(errorcode < emlist.size()); return emlist[errorcode]; } int main() { for (auto i = emlist.begin(); i != emlist.end(); ++i) { std::cout << *i << '\n'; } }EDIT:
const-Verhalten korrigiert (danke an krümelkacker).