String Problem II
-
Danke es klappt, nur verstehen tu ich´s nicht...
for(int i=textCopy.length()-1; i >= 0 ;i--)
{
text[zwsp] = textCopy[i];
zwsp++;
}Ich hab jetzt nur das -1 nach textCopy.lenght() dazu gegeben.
Wieso klappt es jetzt?

Die Schleife wird ja dadurch kürzer. Oh Backe, sicher gibt´s dafür eine klare Antwort. Wäre dankbar wenn du Sie mir erklären könntest.
Lass dir mal text.length() ausgeben und überleg noch mal GANZ SCHARF, bei welchem Index Arrays (oder hier auch strings) immer anfangen. Tip: es ist nicht 1.
Das weiß ich doch, hab ich doch nirgendwo im Code stehen oder ?

Sorry für diese "blöden" Fragen, aber ich versteh´s einfach nicht. Bin ja auch hart am lernen.Lg Mentras
-
gehs doch mal an nem beispiel durch:
"abc"
->
for(int i=textCopy.length(); i >= 0 ;i--)
length = 3
-> i=3, i=2, i=1, i=0text[zwsp] = textCopy[i];
text[0] = i[3]
text[1] = i[2]
text[2] = i[1]
text[3] = i[0]->
"\0cba"
aber da length schon explizit auf 3 gesetzt wurde (beim copy-ctor), bekommst du nur die ersten 3 zeichen ausgegeben:
"\0cb"
->
"cb"wobei das erste zeichen ('\0') implementation defined ist - heißt, dass du nicht davon ausgehen solltest, dass es auch wirklich so ist...
btw:
std::string umdrehen(const std::string& text) { std::string ret; ret.reserve(text.length()); //nicht notwendig, aber eigtl ne tolle sache ^^ for(int i=text.length()-1; i >= 0 ;i--) { ret.push_back(text[i]); } return ret; }oder
std::string umdrehen(const std::string& text) { std::string R = text; std::string::size_type laenge = text.length(); for(std::string::size_type i(laenge), e(laenge/2); i != e; --i) { std::swap(R[i], R[laenge-i]); } return R; }oder (nicht so hübsch)
std::string umdrehen(const std::string& text) { std::string R = text; std::string::size_type laenge = R.length(); for(std::string::size_type i(laenge), e(laenge/2), i2(0); i2 != laenge; --i, ++i2) { text[i] = text[i2]; } return R; }oder (mein favorit)
std::string GetReverse(const std::string &value) { std::string R(value.rend(), value.rbegin()); return R; }bb
PS: Ist alles ungetestet und kann durchaus fehler beinhalten - aber vll haste ja lust mal zu gucken, wie was funktioniert und siehst dann auch, dass du nicht gerade den besten weg gewählt hast ^^
-
Ahhhh,
diese /0 ist das Ende eines Strings oder wie?
Nagut, mit meinem Wissen hab ich daweil den besten Weg gewählt

Bei den aufgelisteten Methoden, die du mir gezeigt hast, verstehe ich die erste Zeile nicht ganz. Vielleicht aber später, wenn ich das Buch durch habe.
std::string umdrehen(const std::string& text)Du deklarierst hier eine Funktion namens "umdrehen" vom Typ String. Die einen Konstanten String-Wert übergeben bekommt,......*buff* schlagt der Hammer zu.
Danach kommt der Adreßoperator, ... und dann schweigt mein Hirn und versorgt meine Zunge nicht mehr mit Wissen^^Lg Mentras
-
Mentras schrieb:
Ahhhh,
diese /0 ist das Ende eines Strings oder wie?
Nö, hat er doch gescgrieben, dass das von Implementierung zu Implementierung anders sein kann. Es liegt nicht an dem Null-terminiertem String, sondern daran, dass du deinen textCopy als KOPIE des Ursprungsstrings erstellt hast. Damit hat er eine bestimmte Länge, über die hinaus du nicht schreiben kannst. Da du am Anfang str[str.length()] eingefügt hast (was ja nicht geht) hast du einen Index schon mit Müll belegt (wahrscheinlich tatsächlich "\0"), somit bleiben dir nur noch length() -1 indizes zu belegen, was einer zu wenig für den kompletten String ist, drum bliebe die 1 in deinem Beispiel unkopiert.
std::string umdrehen(const std::string& text)Du deklarierst hier eine Funktion namens "umdrehen" vom Typ String. Die einen Konstanten String-Wert übergeben bekommt,......*buff* schlagt der Hammer zu.
Danach kommt der Adreßoperator, ... und dann schweigt mein Hirn und versorgt meine Zunge nicht mehr mit Wissen^^Mach dich mal Schlau "Call by Value" und "Call by Reference".
(Kurz: Du übergibst eine Kopie an die Funktion, das mit dem "&" nur eine Referenz, also die Adresse. Das geht schneller, da der String nicht kopiert werden muss.)
-
Vielen Dank, Friedel und unskilled.
Hab´s allmählich verstanden.
Hier für euch
-
gern geschehen ^^
ist auch schade, dass die implementierung so etwas überhaupt zulässt:
std::string R("asd"); R[3] = '\0';warum ist mir schon klar(zumindest beim MSVC) - weil string eben von irgend ner vector-basisklasse erbt - und da sinnigerweise(std::string::c_str) die '\0' noch hinten im vector steht...
hätte aber erwartet, dass da im debug-mode noch irgend nen extra op[] definiert wird, der das checkt - aber man kann eben nich alles haben ^^bb
-
friedel fiedel schrieb:
Außerdem ist das Übergeben als Kopie mit viel Kopieraufwand verbunden. Übergib doch mal ne Referenz!
So könnte es dann ausschauen:
std::string umdrehen(const std::string& text) { std::string ret; for(int i=text.length()-1; i >= 0 ;i--) { ret.push_back(text[i]); } return ret; }Was die Performanz angeht, kann man das sogar noch steigern. Hier ist die "Swaptimization" ...

string umdrehen(string x) { string ret; ret.swap(x); //< string::swap ist schnell for (int i=0, j=ret.length()-1; i<j; ++i,--j) { char c = ret[i]; ret[i] = ret[j]; ret[j] = c; } return ret; }
-
@Swaptimizer
bringts total, da auf swap zu setzen und dafür die kopie schon früher anfertigen zu lassen
n1bb
-
unskilled schrieb:
@Swaptimizer
bringts total, da auf swap zu setzen und dafür die kopie schon früher anfertigen zu lassen
n1Nun, ich habe mit dem Optimierungsthema nicht angefangen. Wollte nur drauf hinweisen, dass "da noch was geht". Ich war am Überlegen, ob ich noch erklären soll, warum das in einigen Fällen besser sein kann. Es war wohl doch nicht offensichtlich. Die "swaptimierte" Version setzt nicht nur auf swap sondern auch auf Compiler die unnötige Kopien bei Rvalue-Argumenten wegoptimieren können (copy elision). Du kannst ja mal "string" selbst wie einen vector implementieren (also ohne copy-on-write) und testen, wie oft Du bei folgendem Beispiel eine Kopie des Heap-allozierten Zeichen-Arrays durchführen musst:
string quelle() {return "Hallo Welt!";} int main() { string hw = umdrehen(umdrehen(quelle())); cout << hw << endl; }
-
Es gibt übrigens auch
std::reverse().