2010-04-28 4 views
11

Ich verstehe nicht die Ergebnisse der folgenden C-Code.Warum bekomme ich dieses unerwartete Ergebnis mit atoi() in C?

main() 
{ 
    char s[] = "AAA"; 
    advanceString(s); 
} 

void advanceString(p[3]) 
{ 
    int val = atoi(p); 
    printf("The atoi val is %d\n",val); 
} 

Hier ist der atoi Wert wird als 0 gezeigt, aber ich kann den genauen Grund nicht herausgefunden. Nach meinem Verständnis sollte es die Summe der dezimalen Äquivalent jeder Werte im Array sein? Bitte korrigieren Sie mich, wenn ich falsch liege.

+3

Bitte fügen Sie den tatsächlichen Code ein, der kompiliert wird. –

+2

@Marcelo Ist das wirklich wichtig in diesem Fall? –

+2

Vielleicht, vielleicht nicht. Aber ist es wirklich so schwer, wenn man bedenkt, dass das OP bereits das Ergebnis des Programms gesehen hat? –

Antwort

12

Es versucht, die Zeichenfolge in eine Ganzzahl zu konvertieren. Da AAA nicht in eine ganze Zahl umgewandelt werden kann, ist der Wert 0. Versuchen Sie, 42 oder etwas zu geben.

Wenn keine gültige Konvertierung durchgeführt werden konnte, wird ein Nullwert zurückgegeben.

Siehe http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

53

atoi() eine String-Darstellung einer ganzen Zahl in seinem Wert umwandelt. Es wird keine beliebigen Zeichen in ihren Dezimalwert konvertieren. Zum Beispiel:

int main(void) 
{ 
    const char *string="12345"; 

    printf("The value of %s is %d\n", string, atoi(string)); 

    return 0; 
} 

Es gibt nichts in der Standard-C-Bibliothek, die „A“ bis 65 oder „Z“ bis 90 konvertiert, müssen Sie, dass Sie sich schreiben, die speziell für was auch immer charset Sie erwarten, wie Eingang.

Nun, da Sie wissen, was atoi() tut, benutzen Sie bitte nicht es mit numerischer Eingabe zu beschäftigen in was auch immer Sie kommen mit. Du solltest wirklich damit umgehen, dass dein Input nicht das ist, was du erwartest. Hmm, was passiert wenn ich 65 anstelle von A eingebe? Lehrer lieben es, Dinge zu brechen.

atoi() macht keine Fehlerprüfung überhaupt, was alles darauf beruht, beliebige Eingaben zerbrechlich zu konvertieren, bestenfalls. Verwenden Sie stattdessen strtol() (POSIX centric Beispiel):

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 

int main(void) 
{ 
    static const char *input ="123abc"; 
    char *garbage = NULL; 
    long value = 0; 

    errno = 0; 

    value = strtol(input, &garbage, 0); 

    switch (errno) { 
     case ERANGE: 
      printf("The data could not be represented.\n"); 
      return 1; 
     // host-specific (GNU/Linux in my case) 
     case EINVAL: 
      printf("Unsupported base/radix.\n"); 
      return 1; 
    } 

    printf("The value is %ld, leftover garbage in the string is %s\n", 
      // Again, host-specific, avoid trying to print NULL. 
      value, garbage == NULL ? "N/A" : garbage); 

    return 0; 
} 

Wenn Lauf, ergibt dies:

Der Wert ist 123, übrig gebliebene Müll in ist die Zeichenfolge abc

Wenn Sie Es ist nicht wichtig, den Müll zu speichern/zu untersuchen. Sie können das zweite Argument auf NULL setzen. Es besteht keine Notwendigkeit zu free(garbage). Wenn Sie 0 als drittes Argument übergeben, wird angenommen, dass die Eingabe der gewünschte Wert einer Dezimal-, Hex- oder Oktaldarstellung ist. Wenn Sie eine Radix von 10 benötigen, verwenden Sie 10 - es wird fehlschlagen, wenn die Eingabe nicht wie erwartet ist.

Sie würden auch den Rückgabewert für den maximalen und minimalen Wert überprüfen, den ein long int verarbeiten kann. Wenn jedoch beide zurückgegeben werden, um einen Fehler anzuzeigen, wird errno festgelegt. Eine Übung für den Leser besteht darin, *input von 123abc zu abc123 zu ändern.

Es ist wichtig, die Rückgabe zu überprüfen, da Ihr Beispiel zeigt, was passiert, wenn Sie dies nicht tun. AbcDeFg ist keine String-Repräsentation einer Ganzzahl, und Sie müssen in Ihrer Funktion damit umgehen.

Für Ihre Implementierung, die grundlegendste Rat, den ich dir geben kann wäre eine Reihe von Schaltern sein, so etwas wie:

// signed, since a return value of 0 is acceptable (NULL), -1 
// means failure 
int ascii_to_ascii_val(const char *in) 
{ 
    switch(in) { 
     // 64 other cases before 'A' 
     case 'A': 
      return 65; 
     // keep going from here 
     default: 
      return -1; // failure 

} 

.. dann laufen nur, dass in einer Schleife.

Oder füllen Sie ein Wörterbuch vor, das eine Suchfunktion (besser) enthalten könnte. Sie brauchen keine Hashes, nur einen Schlüssel -> Wert speichern, da Sie wissen, was es im Voraus enthalten wird, wo die Standard-ASCII-Zeichen Schlüssel sind, und ihre entsprechenden Bezeichner sind Werte.

+1

Sie können den [strerror] (http://en.wikipedia.org/wiki/Strerror) verwenden, um einen von Menschen lesbaren Text aus einem Fehlercode zu erhalten. – Tarantula

+0

während die Antwort richtig ist, würde es mehr helfen, wenn die Antwort dem OP sagen würde, wie man sein Problem löst. – Alex

+0

@Alex Glauben Sie es oder nicht, ich habe gerade Ihren Kommentar gesehen. Ein wenig bearbeitet :) –

6

Lesen Sie atoi() als a zu i (ASCII zu Integer).

atoi() konvertiert eine Zeichenfolge, die eine Dezimalzahl darstellt, in Ganzzahl.

char s[] = "42"; 
int num = atoi(s); //The value of num is 42. 
+2

+1, weil es alles enthält, was eine Antwort braucht ;-) – Frunsi

2

atoi erwartet ihr Argument eine Zeichenfolgendarstellung einer Dezimalzahl (Basis 10) Ganzzahl konstant zu sein; AAA ist keine gültige dezimale Ganzzahlkonstante, daher gibt atoi 0 zurück, weil es keine andere Möglichkeit gibt, um anzuzeigen, dass die Eingabe ungültig ist.

Beachten Sie, dass atoi bis zum ersten Zeichen konvertiert wird, das nicht Teil einer gültigen Ganzzahlkonstante ist; mit anderen Worten, "123" und "123w" werden beide in 123 umgewandelt.

Wie alle anderen auch sagen, verwenden Sie nicht atoi; Verwenden Sie stattdessen strtol.

Verwandte Themen