Wie konvertiere ich eine char
zu einer int
in C und C++?
Antworten
Zu viele Anzeigen?Das hängt davon ab, was Sie tun wollen:
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 */
zur Umwandlung des Zeichens '0' -> 0
, '1' -> 1
usw., können Sie schreiben
char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */
Erläuterung :
a - '0'
ist gleichbedeutend mit ((int)a) - ((int)'0')
was bedeutet, dass die Ascii-Werte der Zeichen voneinander subtrahiert werden. Da 0
kommt direkt vor 1
in der ascii-Tabelle (und so weiter bis 9
), die Differenz zwischen den beiden ergibt die Zahl, die das Zeichen a
vertritt.
Char ist nur eine 1-Byte-Ganzzahl. Der Typ char hat nichts Magisches an sich! Genauso wie Sie eine short einer int oder eine int einer long zuweisen können, können Sie eine char einer int zuweisen.
Ja, der Name des primitiven Datentyps ist zufällig "char", was darauf hindeutet, dass er nur Zeichen enthalten sollte. Aber in Wirklichkeit ist "char" nur eine schlechte Namenswahl, die jeden verwirrt, der versucht, die Sprache zu lernen. Ein besserer Name für diesen Datentyp ist int8_t, und Sie können diesen Namen stattdessen verwenden, wenn Ihr Compiler dem neuesten C-Standard folgt.
Obwohl Sie natürlich sollte Verwenden Sie den Typ char, wenn Sie Strings bearbeiten, da der Index der klassischen ASCII-Tabelle in 1 Byte passt. Sie könnte jedoch String-Handling mit regulären Ints als auch, obwohl es keinen praktischen Grund in der realen Welt, warum Sie jemals wollen, dass zu tun. Zum Beispiel funktioniert der folgende Code perfekt:
int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };
for(i=0; i<6; i++)
{
printf("%c", str[i]);
}
Sie müssen sich darüber im Klaren sein, dass Zeichen und Zeichenketten nur Zahlen sind, wie alles andere im Computer auch. Wenn Sie 'a' in den Quellcode schreiben, wird es in die Zahl 97 umgewandelt, die eine Integer-Konstante ist.
Wenn Sie also einen Ausdruck schreiben wie
char ch = '5';
ch = ch - '0';
dies ist eigentlich gleichbedeutend mit
char ch = (int)53;
ch = ch - (int)48;
die dann die Integer-Promotions der Sprache C durchläuft
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 eine Menge subtiler Dinge wie diese zwischen den Zeilen, wo char implizit als ein int behandelt wird.
(Diese Antwort bezieht sich auf die C++-Seite der Dinge, aber das Problem der Vorzeichenerweiterung besteht auch in C.)
Umgang mit allen drei char
Typen ( signed
, unsigned
y char
) ist heikler als es zunächst scheint. Werte im Bereich von 0 bis SCHAR_MAX
(das ist 127 für eine 8-Bit char
) sind einfach:
char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;
Aber, wenn somevalue
liegt außerhalb dieses Bereichs und geht nur über unsigned char
gibt Ihnen konsistente Ergebnisse für die "gleichen" char
Werte 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 bei der Verwendung von Funktionen aus ctype.h comme isupper
ou toupper
wegen der Vorzeichenerweiterung:
char c = negative_char; // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n); // Undefined behavior.
Beachten Sie, dass die Umwandlung durch int implizit ist; dies hat die gleiche UB:
char c = negative_char;
bool b = isupper(c);
Um dies zu beheben, gehen Sie durch unsigned char
was leicht durch Einpacken von ctype.h funktioniert durch safe_ctype :
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.
Das funktioniert, weil jede Funktion, die einen der drei Char-Typen annimmt, auch die beiden anderen Char-Typen annehmen kann. Dies führt zu zwei Funktionen, die jeden der Typen verarbeiten 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)
ergibt immer einen nicht-negativen Wert - auch wenn ein negativer Wert übergeben wird char
oder negativ signed char
- und chr
nimmt einen beliebigen Wert an ord
produziert und gibt genau dasselbe zurück char
.
In der Praxis würde ich wahrscheinlich einfach durch unsigned char
anstatt diese zu verwenden, aber sie verpacken den Cast kurz und bündig und bieten einen bequemen Platz, um eine Fehlerprüfung für int
-zu- char
und wäre kürzer und übersichtlicher, wenn man sie mehrmals in unmittelbarer Nähe verwenden muss.
- See previous answers
- Weitere Antworten anzeigen