Verständnis, wie man atoi erstellt; Wie werden Charaktere verglichen?

8

Ich versuche, mein Verständnis von C ++, insbesondere Zeigerarithmetik, zu verbessern. Ich benutze Atoi ziemlich oft, aber ich habe selten darüber nachgedacht, wie es funktioniert. Wenn ich nachschlage, wie es gemacht wird, verstehe ich es meistens, aber da ist eine Sache, über die ich verwirrt bin.

Hier ist ein Beispiel für eine Lösung, die ich online gefunden habe:

%Vor%

Ich denke, der Hauptgrund, warum ich mich schwer damit beschäftigt habe, zu verstehen, wie es in der Vergangenheit getan wurde, ist der Vergleich der Charaktere. Die "while" -Anweisung sagt , während das Zeichen existiert, und das Zeichen ist kleiner als oder gleich 9, und es ist größer als -oder-gleich-0 dann tu was. Diese Aussage sagt mir zwei Dinge:

  1. Zeichen können logisch mit anderen Zeichen verglichen werden (aber was ist der zurückgegebene Wert?).

Bevor ich mir das angeschaut habe, nehme ich an, dass ich es unbewusst wusste, aber ich habe nie darüber nachgedacht, aber ein "5" -Zeichen ist "kleiner" als ein "6" -Zeichen, genauso wie 5 kleiner als 6 ist Sie können die Zeichen als Ganzzahlen vergleichen, im Wesentlichen (für diese Absicht).

  1. Irgendwie während (* sPtr) und * SPtr! = 0 sind unterschiedlich. Dies scheint mir offensichtlich, aber ich finde, dass ich es nicht in Worte fassen kann, was bedeutet, dass ich weiß, dass das wahr ist, aber ich verstehe nicht warum.

Bearbeiten: Ich habe keine Ahnung, was der * pStr - '0' Teil tun würde.

Jede Hilfe, die diese Beobachtungen sinnvoll macht, wäre sehr ... hilfreich! Vielen Dank!

    
Joshua 30.01.2013, 22:34
quelle

8 Antworten

2

Ein Zeichen in C wird einfach als ASCII-Wert dargestellt. Da alle Ziffern in ASCII fortlaufend sind (dh 0x30 == '0' und 0x39 == '9' mit allen anderen Ziffern dazwischen), können Sie bestimmen, ob ein Zeichen eine Ziffer ist, indem Sie einfach eine Bereichsüberprüfung durchführen und Sie kann den Wert der Ziffer durch Subtraktion von '0' erhalten.

    
nneonneo 30.01.2013, 22:38
quelle
4
  

solange das Zeichen existiert

Nein, nicht wirklich. Es steht "while character ist nicht 0 (oder ''''0'''' ). Grundsätzlich bedeutet ASCII-Zeichen 48 ein Ende einer" C "Zeichenkette. Da Sie nicht über das Ende eines Zeichenarrays hinausgehen wollen (und das genaue Länge ist nicht bekannt), jedes Zeichen wird auf '1' getestet.

  

Zeichen können logisch mit anderen Zeichen verglichen werden

Das stimmt. Character ist nichts anderes als eine Zahl, na ja, zumindest im ASCII-Format. In ASCII entspricht 'Z' beispielsweise einem Dezimalwert von while (*sPtr) , *sPtr != 0 ist 49, (nul) ist 90 (Sie können sich ASCII-Tabelle hier ). Also, yeah, Sie können Zeichen genau vergleichen, wie Sie ganze Zahlen vergleichen.

  

Irgendwie sind (nul) und %code% anders.

Nicht anders. Eine dezimale 0 ist ein spezielles ASCII-Symbol% ​​co_de%, das verwendet wird, um das Ende von "C" -String anzuzeigen, wie ich am Anfang erwähnt habe. Sie können %code% nicht sehen oder drucken, aber es ist da.

    
user405725 30.01.2013 22:40
quelle
3

Das * pStr - '0' konvertiert das Zeichen in seinen numerischen Wert '1' - '0' = 1 Die while-Schleife prüft, ob wir nicht am Ende der Zeichenfolge stehen und dass wir eine gültige Ziffer haben.

    
Mark PM 30.01.2013 22:37
quelle
0

Beachten Sie, dass die angegebene Implementierung von atoi nicht vollständig ist. Real atoi kann negative Werte verarbeiten.

  

Irgendwie während (* sPtr) und * sPtr! = 0 anders sind.

Diese beiden Ausdrücke sind gleich. Bei Verwendung als Bedingung wird *sPtr als wahr betrachtet, wenn der an der Adresse sPtr gespeicherte Wert nicht Null ist, und *sPtr != 0 ist wahr, wenn der an der Adresse sPtr gespeicherte Wert nicht Null ist. Der Unterschied besteht darin, dass der zweite Ausdruck, wenn er an einer anderen Stelle verwendet wird, als wahr oder falsch ausgewertet wird, aber der erste Wert wird als gespeicherter Wert ausgewertet.

    
Josef Kufner 30.01.2013 22:45
quelle
0

Zeichenketten im C-Stil sind nullterminiert .

Daher:

%Vor%

Dies testet:

  • *pStr , die das Ende der Zeichenfolge noch nicht erreicht hat und entspricht dem Schreiben von *pStr != 0 (Anmerkung ohne das einfache Anführungszeichen, ASCII-Wert 0 oder NUL ).
  • *pStr >= '0' && *pStr <= '9' (vielleicht logischer), dass das Zeichen bei *pStr im Bereich '0' (ASCII-Wert 48 ) bis '9' (ASCII-Wert 57 ) liegt, also eine Ziffer .
Johnsyweb 30.01.2013 22:43
quelle
0

Die Darstellung von '0' im Speicher os 0x30 und die Darstellung von '9' ist 0x39 . Dies sieht der Computer, und wenn er sie mit logischen Operatoren vergleicht, verwendet er diese Werte. Das Null-Beendigungszeichen wird als 0x00 dargestellt (alias Null). Der Schlüssel hier ist, dass chars genau wie jede andere int der Maschine ist.

Daher sagt die while Aussage:

  

Während das Zeichen, das wir untersuchen, gültig ist (aka NICHT null und daher KEIN Nullterminator) und sein Wert (wie die Maschine es sieht) kleiner als 0x39 ist und sein Wert größer als 0x30 ist, fahre fort.

Der Rumpf der while -Schleife berechnet dann den geeigneten Wert, der dem Akkumulator basierend auf der Position der ganzen Zahl in der Zeichenfolge hinzugefügt wird. Es erhöht dann den Zeiger und geht wieder. Sobald es fertig ist, gibt es den akkumulierten Wert zurück.

    
Ephemera 30.01.2013 22:51
quelle
0

Dieser Codeabschnitt verwendet ascii-Werte, um eine ganzzahlige Zahl seines Alpha-Äquivalents zu akkumulieren.

In Bezug auf Ihre erste nummerierte Kugel scheint es ziemlich trivial zu sein, dass das Ergebnis beim Booleschen Vergleich das Ergebnis ist. Obwohl ich das Gefühl habe, du wolltest fragen, ob der Compiler tatsächlich "Charaktere" versteht. Zu meinem Verständnis, obwohl dieser Vergleich mit den Ascii-Werten der Zeichen erfolgt. ein & lt; b wird interpretiert als (97 & lt; 98). (Beachten Sie, dass auch leicht zu sehen ist, dass ASCII-Werte verwendet werden, wenn Sie "a" und "A" vergleichen, da "A" kleiner ist als "a")

In Bezug auf Ihre zweite Aufzählung scheint es, dass die while-Schleife überprüft, dass es tatsächlich einen zugewiesenen Wert gibt, der nicht NULL ist (ascii-Wert 0). Der UND-Operator erzeugt FALSCH, sobald eine falsche Anweisung auftritt, so dass Sie keinen Vergleich für ein NULL-Zeichen ausführen. Was den Rest der while-Schleife anbelangt, führt sie einen Ascii-Vergleich durch, wie ich bereits in Bullet 1 erwähnt habe. Sie prüft nur, ob das angegebene Zeichen einem Ascii-Wert entspricht, der mit einer Zahl in Zusammenhang steht. d.h. zwischen "0" und "9" (oder ascii: zwischen 48 und 57)

LETZTLICH der (* ptr-'0 ') ist meiner Meinung nach der interessanteste Teil. Diese Anweisung gibt eine Ganzzahl zwischen 0 und 9 einschließlich zurück. Wenn Sie sich ein Ascii-Diagramm ansehen, werden Sie feststellen, dass die Zahlen 0 bis 9 nebeneinander liegen. Stellen Sie sich '3' - '0' vor, was 51 - 48 ist und 3 ergibt! : D Also vereinfacht es die Subtraktion von ASCII und gibt den entsprechenden ganzzahligen Wert zurück. : D

Prost, und ich hoffe, das erklärt ein bisschen

    
TopGunCoder 30.01.2013 23:04
quelle
0

Lasst es uns aufschlüsseln:

if ( pStr )

Wenn Sie atoi einen Null-Zeiger übergeben, wird pStr 0x00 - und dies wird falsch sein. Sonst haben wir etwas zu analysieren.

while ( *pStr && *pStr <= '9' && *pStr >= '0' )

Ok, hier gibt es eine Menge Dinge. *pStr bedeutet, dass wir prüfen, ob der Wert, auf den pStr zeigt, 0x00 ist oder nicht. Wenn Sie sich eine ASCII-Tabelle ansehen, ist das ASCII für 0x00 'null' und in C / C ++ ist die Konvention, dass Strings null terminiert sind (im Gegensatz zu Pascal- und Java-Strings, die Ihnen sagen, dass ihre Länge dann so viele hat) Figuren). Wenn also *pStr zu false führt, ist unsere Zeichenfolge zu Ende und wir sollten aufhören.

*pStr <= '9' && *pStr >= '0' funktioniert, weil die Werte für die ASCII-Zeichen '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' zusammenhängend sind - '0 'ist 0x30 und' 9 'ist zum Beispiel 0x39 . Wenn also pStr auf einen Wert zeigt, der außerhalb dieses Bereichs liegt, dann analysieren wir keine Ganzzahl und sollten aufhören.

iRetVal = (iRetVal * 10) + (*pStr - '0');

Da die Eigenschaften von ASCII-Ziffern zusammenhängend im Speicher sind, wird *pStr - '0' , wenn wir wissen, eine Zahl haben, auf ihren numerischen Wert - 0 für '0' ( 0x30 - 0x30 ), 1 für ' 1 '( 0x31 - 0x30 ) ... 9 für' 9 '. Also verschieben wir unsere Nummer und schieben den neuen Platz ein.

pStr++;

Durch Hinzufügen von eins zum Zeiger zeigt der Zeiger auf die nächste Adresse im Speicher - das nächste Zeichen in der Zeichenfolge, die wir in eine Ganzzahl konvertieren.

Beachten Sie, dass diese Funktion versagt, wenn die Zeichenfolge nicht null-terminiert ist, keine Zahlen enthält (z. B. "-") oder in keiner Weise ein ASCII-Zeichen ist. Es ist keine Magie, es beruht nur darauf, dass diese Dinge wahr sind.

    
Patashu 30.01.2013 23:27
quelle

Tags und Links