Konvertieren Sie char in int in C und C ++


401

Wie konvertiere ich ein charin ein intin C und C ++?


1
@ Matt: Es wäre eine gute Idee, konkreter zu sein. Wenn Sie nach einer Verallgemeinerung fragen, werden nur allgemeine Antworten eingeladen, die für Ihre Aufgabe nicht zutreffend oder sogar korrekt sind. Denken Sie daran, wenn Sie fragen müssen, wissen Sie wahrscheinlich nicht genug, um richtig zu verallgemeinern.
Prost und hth. - Alf

@Alf P. Steinbach: Die ursprüngliche Frage war vage, welche Sprache. Mit Schlüsselwörtern cund c++halte ich Antworten für beide Sprachen für vernünftig.
Matt Joiner

8
Aufgrund meiner umfangreichen Erfahrung in anderen technischen Foren ist meine Intuition, dass das OP wirklich bedeutet: "Wie nehme ich die Textdarstellung einer Zahl (in Basis 10) und konvertiere sie in die entsprechende Zahl?" Im Allgemeinen haben C- und C ++ - Neulinge normalerweise unglaublich unscharfe Vorstellungen darüber, wie Text in diesen Sprachen funktioniert und was er charwirklich bedeutet.
Karl Knechtel

3
@KarlKnechtel: Wenn das stimmt (ich gebe es ungefähr 50/50, da viele frühe Tutorials auch dazu ermutigen, ASCII-Werte aus Zeichen herauszuholen, obwohl ASCII nicht den gesamten Bereich abdeckt), muss das OP Klarheit schaffen - aber das ist ein Betrug von stackoverflow.com/questions/439573/… .
Fred Nurk

3
Das OP hatte drei Stunden Zeit, um diese Frage zu klären, und versäumte es, dies zu tun. So wie es ist, gibt es keine Möglichkeit zu wissen, was tatsächlich gefragt wird. Zum Schließen gewählt.
sbi

Antworten:


551

Kommt darauf an, was du machen willst:

Um den Wert als ASCII-Code zu lesen, können Sie schreiben

char a = 'a';
int ia = (int)a; 
/* note that the int cast is not necessary -- int ia = a would suffice */

das Zeichen zu konvertieren '0' -> 0, '1' -> 1etc, können Sie schreiben

char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */

Erklärung :
a - '0'ist äquivalent zu ((int)a) - ((int)'0'), was bedeutet, dass die ASCII-Werte der Zeichen voneinander subtrahiert werden. Da in der ASCII-Tabelle 0direkt davor steht 1(und so weiter bis 9), gibt die Differenz zwischen den beiden die Zahl an, die das Zeichen adarstellt.


14
ia = (a - '0')% 48;
Kshitij Banerjee

@KshitijBanerjee Das ist aus zwei Gründen keine gute Idee: Es gibt Ihnen eine negative Zahl für ASCII-Zeichen vor '0' (wie &-> -10) und es gibt Zahlen größer als 10 (wie x-> 26)
SheetJS

2
int ia = a - '0' - das ist was du brauchst
Funk

5
@ kevin001 Wenn Sie das Zeichen in int konvertieren möchten und ein Zeichen '1'eine ASCII-Zahl enthält, die dies nicht ist 1, müssen Sie den Versatz entfernen '0', um ihn neu auszurichten und von 0 bis 9 zu zählen. Die fortlaufenden Zahlen 1-9 sind in der ASCII-Ganzzahl benachbart.
krisdestruction

Keine Besetzung erforderlich / erwünscht
Craig Estey

97

Nun, im ASCII-Code beginnen die Zahlen (Ziffern) bei 48 . Alles was Sie tun müssen ist:

int x = (int)character - 48;

19
@chad: Nicht nur besser lesbar, sondern auch portabler. C und C ++ garantieren keine ASCII-Darstellung, aber sie garantieren, dass unabhängig von der verwendeten Darstellung die Darstellungen der 10 Dezimalstellen zusammenhängend und in numerischer Reihenfolge sind.
Ben Voigt

Das einzige , was ich geändert hätte 48 drehen, was ein wenig „magischen“ scheint'0'
ArielGro

59

C und C ++ fördern Typen immer mindestens int. Darüber hinaus sind Zeichenliterale intin C und charin C ++ vom Typ .

Sie können einen charTyp einfach konvertieren, indem Sie ihn einem zuweisen int.

char c = 'a'; // narrowing on C
int a = c;

3
Sie könnten die auch unter-schätzen verwenden schmerzlich einstellige operator+() für diesen Zweck.
Cubbi

24
-1 Die Antwort ist falsch für die einzig sinnvolle Interpretation der Frage. Dieser (Code int a = c;) behält alle negativen Werte bei, mit denen C-Standardbibliotheksfunktionen nicht umgehen können. Die Funktionen der C-Standardbibliothek legen den Standard für die Behandlung von charWerten als fest int.
Prost und hth. - Alf

6
@ Matt: Ich halte die Abstimmung. Ich würde es wenn möglich stärken! Die von Ihnen und anderen angenommene Frageninterpretation ist nicht aussagekräftig, weil sie zu trivial ist und weil es für die spezielle Typenkombination des OP ein nicht so triviales, sehr wichtiges praktisches Problem gibt. Der Rat, den Sie geben, ist für den Anfänger direkt gefährlich . Dies führt höchstwahrscheinlich zu einem undefinierten Verhalten für ihre Programme, die C-Standard-Bibliothekszeichenklassifizierungsfunktionen verwenden. Re ref. Auf die Antwort von @ Sayam hat er diese Antwort gelöscht.
Prost und hth. - Alf

3
-1 für falsch: isupper () hat undefinierte Ergebnisse, wenn ein 1252-Highbit-Zeichen übergeben wird.
Chris Becke

1
Was meinst du mit "immer fördern"? Werte werden bei impliziten Konvertierungen, bei der Übergabe bestimmter Parametertypen (z. B. an eine varargs-Funktion) und wenn ein Operator seine Operanden kompatibel machen muss, heraufgestuft. Aber es gibt sicherlich Zeiten, in denen ein Wert nicht heraufgestuft wird (z. B. wenn ich ein Zeichen an eine Funktion übergebe, die ein Zeichen erwartet), sonst hätten wir keine Typen, die kleiner als ein int sind.
Adrian McCarthy

31

char ist nur eine 1-Byte-Ganzzahl. Es gibt nichts Magisches mit dem Char-Typ! So wie Sie einem Int ein Short oder einem Long ein Int zuweisen können, können Sie einem Int ein Zeichen zuweisen.

Ja, der Name des primitiven Datentyps lautet zufällig "char", was unterstellt, dass er nur Zeichen enthalten sollte. Aber in Wirklichkeit ist "char" nur eine schlechte Wahl, um jeden zu verwirren, der versucht, die Sprache zu lernen. Ein besserer Name dafür ist int8_t, und Sie können diesen Namen stattdessen verwenden, wenn Ihr Compiler dem neuesten C-Standard folgt.

Natürlich sollten Sie bei der Zeichenfolgenbehandlung den Typ char verwenden, da der Index der klassischen ASCII-Tabelle in 1 Byte passt. Sie können das String-Handling jedoch auch mit regulären Ints durchführen, obwohl es in der realen Welt keinen praktischen Grund gibt, warum Sie dies jemals tun möchten. Der folgende Code funktioniert beispielsweise einwandfrei:

  int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };

  for(i=0; i<6; i++)
  {
    printf("%c", str[i]);
  }

Sie müssen erkennen, dass Zeichen und Zeichenfolgen wie alles andere im Computer nur Zahlen sind. Wenn Sie 'a' in den Quellcode schreiben, wird es in die Zahl 97 vorverarbeitet, die eine ganzzahlige Konstante ist.

Also, wenn Sie einen Ausdruck wie schreiben

char ch = '5';
ch = ch - '0';

das ist eigentlich gleichbedeutend mit

char ch = (int)53;
ch = ch - (int)48;

Das geht dann durch die C-Sprache Integer Promotions

ch = (int)ch - (int)48;

und dann auf ein Zeichen gekürzt, um dem Ergebnistyp zu entsprechen

ch = (char)( (int)ch - (int)48 );

Es gibt viele subtile Dinge wie diese zwischen den Zeilen, in denen char implizit als int behandelt wird.


Da die Frage nicht mit einem Tag versehen ist ascii, sollten Sie keine bestimmte Codierung annehmen. Die Einstellung chargleich int8_tist falsch, weil es genauso wahrscheinlich sein könnte uint8_toder uint24_t.
Roland Illig

1
@RolandIllig Nein, a charist immer 1 Byte und wenn die Typen int8_t/ uint8_tauf dem gegebenen System existieren (was sehr wahrscheinlich ist), können sie das Ergebnis von a anpassen char, da es dann 8 Bits sind. Auf hochexotischen Systemen wie verschiedenen veralteten DSPs charwerden 16 Bit und die uint8_tnicht existieren. Das Schreiben von Code für die Kompatibilität mit veralteten DSPs ist Unsinn, ebenso wie das Schreiben für die Kompatibilität mit den eigenen Komplement- oder Vorzeichen- und Magnitudensystemen. Riesige Zeitverschwendung, da solche Systeme in der realen Welt kaum existieren.
Lundin

18

(Diese Antwort befasst sich mit der C ++ - Seite, aber das Problem mit der Zeichenerweiterung besteht auch in C.)

Umgang mit allen drei charTypen ( signed, unsigned, und char) ist empfindlicher als es zunächst erscheint. Werte im Bereich von 0 bis SCHAR_MAX(was 127 für ein 8-Bit ist char) sind einfach:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;

Wenn Sie sich somevaluejedoch außerhalb dieses Bereichs befinden, erhalten Sie nur unsigned charkonsistente Ergebnisse für die "gleichen" charWerte in allen drei Typen:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.

Dies ist wichtig, wenn Funktionen von ctype.h verwendet werden , z. B. isupperoder toupperaufgrund der Vorzeichenerweiterung:

char c = negative_char;  // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n);  // Undefined behavior.

Beachten Sie, dass die Konvertierung durch int implizit ist. das hat die gleiche UB:

char c = negative_char;
bool b = isupper(c);

Um dies zu beheben, gehen Sie durch unsigned char, indem Sie die Funktionen von ctype.h einfach über safe_ctype umschließen :

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c);  // No UB.

std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.

Dies funktioniert, da jede Funktion, die einen der drei Zeichentypen verwendet, auch die anderen beiden Zeichentypen verwenden kann. Es führt zu zwei Funktionen, die jeden der Typen handhaben können:

int ord(char c) { return (unsigned char)c; }
char chr(int n) {
  assert(0 <= n);  // Or other error-/sanity-checking.
  assert(n <= UCHAR_MAX);
  return (unsigned char)n;
}

// Ord and chr are named to match similar functions in other languages
// and libraries.

ord(c)gibt Ihnen immer einen nicht negativen Wert - auch wenn ein negativer charoder negativer Wert übergeben wird signed char- und chrnimmt einen beliebigen Wert, ordder genau denselben erzeugt und zurückgibt char.

In der Praxis würde ich diese wahrscheinlich nur durchgießen , unsigned charanstatt sie zu verwenden, aber sie wickeln die Besetzung kurz und bündig ein, bieten einen praktischen Ort zum Hinzufügen von Fehlerprüfungen für int-to- charund wären kürzer und klarer, wenn Sie sie mehrmals verwenden müssen in unmittelbarer Nähe.



7

Es hängt davon ab, was Sie unter "konvertieren" verstehen.

Wenn Sie eine Reihe von Zeichen haben, die eine Ganzzahl darstellen, wie "123456", gibt es in C zwei typische Möglichkeiten, dies zu tun: Verwenden Sie eine Spezialkonvertierung wie atoi () oder strtol () oder den Allzweck- sscanf () . C ++ (was wirklich eine andere Sprache ist, die sich als Upgrade tarnt) fügt einen dritten Stringstream hinzu.

Wenn Sie meinen, dass das genaue Bitmuster in einer Ihrer intVariablen als behandelt werden charsoll, ist dies einfacher. In C sind die verschiedenen Ganzzahltypen eher ein Geisteszustand als tatsächliche separate "Typen". Verwenden Sie es einfach dort, wo Sie chargefragt werden, und Sie sollten in Ordnung sein. Möglicherweise benötigen Sie eine explizite Konvertierung, damit der Compiler gelegentlich aufhört zu jammern. Sie sollten jedoch nur zusätzliche Bits nach 256 löschen.


6

Ich habe absolut nullFähigkeiten in C, aber für eine einfache Analyse:

char* something = "123456";

int number = parseInt(something);

... das hat bei mir funktioniert:

int parseInt(char* chars)
{
    int sum = 0;
    int len = strlen(chars);
    for (int x = 0; x < len; x++)
    {
        int n = chars[len - (x + 1)] - '0';
        sum = sum + powInt(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}

Dieser Code ruft schnell undefiniertes Verhalten hervor und eignet sich daher nicht zum Kopieren und Einfügen. (int Überlauf)
Roland Illig

4

Vermutlich möchten Sie diese Konvertierung für die Verwendung von Funktionen aus der C-Standardbibliothek.

In diesem Fall do (C ++ - Syntax)

typedef unsigned char UChar;

char myCppFunc( char c )
{
    return char( someCFunc( UChar( c ) ) );
}

Der Ausdruck wird in UChar( c )konvertiert unsigned char, um negative Werte zu entfernen, die mit Ausnahme von EOF von den C-Funktionen nicht unterstützt werden.

Dann wird das Ergebnis dieses Ausdrucks als tatsächliches Argument für ein intformales Argument verwendet. Wo Sie automatisch befördert werden int. Sie können diesen letzten Schritt auch explizit explizit schreiben int( UChar( c ) ), aber ich persönlich finde das zu ausführlich.

Prost & hth.,


0

Ich hatte Probleme beim Konvertieren eines char-Arrays wie "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"in seinen tatsächlichen ganzzahligen Wert, der durch "7C" als ein hexadezimaler Wert dargestellt werden kann. Nachdem ich um Hilfe gekreuzt hatte, schuf ich dies und dachte, es wäre cool, es zu teilen.

Dies trennt die Zeichenfolge in ihre richtigen ganzen Zahlen und kann für mehr Personen als nur mich hilfreich sein;)

unsigned int* char2int(char *a, int len)
{
    int i,u;
    unsigned int *val = malloc(len*sizeof(unsigned long));

    for(i=0,u=0;i<len;i++){
        if(i%2==0){
            if(a[i] <= 57)
                val[u] = (a[i]-50)<<4;
            else
                val[u] = (a[i]-55)<<4;
        }
        else{
            if(a[i] <= 57)
                val[u] += (a[i]-50);
            else
                val[u] += (a[i]-55);
            u++;
        }
    }
    return val;
}

Ich hoffe es hilft!


Haben Sie diesen Code jemals getestet? Die 50 sollte eine 48 sein, die 55 funktioniert nur für ASCII-Großbuchstaben, während Ihr Beispiel Kleinbuchstaben enthält.
Roland Illig

0

Für char oder short to int müssen Sie nur den Wert zuweisen.

char ch = 16;
int in = ch;

Gleiches gilt für int64.

long long lo = ch;

Alle Werte sind 16.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.