Warum läuft dieser Code?
-
Betrifft zwar nicht direkt das Thema, aber noch einige Anmerkungen:
- Bitte [cpp]- statt [code]-Tags verwenden.
- Code einrücken erhöht die Lesbarkeit.
- Am Ende von Anweisungsblöcken (Funktionen/Schleifen/If-Abfragen) braucht es kein Semikolon (ist aber erlaubt).
-
Also zuerst mal: str + j++ : j hat ja den Postinkrement-Operator, dh. es wird erst in dem Ausdruck verwendet, mit seinem 'alten Wert', beim ersten Durchlauf also mit 0, und danach inkrementiert. Es findet also im ersten Schleifendurchlauf die Zuweisung *(str + 0) = *(str + 0) statt und erst nach dieser Zuweisung hat j den Wert 1.
Aha, das war mir schon mal nicht bewusst. Ich habe angenommen, dass der ++ -Operator Vorrang hat. Hat das speziell mit Konditionen (bedingungen) zu tun? In div. Tabellen hat ++ immer Vorrang vor +. Oder habe ich da eine generelle Lücke (zwischen den anderen Lücken; habe gerade erst mit c++ angefangen)?
Dann: was meinst Du mit Value = Value? Da steht dann letztendlich, was ich gerade beschrieben habe, eine ganz normale Zuweisung, in der eine Zeigervariable - str - mit dem *-Operator dereferenziert wird.
Das meine ich ja. Diese Zuweisung kann doch gar nicht funktionieren. Da auf beiden Seiten der Zuweisung dereferenziert wird, muss es doch auf einen Fehler hinauslaufen. Denn wenn rechts ein value steht (also ein konkreter Wert; dereferenziert), dann muss das doch in eine Variable gesteckt werden, zB:
char neu = *str;str ist ein Zeiger auf einen Character, mit str + irgendwas wird ein entsprechender Offset auf den Zeiger addiert, so daß er dann auf einen anderen Character zeigt, und mit *str - oder eben auch mit *(str + irgendwas) wird der char, auf den gezeigt wird, angesprochen (gelesen oder beschrieben).
Müsste der Code dann nicht
(str + 0) = *(str + 0);lauten? Also 'Zeiger auf' = 'Wert aus'?
-
Frage: merkt der Compiler, auf welcher Seite der Zuweisung er gerade ist? Dann würde
*str = *str;ja Sinn machen, weil er dann einfach den Inhalt (value) aus str an die Speicherstelle von str schreiben könnte. Ich bin davon ausgegangen, dass erstmal beiden Seiten "ausgerechnet" werden, und anschliessend geguckt wird, ob die Zuweisung passt oder nicht.
-
Stell dir das so vor:
(*str).operator=(*str);Vielleicht wird aber auch alles klarer, wenn man das mal vernünftig aufschreibt!
void eatspaces(char* str) { int i=0; int j=0; while( (str[i] = str[j++]) != '\0' ) { { if( str[i] != ' ') i++; } return; };Also: Er kopiert solange von Position j auf Position i und erhöht dann j, bis an Position i irgendwas != Leerzeichen steht. Dann erhöht er i um einen. j eilt i sozusagen voraus. Und das ganze macht er solange, bis er auf i ein \0 aka 0-Terminator geschrieben hat.
-
Decimad schrieb:
Stell dir das so vor:
(*str).operator=(*str);Vielleicht wird aber auch alles klarer, wenn man das mal vernünftig aufschreibt!
void eatspaces(char* str) { int i=0; int j=0; while( (str[i] = str[j++]) != '\0' ) { { if( str[i] != ' ') i++; } return; };Also: Er kopiert solange von Position j auf Position i und erhöht dann j, bis an Position i irgendwas != Leerzeichen steht. Dann erhöht er i um einen. j eilt i sozusagen voraus. Und das ganze macht er solange, bis er auf i ein \0 aka 0-Terminator geschrieben hat.
Alles klar! Astrein, Deinen neuen Code verstehe ich endlich und das, was da eigentlich passiert. Oh mann, diese c++-Syntax macht mich wirklich noch narrisch.
Vielen Dank für die Hilfe! Wieder ein bisschen mehr verstanden.
-
Ist der Codeabschnitt aus einer Übung à la "finden Sie 10 Gründe, warum folgender Code nicht gut ist?".
Wenn nicht, ist das "return;", die Semikolons und die Klammern um i++ wirklich so im Original abgedruckt?
-
Nanyuki schrieb:
Ist der Codeabschnitt aus einer Übung à la "finden Sie 10 Gründe, warum folgender Code nicht gut ist?".
Wenn nicht, ist das "return;", die Semikolons und die Klammern um i++ wirklich so im Original abgedruckt?Im Original:
void eatspaces(char* str) { int i = 0; // 'Copy to' index to string int j = 0; // 'Copy from' index to string while((*(str + i) = *(str + j++)) != '\0') // Loop while character // copied is not \0 if(*(str + i) != ' ') // Increment i as long as i++; // character is not a space return; }So oder so ging's mir ja nur um die while-Kondition, die ich bis dato nicht verstanden hatte. Das Buch "Ivor Horton's c++" finde ich persönlich ansonsten ganz gut. Mein M&T-Buch ist dagegen der letzte Schrott.
Naja, dauert dann halt schon etwas, bis ich mich vernünftig eingearbeitet habe. Aber: den obigen Code finde ich - in meinen Anfängeraugen - auch völlig unverständlich.
-
[quote="isitthatsimple"]
Ich habe angenommen, dass der ++ -Operator Vorrang hat. Hat das speziell mit Konditionen (bedingungen) zu tun? In div. Tabellen hat ++ immer Vorrang vor +. Oder habe ich da eine generelle Lücke (zwischen den anderen Lücken; habe gerade erst mit c++ angefangen)?
int i = 0; int a = 5; i = a++; // jetzt ist i == 5 und a == 6 i = ++a; // jetzt ist i == 7 und a ebenfalls
-
Übrigens kann man bei 'int's den Test auf "!= 0" weglassen, das wird automatisch gemacht, wenn ein bool herauskommen soll (den die while-Schleife ja verlangt):
void eatspaces(char* str) { int i=0, j=0; while ( str[i] = str[j++] ) if ( str[i] != ' ' ) ++i; }
-
Zumindest mein Compiler würde jedoch bei obigem Code warnen, daß man möglicherweise '=' anstatt "==" verwendet habe. Das Verwenden von "!= 0" dokumentiert die explizite Berücksichtigung dieser Möglichkeit für Compiler sowie für andere Programmierer.
-
Badestrand schrieb:
Übrigens kann man bei 'int's den Test auf "!= 0" weglassen, das wird automatisch gemacht, wenn ein bool herauskommen soll (den die while-Schleife ja verlangt):
void eatspaces(char* str) { int i=0, j=0; while ( str[i] = str[j++] ) if ( str[i] != ' ' ) ++i; }Wobei in diesem speziellen Fall ja nach dem EOL (\0) werden soll. Nichtsdestotrotz ist die Notation mit eckigen Klammern (str[i]) irgendwie viel einfacher zu verstehen (für mich zumindest).
Ich hatte mir das, als ich anfing mit einem Projekt (alter C64-Zock) nicht so schwer vorgestellt mit c++. Und OO ist für einen alten 6502er wie mich sowieso nicht sehr einfach. Naja, die Fragen (Bugs) ergeben sich meistens erst zur Laufzeit. Das war früher auch schon so.

-
Badestrand schrieb:
Übrigens kann man bei 'int's den Test auf "!= 0" weglassen, das wird automatisch gemacht, wenn ein bool herauskommen soll
Würde ich aber trotzdem nicht machen, und zwar aus dem einfachen Grund, dass man nicht gleich sieht, dass auf 0 geprüft wird. Bei Zeigern gilt das selbe...
Bei mehreren Zuweisungen der selben Variable in einem Ausdruck (dazu gehören die Operatoren
++,--,+=,-=, etc.) sollte man vorsichtig sein, da das Resultat möglicherweise nicht definiert ist.
-
Da haschn zonga mit dem for gmacht und musch etzt echt luga dass me alz gaut.
-
Nanyuki schrieb:
Ist der Codeabschnitt aus einer Übung à la "finden Sie 10 Gründe, warum folgender Code nicht gut ist?".
Ein ähnlicher Gedanke kam mir auch. Verständlich wird die Anwesenheit dieses Stück Codes wenn man weiß, dass vom gleichem Autor auch ein 'Beginning C: From Novice to Professional (Beginning: from Novice to Professional)' existiert. Und für jede neue Version des VC-Studios schreibt er ein neues Buch

Für ein C++-Buch fände ich es angebrachter wenn man an dieser Stelle etwa ..
#include <algorithm> // remove #include <iostream> #include <ostream> #include <string> int main() { using namespace std; string str = "Text mit Space "; str.erase( remove( str.begin(), str.end(), ' ' ), str.end() ); // == eat spaces cout << "[" << str << "]" << endl; return 0; }.. vorfinden würde.
Zusammen mit einer schönen Erklärung warum das funktioniert.:xmas2: Werner