@ 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.
@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:
@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.
Sie könnten die auch unter-schätzen verwenden schmerzlich einstelligeoperator+() 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;signedchar sc = c;unsignedchar 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;signedchar sc = c;unsignedchar uc = c;// Might not be true: int(c) == int(sc) and int(c) == int(uc).int nc =(unsignedchar)c;int nsc =(unsignedchar)sc;int nuc =(unsignedchar)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(unsignedchar 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(unsignedchar)c;}char chr(int n){assert(0<= n);// Or other error-/sanity-checking.assert(n <= UCHAR_MAX);return(unsignedchar)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.
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.
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)
typedefunsignedcharUChar;char myCppFunc(char c ){returnchar( 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.
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;)
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.
Dies ist undefiniertes Verhalten. Wenn Sie die Adresse einer char-Variablen verwenden, erhalten Sie ein char *, aber keinen C-String, was atoi erwartet.
c
undc++
halte ich Antworten für beide Sprachen für vernünftig.char
wirklich bedeutet.Antworten:
Kommt darauf an, was du machen willst:
Um den Wert als ASCII-Code zu lesen, können Sie schreiben
das Zeichen zu konvertieren
'0' -> 0
,'1' -> 1
etc, können Sie schreibenErklä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-Tabelle0
direkt davor steht1
(und so weiter bis9
), gibt die Differenz zwischen den beiden die Zahl an, die das Zeichena
darstellt.quelle
&
-> -10) und es gibt Zahlen größer als 10 (wiex
-> 26)'1'
eine ASCII-Zahl enthält, die dies nicht ist1
, 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.Nun, im ASCII-Code beginnen die Zahlen (Ziffern) bei 48 . Alles was Sie tun müssen ist:
quelle
'0'
C und C ++ fördern Typen immer mindestens
int
. Darüber hinaus sind Zeichenliteraleint
in C undchar
in C ++ vom Typ .Sie können einen
char
Typ einfach konvertieren, indem Sie ihn einem zuweisenint
.quelle
operator+()
für diesen Zweck.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 vonchar
Werten als festint
.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:
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
das ist eigentlich gleichbedeutend mit
Das geht dann durch die C-Sprache Integer Promotions
und dann auf ein Zeichen gekürzt, um dem Ergebnistyp zu entsprechen
Es gibt viele subtile Dinge wie diese zwischen den Zeilen, in denen char implizit als int behandelt wird.
quelle
ascii
, sollten Sie keine bestimmte Codierung annehmen. Die Einstellungchar
gleichint8_t
ist falsch, weil es genauso wahrscheinlich sein könnteuint8_t
oderuint24_t
.char
ist immer 1 Byte und wenn die Typenint8_t
/uint8_t
auf dem gegebenen System existieren (was sehr wahrscheinlich ist), können sie das Ergebnis von a anpassenchar
, da es dann 8 Bits sind. Auf hochexotischen Systemen wie verschiedenen veralteten DSPschar
werden 16 Bit und dieuint8_t
nicht 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.(Diese Antwort befasst sich mit der C ++ - Seite, aber das Problem mit der Zeichenerweiterung besteht auch in C.)
Umgang mit allen drei
char
Typen (signed
,unsigned
, undchar
) ist empfindlicher als es zunächst erscheint. Werte im Bereich von 0 bisSCHAR_MAX
(was 127 für ein 8-Bit istchar
) sind einfach:Wenn Sie sich
somevalue
jedoch außerhalb dieses Bereichs befinden, erhalten Sie nurunsigned char
konsistente Ergebnisse für die "gleichen"char
Werte in allen drei Typen:Dies ist wichtig, wenn Funktionen von ctype.h verwendet werden , z. B.
isupper
odertoupper
aufgrund der Vorzeichenerweiterung:Beachten Sie, dass die Konvertierung durch int implizit ist. das hat die gleiche UB:
Um dies zu beheben, gehen Sie durch
unsigned char
, indem Sie die Funktionen von ctype.h einfach über safe_ctype umschließen :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:
ord(c)
gibt Ihnen immer einen nicht negativen Wert - auch wenn ein negativerchar
oder negativer Wert übergeben wirdsigned char
- undchr
nimmt einen beliebigen Wert,ord
der genau denselben erzeugt und zurückgibtchar
.In der Praxis würde ich diese wahrscheinlich nur durchgießen ,
unsigned char
anstatt sie zu verwenden, aber sie wickeln die Besetzung kurz und bündig ein, bieten einen praktischen Ort zum Hinzufügen von Fehlerprüfungen fürint
-to-char
und wären kürzer und klarer, wenn Sie sie mehrmals verwenden müssen in unmittelbarer Nähe.quelle
Verwendung
static_cast<int>
:Bearbeiten: Sie sollten wahrscheinlich versuchen, die Verwendung zu vermeiden
(int)
check out Warum statisches_cast <int> (x) anstelle von (int) x verwenden? Für mehr Information.
quelle
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
int
Variablen als behandelt werdenchar
soll, ist dies einfacher. In C sind die verschiedenen Ganzzahltypen eher ein Geisteszustand als tatsächliche separate "Typen". Verwenden Sie es einfach dort, wo Siechar
gefragt 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.quelle
Ich habe absolut
null
Fähigkeiten in C, aber für eine einfache Analyse:... das hat bei mir funktioniert:
quelle
Vermutlich möchten Sie diese Konvertierung für die Verwendung von Funktionen aus der C-Standardbibliothek.
In diesem Fall do (C ++ - Syntax)
Der Ausdruck wird in
UChar( c )
konvertiertunsigned 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
int
formales Argument verwendet. Wo Sie automatisch befördert werdenint
. Sie können diesen letzten Schritt auch explizit explizit schreibenint( UChar( c ) )
, aber ich persönlich finde das zu ausführlich.Prost & hth.,
quelle
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;)
Ich hoffe es hilft!
quelle
Für char oder short to int müssen Sie nur den Wert zuweisen.
Gleiches gilt für int64.
Alle Werte sind 16.
quelle
Mit dieser atoi-Methode können Sie char in int konvertieren. Weitere Informationen finden Sie unter http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/string/stoi/ .
quelle