String To Long
-
Hallo zusammen,
ich habe hier eine kleine Beispielfunktion aus meinem Lehrbuch, die einen String in long konvertiert. Dazu habe ich einige Fragen:long StrToLong(string str) { register int i = 0; long vz = 1, zahl = 0; //for(i=0;i<str.size() && isspace(str[i]); ++i) // ; diese Zeilen kann man doch weglassen if (i < str.size()) { if( str[i] == '+' ) {vz = 1; ++i;} if( str[i] == '-' ) {vz = -1; ++i;} } for(; i < str.size() && isdigit(str[i]); ++i) zahl = zahl * 10 + (str[i] - '0'); return vz * zahl; }1.) Die zwei kommentierten Zeilen sind im ursprünglichen Programm nicht kommentiert, sondern sind dazu da um "Führende Zwischenraumzeichen zu überlesen". Was soll das bringen. Wenn ich sie kommentiere, dann funktioniert das Programm auch.
2.) Bei der zweiten for - Schleife liegt das eigentliche Problem. Die erste Grenze ist die Länge des Strings, was für mich einleuchtend ist. Soll "&& isdigit(str[i])" sichergehen,dass nur bis dahin gezählt wird, wo auch nur eine Zahl vorhanden ist und kein Buchstabe? Ich dachte, dass "isdigit" ein Makro ist, dass einen bool Wert zurück gibt. Darauf deutet ja auch schon der Name an. Welchen Wert gibt sie denn zurück?
3.) Eigentlich ist das doch keine richtige Typumwandlung, da auch hier von der impliziten Typumwandlung Gebrauch gemacht wird, oder? In der Anweisung der zweiten for-Schleife
4.) was soll das -'0' in der Anweisung der zweiten for-Schleife?
Vielen Dank für eure Hilfe
lg, freakC++
-
freakC++ schrieb:
1.) Die zwei kommentierten Zeilen sind im ursprünglichen Programm nicht kommentiert, sondern sind dazu da um "Führende Zwischenraumzeichen zu überlesen". Was soll das bringen. Wenn ich sie kommentiere, dann funktioniert das Programm auch.
Dort werden führende Leerzeichen übersprungen. Stell deinem String mal ein paar Leerzeichen voran und lass dein Programm einmal mit den beiden Zeilen und einmal ohne laufen. Dann wirst du den Unterschied sehen.
2.) Bei der zweiten for - Schleife liegt das eigentliche Problem. Die erste Grenze ist die Länge des Strings, was für mich einleuchtend ist. Soll "&& isdigit(str[i])" sichergehen,dass nur bis dahin gezählt wird, wo auch nur eine Zahl vorhanden ist und kein Buchstabe? Ich dachte, dass "isdigit" ein Makro ist, dass einen bool Wert zurück gibt. Darauf deutet ja auch schon der Name an. Welchen Wert gibt sie denn zurück?
Wenn der Name nicht schon sprechend genug ist, schau in eine Referenz, beispielsweise cplusplus.com. Da kann man lesen:
int isdigit ( int c );
Checks if parameter c is a decimal digit character.
Decimal digits are any of: 0 1 2 3 4 5 6 7 8 9
Was das soll, hast du korrekt erkannt: Es soll festgestell werden, wo die Zahl zu Ende ist.
3.) Eigentlich ist das doch keine richtige Typumwandlung, da auch hier von der impliziten Typumwandlung Gebrauch gemacht wird, oder? In der Anweisung der zweiten for-Schleife
Vorher hast du einen String, hinterher einen long. Wo ist dein Problem?
4.) was soll das -'0' in der Anweisung der zweiten for-Schleife?
In der ASCII Zeichentabelle kommen die einzelnen Ziffern nicht gleich am Anfang. Wenn man daher einzelne Zeichen als arithmetische Ziffern auffassen will, muss man den Wert der ersten Ziffer abziehen.
Verstanden oder ist mehr Erklärung nötig?Und allgemein: Du schreibst, dass dies aus einem Lehrbuch ist, deshalb nehme ich an, man soll den Algorithmus nachvollziehen. Das ist sicherlich sehr nützlich und das solltest du auch tun. Ich will aber noch anmerken, dass C++ natürlich auch Sprachelemente bietet, die diese Umwandlung schon vollautomatisch durchführen (siehe std::stringstream).
-
Was auskommentiert wurde kann Leerzeichen vor der brauchbaren Eingabe abfangen.
Der Rest ist keine gute Lösung. Die Subtraktion mit '0' basiert auf der ASCII-Zeichentabelle, was aber sehr fehleranfällig ist.
Man sollte anstatt dessen z.B. atol benutzen: http://www.cplusplus.com/reference/clibrary/cstdlib/atol/
-
Hallo,
ich verstehe diese Auskommentierung immer noch nicht. Auch wenn ich Leerzeichen der Zahl voranstelle, wird das Programm korrekt ausgeführt.
Man kann ja sehen, dass die Schleife keine Anweisung besitzt, keine Variablen ändert und daher nur eine Verzögerung des Programms
darstellt.Ich meinte eigentlich, dass hier ja nur von der impliziten Typumwandlung Gebrauch gemacht wird. Diese Methode wandelt den Typ also nur um, weil
sie sich auf die automatische Umwandlung stützt.Vielen Dank
lg, freakC++
-
freakC++ schrieb:
Man kann ja sehen, dass die Schleife keine Anweisung besitzt, keine Variablen ändert und daher nur eine Verzögerung des Programms darstellt.
Die Schleife ändert sehr wohl eine Variable nämlich
i:register int i = 0; /* ... */ for(i=0;i<str.size() && isspace(str[i]); ++i) ; /* ... */
-
freakC++ schrieb:
Ich meinte eigentlich, dass hier ja nur von der impliziten Typumwandlung Gebrauch gemacht wird. Diese Methode wandelt den Typ also nur um, weil sie sich auf die automatische Umwandlung stützt.
In der zweiten for-Schleife wird gerechnet, da kannst du doch nicht von impliziter Typumwandung sprechen. Wo wäre denn deiner Meinung nach eine implizite Umwandlung, auf die sich dieser Algorithmus stützt?
Stefan.
-
teste mal _-666 ( wobei _ Leerzeichen entspricht )
-
Wenn ich -666 inklusive Leerzeichen eingebe und beide Versionen damit teste (also einmal mit Kommentar und einam l nicht), dann kommt bei beiden das gleiche Ergebnis.
Wenn ich str[i] einem long Wert zuweise, dann muss doch eine Typumwandlung erfolgen, denn str ist doch ein String. Was verstehe ich da falsch?
Vielen Dank
lg, freakC++
-
freakC++ schrieb:
Wenn ich str[i] einem long Wert zuweise, dann muss doch eine Typumwandlung erfolgen, denn str ist doch ein String. Was verstehe ich da falsch?
str ist zwar ein string, str[i] aber nicht - das ist ein char. Und somit wären wir wieder bei dem Thema, dass man solche Sachen in wenigen Sekunden in einer Referenz nachschlagen kann.
-
freakC++ schrieb:
Wenn ich -666 inklusive Leerzeichen eingebe und beide Versionen damit teste (also einmal mit Kommentar und einam l nicht), dann kommt bei beiden das gleiche Ergebnis.
Dann sind die Leerzeichen bereits vorher aus dem String entfernt worden.
Wenn ich str[i] einem long Wert zuweise, dann muss doch eine Typumwandlung erfolgen, denn str ist doch ein String. Was verstehe ich da falsch?
Der string::operator[] liefert ein char, was bei einer Zuweisung auf eine Variable vom Typ long automatisch konvertiert wird.
-
Und da ich schon ahne, was die nächste Frage sein wird: char ist ein integraler Datentyp (das heißt, verhält sich wie eine Ganzzahl). Man kann damit genauso rechnen wie mit int. Und genau das ist es, was bei dem Algorithmus passiert.
zahl * 10 + (str[i] - '0');Zuerst wird von dem Wert von str[i] der Wert des chars '0' abgezogen. Die Idee dahinter ist, dass in der Zeichentabelle die Ziffern als 0123456789 angeordnet sind. Daher hat das Ergebnis der Subtraktion hinterher Werte zwischen 0 und 9. Danach wird das Ergebnis dann einem Stellenwertsystem entsprechend der Variablen zahl hinzugefügt.
Wie aber schon angemerkt wurde, muss man sich dazu auf eben genau diese Eigenschaft der Zeichentabelle verlassen können. Wenn man wirklich portabel programmieren möchte, sollte man daher die fertigen Funktionen zur Umwandlung benutzen oder etwas programmieren, dass diese Annahme nicht zwangsläufig macht.
Trotzdem ist die Funktion sehr gut als Anschauungsmaterial geeignet.
-
Hallo,
achso...jetzt verstehe ich! Tja, SeppJ...du scheinst hellseherische Kräfte zu besitzen. Danke für die Antwort im Voraus!
Erst die Antwort dann die Frage...interessante Reihenfolge![edit] Das hätte aber sogar ich gewusst

Vielen Dank --> ihr seit toll
lg, freakC++
-
SeppJ schrieb:
Wie aber schon angemerkt wurde, muss man sich dazu auf eben genau diese Eigenschaft der Zeichentabelle verlassen können. Wenn man wirklich portabel programmieren möchte, sollte man daher die fertigen Funktionen zur Umwandlung benutzen oder etwas programmieren, dass diese Annahme nicht zwangsläufig macht.
Man kann sich drauf verlassen.