String
-
Noch schlimmer: Ein std::string kann auch mittendrin Nullbytes enthalten. Eine while()-Schleife wie deine würde also ggf. nur den halben std::string sehen.
Stefan.
-
och nö schrieb:
drakon schrieb:
Nein. std::string hat keine Null-Terminierung.
Wenn du aber einen C String aus einem
std::string
haben willst, dann gibt es dafür die Member std::string::c_str.Was soll n das wieder für ein Tipp sein? Soll er jetzt jedem std::string nen char* damit er mit while durchgehen kann?
Hmm. Ich habe gesagt, dass es diese Funktion gibt, wenn man einen C-String haben will. Hast aber recht, dass man das dann nicht so einsezen sollte, um durch zu gehen.
-
DStefan schrieb:
Noch schlimmer: Ein std::string kann auch mittendrin Nullbytes enthalten. Eine while()-Schleife wie deine würde also ggf. nur den halben std::string sehen.
Stefan.
Gruselig, dann werde ich mir mal die Iterator (Klasse?) angucken... danke!
-
Wozu brauchst du das überhaupt? Evtl. gibt es für dein Problem ja eine andere Lösung als eine while-Schleife.
-
Naja arbeite an einer Verschlüsselung (So zur Übung)
Und da übergebe ich einer Funktion einen String.
Die Funktion läuft jetzt in einer Schleife jedes Zeichen durch und ersetzt diese mit einer Zahl aus einer 2D-Matrix. (Polybios-Chiffre)
Ja, und die Funktion funktioniert irgendwie nicht,...
std::string verschluesseln(std::string nocrypt) /* Verschluesselungen */ { /* Polybios Verschluesselung... */ for(int i=0;i!='\0';i++) //Da muss ich die Bedingung ändern. { switch(nocrypt.at(i)) { //ein paar cases
-
Mach es doch eben mit Iteratoren:
// Wichtig: Const-Referenz als Parameter, um unnötige Kopie zu sparen std::string verschluesseln(const std::string& nocrypt) { for (std::string::iterator itr = nocrypt.begin(), end = nocrypt.end(); itr != end, ++itr) { mache_etwas(*itr); } }
Du kannst auch Indizes benutzen, allerdings solltest du als Abbruchbedingung die Länge des Strings haben. Momentan probierst du, auf 0 zu prüfen ('\0' == 0) und somit läuft die Schleife nie.
-
// Wichtig: Const-Referenz als Parameter, um unnötige Kopie zu sparen std::string verschluesseln(const std::string& nocrypt) { for (std::string::iterator itr = nocrypt.begin(), end = nocrypt.end(); itr != end, ++itr) { mache_etwas(*itr); } }
Wieso muss ich eine const-Referenz angeben? Dann kann ich ja den String nicht mehr ändern.
-
Nun, es funktioniert und ich freu mich echt doll xD
Nur sollte ich mir lieber das Kapitel "const" wieder angucken. Verstehe momentan gar nicht wieso der String sich verändern konnte.
Danke Leute werde nun nur noch iteratoren anstatt die while(i!='\0') benutzen^^
-
anfänger94 schrieb:
Wieso muss ich eine const-Referenz angeben? Dann kann ich ja den String nicht mehr ändern.
Du musst ja den Originalstring nicht ändern, sondern einen neuen erzeugen. Leider habe ich vergessen, einen neuen zu deklarieren und auf diesem zu operieren, tut mir leid. Die
return
-Anweisung käme dann auch noch hin.Man kann natürlich auch eine Version schreiben, die eine (Non-Const-)Referenz nimmt und den Originalstring ändert. Und dann vielleicht noch eine, die auf diese zugreift und eine Kopie zurückgibt (analog zu
operator+
undoperator+=
).
-
Ach, kein Problem das mit dem returnen war klar ^^
Allerdings hab ich es mit dem const echt nicht verstanden. Sobald ich schreibe:
const std::string& test
meldet der Compiler:
Fehler error C2440: 'Initialisierung': 'std::_String_const_iterator<_Elem,_Traits,_Alloc>' kann nicht in 'std::_String_iterator<_Elem,_Traits,_Alloc>' konvertiert werden
-
anfänger94 schrieb:
Ach, kein Problem das mit dem returnen war klar ^^
Allerdings hab ich es mit dem const echt nicht verstanden. Sobald ich schreibe:
const std::string& test
meldet der Compiler:
Fehler error C2440: 'Initialisierung': 'std::_String_const_iterator<_Elem,_Traits,_Alloc>' kann nicht in 'std::_String_iterator<_Elem,_Traits,_Alloc>' konvertiert werden
Du brauchst dann natürlich auch einen const_iterator, weil du ja sonst den string über Iteratoren ändern könntest, was ja nicht gehen darf.
-
Ja, weil du dann eben versuchst, den konstanten String zu verändern (Zugriff über
iterator
ist nicht erlaubt beiconst
-qualifizierten Objekten, dafür sollte manconst_iterator
nehmen, wodurch man aber wieder die vom Iterator referenzierten Objekte nicht ändern kann).Eine Möglichkeit:
// Const-Referenz als Parameter, Rückgabetyp std::string // Verändert den Originalstring nicht, gibt einen verschlüsselten zurück. std::string verschluesseln(const std::string& nocrypt) { std::string kopie = nocrypt; for (std::string::iterator itr = kopie.begin(), end = kopie.end(); itr != end, ++itr) { mache_etwas(*itr); } return kopie; }
Oder eine Aufteilung in zwei Funktionen, von denen eine den String direkt ändert (ich denke, oft ist dieses Verhalten erwünscht, und dann ist
a = verschluesseln(a)
Performance-Verschwendung):// Referenz als Parameter und Rückgabetyp void // Verschlüsselt direkt den String, der als Parameter übergeben wird. void verschluesseln(std::string& nocrypt) { for (std::string::iterator itr = nocrypt.begin(), end = nocrypt.end(); itr != end, ++itr) { mache_etwas(*itr); } } // Const-Referenz als Parameter, Rückgabetyp std::string // Gleiches Verhalten wie die obere Funktion (1. Möglichkeit) std::string erstelle_verschluesselung(const std::string& nocrypt) { std::string kopie = nocrypt; verschluesseln(kopie); return kopie; }
-
Nexus schrieb:
// Const-Referenz als Parameter, Rückgabetyp std::string // Gleiches Verhalten wie die obere Funktion (1. Möglichkeit) std::string erstelle_verschluesselung(const std::string& nocrypt) { std::string kopie = nocrypt; verschluesseln(kopie); return kopie; }
Selbst das kann wie folgt noch verbessert werden.
std::string erstelle_verschluesselung(std::string nocrypt) { std::string kopie; kopie.swap(nocrypt); verschluesseln(kopie); return kopie; }
Siehe Artikel von Dave Abrahams.
Gruß,
SP
-
Sebastian Pizer schrieb:
Selbst das kann wie folgt noch verbessert werden. [...] Siehe Artikel von Dave Abrahams.
Vielen Dank für diesen wertvollen Hinweis! Ich sollte mich endlich mal ausführlich mit solchen Dingen befassen... Den Artikel habe ich mir zwar auch schon angeschaut, allzu viel scheint da aber nicht geblieben zu sein.
-
ahhhh!
Verstehe es so langsam!
Werde mich mal mit dem Kapitel auseinandersetzen.Danke für eure Erklärungen
-
Sebastian Pizer schrieb:
Selbst das kann wie folgt noch verbessert werden.
std::string erstelle_verschluesselung(std::string nocrypt) { std::string kopie; kopie.swap(nocrypt); verschluesseln(kopie); return kopie; }
Siehe Artikel von Dave Abrahams.
Ich hätte an sowas gedacht
std::string erstelle_verschluesselung(std::string kopie) { verschluesseln(kopie); return kopie; }
-
volkard schrieb:
Ich hätte an sowas gedacht
std::string erstelle_verschluesselung(std::string kopie) { verschluesseln(kopie); return kopie; }
Allerdings führt kein existierender Compiler hier NRVO durch (zumindest wenn nicht geinlined wird). Verständlich, denn hier müsste bereits der Aufrufer wissen, dass Funktionsargument und Rückggabewert den gleichen Speicherbereich einnehmen.