Convertir char en int en C et C ++

401

Comment convertir un charen un inten C et C ++?

mainajaved
la source
1
@Matt: ce serait une bonne idée d'être plus concret. poser des questions sur une généralisation invite simplement à des réponses généralisées qui ne sont pas applicables ou même correctes pour votre tâche. Gardez à l'esprit que lorsque vous devez demander, vous n'en savez probablement pas assez pour généraliser correctement.
Bravo et hth. - Alf
@Alf P. Steinbach: La question initiale était vague concernant la langue. Avec les mots c- clés et c++, je pense que les réponses face aux deux langues sont raisonnables.
Matt Joiner
8
D'après ma vaste expérience sur d'autres forums techniques, mon intuition est que l'OP signifie vraiment "comment puis-je prendre la représentation textuelle d'un nombre (en base 10) et le convertir en nombre correspondant?" De manière générale, les néophytes C et C ++ ont généralement des idées incroyablement floues sur le fonctionnement du texte dans ces langages et ce que charcela signifie vraiment.
Karl Knechtel
3
@KarlKnechtel: Si c'est vrai (je lui donne environ 50/50 car de nombreux premiers tutoriels encouragent également à obtenir des valeurs ASCII à partir des caractères, même si ASCII ne couvre pas toute la plage), l'OP doit être clair - mais c'est une dupe de stackoverflow.com/questions/439573/… .
Fred Nurk
3
Le PO avait trois heures pour clarifier cette question et ne l'a pas fait. En l'état, il n'y a aucun moyen de savoir ce qui est réellement demandé. A voté pour fermer.
sbi

Réponses:

552

Ça dépend de ce que tu veux faire:

pour lire la valeur sous forme de code ascii, vous pouvez écrire

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

pour convertir le caractère '0' -> 0, '1' -> 1etc, vous pouvez écrire

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

Explication :
a - '0'est équivalent à ((int)a) - ((int)'0'), ce qui signifie que les valeurs ascii des caractères sont soustraites les unes des autres. Puisque 0vient juste avant 1dans le tableau ascii (et ainsi de suite jusqu'à 9), la différence entre les deux donne le nombre que le caractère areprésente.

Foo Bah
la source
14
ia = (a - '0')% 48;
Kshitij Banerjee
@KshitijBanerjee Ce n'est pas une bonne idée pour deux raisons: il vous donne un nombre négatif pour les caractères ascii avant '0' (comme &-> -10), et il vous donne des nombres supérieurs à 10 (comme x-> 26)
SheetJS
2
int ia = a - '0' - c'est ce dont vous avez besoin
funk
5
@ kevin001 Si vous souhaitez convertir le caractère en int et qu'un caractère '1'fournit un nombre ascii qui ne l'est pas 1, vous devez supprimer le décalage '0'pour le réaligner pour qu'il compte de 0 à 9. Les nombres consécutifs 1-9 sont adjacents dans le nombre entier ascii.
krisdestruction
Aucun casting n'est requis / souhaité
Craig Estey
97

Eh bien, en code ASCII, les chiffres (chiffres) commencent à 48 . Il vous suffit de:

int x = (int)character - 48;
Vlad Isoc
la source
19
@chad: Non seulement plus lisible, mais aussi plus portable. C et C ++ ne garantissent pas une représentation ASCII, mais ils garantissent que quelle que soit la représentation utilisée, les représentations des 10 chiffres décimaux sont contiguës et dans l'ordre numérique.
Ben Voigt
La seule chose que j'aurais changé est d'avoir 48 ans, ce qui semble un peu "magique" à'0'
ArielGro
59

C et C ++ promeuvent toujours les types au moins int. De plus, les littéraux de caractères sont de type inten C et charen C ++.

Vous pouvez convertir un chartype simplement en l'attribuant à un int.

char c = 'a'; // narrowing on C
int a = c;
Matt Joiner
la source
3
Vous pouvez également utiliser l' unaire très sous-estimé operator+()à cette fin.
Cubbi
24
-1 La réponse est incorrecte pour la seule interprétation significative de la question. Ce (code int a = c;) conservera toutes les valeurs négatives que les fonctions de bibliothèque standard C ne peuvent pas gérer. Les fonctions de bibliothèque standard C définissent la norme pour ce que signifie gérer les charvaleurs en tant que int.
Bravo et hth. - Alf
6
@Matt: Je garde le downvote. Je le renforcerais si possible! L'interprétation de la question que vous et d'autres avez supposée n'est pas significative, car elle est trop triviale, et parce que pour la combinaison particulière de types du PO, il y a un problème pratique très important pas si trivial. Les conseils que vous donnez sont directement dangereux pour le novice. Il en résultera très probablement un comportement indéfini pour leurs programmes qui utilisent les fonctions de classification des caractères de la bibliothèque C standard. Re ref. à la réponse de @ Sayam, il a supprimé cette réponse.
Bravo et hth. - Alf
3
-1 pour être incorrect: isupper () aura des résultats indéfinis s'il passe un caractère 1252 highbit.
Chris Becke
1
Qu'entendez-vous par «toujours promouvoir»? Les valeurs sont promues pendant les conversions implicites, certains types de paramètres passant (par exemple, à une fonction varargs), et lorsqu'un opérateur doit rendre ses opérandes compatibles avec les types. Mais il y a certainement des moments où une valeur n'est pas promue (comme si je passe un char à une fonction qui attend un char), sinon nous n'aurions pas de types plus petits qu'un int.
Adrian McCarthy
31

char n'est qu'un entier de 1 octet. Il n'y a rien de magique avec le type char! Tout comme vous pouvez attribuer un short à un int ou un int à un long, vous pouvez affecter un char à un int.

Oui, le nom du type de données primitif se trouve être "char", ce qui laisse entendre qu'il ne doit contenir que des caractères. Mais en réalité, "char" est juste un mauvais choix pour confondre tous ceux qui essaient d'apprendre la langue. Un meilleur nom est int8_t, et vous pouvez utiliser ce nom à la place, si votre compilateur suit la dernière norme C.

Bien que vous sûr devez utiliser le type char lorsque vous effectuez la gestion des chaînes, car l'index des ajustements de table ASCII classique dans 1 octet. Cependant, vous pouvez également manipuler des cordes avec des entiers réguliers, bien qu'il n'y ait aucune raison pratique dans le monde réel pour laquelle vous voudriez faire cela. Par exemple, le code suivant fonctionnera parfaitement:

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

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

Vous devez comprendre que les caractères et les chaînes ne sont que des nombres, comme tout le reste de l'ordinateur. Lorsque vous écrivez «a» dans le code source, il est prétraité en nombre 97, qui est une constante entière.

Donc, si vous écrivez une expression comme

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

c'est en fait équivalent à

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

qui passe ensuite par les promotions entières du langage C

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

puis tronqué à un caractère pour s'adapter au type de résultat

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

Il y a beaucoup de choses subtiles comme ça entre les lignes, où char est implicitement traité comme un int.

Lundin
la source
Étant donné que la question n'est pas balisée ascii, vous ne devez pas supposer d'encodage spécifique. La valeur charégale à int8_test incorrecte, car elle pourrait également être uint8_tou uint24_t.
Roland Illig
1
@RolandIllig Non, a charvaut toujours 1 octet et si les types int8_t/ uint8_texistent sur le système donné (ce qui est très probable), ils pourront ajuster le résultat de a char, car ce sera alors 8 bits. Sur les systèmes très exotiques tels que divers DSP obsolètes, charsera de 16 bits et uint8_tn'existera pas. Écrire du code pour la compatibilité avec les DSP obsolètes est un non-sens, tout comme l'écrire pour la compatibilité avec ses systèmes de complément ou de signe et d'amplitude. Énorme perte de temps, car de tels systèmes existent à peine dans le monde réel.
Lundin
18

(Cette réponse concerne le côté C ++ des choses, mais le problème d'extension de signe existe également en C.)

Manipulation des trois chartypes ( signed, unsignedet char) est plus délicate qu'il n'y paraît. Les valeurs comprises entre 0 et SCHAR_MAX(qui est de 127 pour un 8 bits char) sont faciles:

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

Mais, lorsque se somevaluesitue en dehors de cette plage, le simple unsigned charfait de vous donner des résultats cohérents pour les "mêmes" charvaleurs dans les trois types:

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.

Ceci est important lorsque vous utilisez des fonctions de ctype.h , telles que isupperou toupper, en raison de l'extension de signe:

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

Notez que la conversion via int est implicite; cela a le même UB:

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

Pour résoudre ce problème, passez par unsigned char, ce qui se fait facilement en encapsulant les fonctions ctype.h via 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.

Cela fonctionne car toute fonction prenant l'un des trois types de caractères peut également prendre les deux autres types de caractères. Il conduit à deux fonctions qui peuvent gérer n'importe lequel des types:

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)vous donne toujours une valeur non négative - même en cas de passage négatif charou négatif signed char- et chrprend n'importe quelle valeur ordproduit et rend exactement la même chose char.

Dans la pratique, je ferais probablement un cast au unsigned charlieu de les utiliser, mais ils enveloppent succinctement le cast, fournissent un endroit pratique pour ajouter la vérification des erreurs pour int-to- char, et seraient plus courts et plus clairs lorsque vous devez les utiliser plusieurs fois à proximité.

Fred Nurk
la source
12

Utilisation static_cast<int>:

int num = static_cast<int>(letter); // if letter='a', num=97

Edit: Vous devriez probablement essayer d'éviter d'utiliser(int)

int num = (int) lettre;

consultez Pourquoi utiliser static_cast <int> (x) au lieu de (int) x? pour plus d'informations.

herohuyongtao
la source
7

Cela dépend en quelque sorte de ce que vous entendez par «convertir».

Si vous avez une série de caractères qui représente un entier, comme "123456", il existe deux façons typiques de le faire en C: Utilisez une conversion à usage spécial comme atoi () ou strtol () , ou le sscanf à usage général () . C ++ (qui est vraiment un langage différent se faisant passer pour une mise à niveau) ajoute un troisième, les flux de chaînes.

Si vous voulez dire que vous voulez que le motif de bits exact dans l'une de vos intvariables soit traité comme un char, c'est plus facile. En C, les différents types entiers sont vraiment plus un état d'esprit que de véritables "types" séparés. Commencez simplement à l'utiliser là où charon vous le demande, et ça devrait aller. Vous devrez peut-être une conversion explicite pour que le compilateur arrête de pleurnicher à l'occasion, mais tout ce qui devrait faire est de supprimer tous les bits supplémentaires au-delà de 256.

TED
la source
6

J'ai absolument des nullcompétences en C, mais pour une analyse simple:

char* something = "123456";

int number = parseInt(something);

... cela a fonctionné pour moi:

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;
}
Henke
la source
Ce code invoque rapidement un comportement indéfini et n'est donc pas adapté au copier-coller. (débordement int)
Roland Illig
4

Vraisemblablement, vous voulez cette conversion pour utiliser les fonctions de la bibliothèque standard C.

Dans ce cas, faites (syntaxe C ++)

typedef unsigned char UChar;

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

L'expression est UChar( c )convertie unsigned charen afin de se débarrasser des valeurs négatives qui, à l'exception d'EOF, ne sont pas prises en charge par les fonctions C.

Ensuite, le résultat de cette expression est utilisé comme argument réel pour un intargument formel. Où vous obtenez une promotion automatique int. Vous pouvez également écrire cette dernière étape explicitement, comme int( UChar( c ) ), mais personnellement, je trouve cela trop verbeux.

Santé et hth.,

Santé et hth. - Alf
la source
0

J'avais des problèmes pour convertir un tableau de caractères comme "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"dans sa valeur entière réelle qui pourrait être représentée par `7C 'comme une valeur hexadécimale. Donc, après avoir cherché de l'aide, j'ai créé cela et j'ai pensé que ce serait cool de partager.

Cela sépare la chaîne de caractères en ses entiers droits, et peut être utile à plus de gens que moi;)

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;
}

J'espère que cela aide!

Mathorlaz
la source
Avez-vous déjà testé ce code? Le 50 doit être un 48, le 55 ne fonctionne que pour les lettres ASCII majuscules tandis que votre exemple contient des lettres minuscules.
Roland Illig
0

Pour char ou short to int, il vous suffit d'attribuer la valeur.

char ch = 16;
int in = ch;

Identique à int64.

long long lo = ch;

Toutes les valeurs seront 16.

Riwels
la source
-1
int charToint(char a){
char *p = &a;
int k = atoi(p);
return k;
}

Vous pouvez utiliser cette méthode atoi pour convertir char en int. Pour plus d'informations, vous pouvez vous référer à ce http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/string/stoi/ .

pranav suresh
la source
1
Il s'agit d'un comportement indéfini. Prendre l'adresse d'une variable char vous donnera un char * mais pas une chaîne C, ce à quoi atoi s'attend.
luizfls