Convertir un chiffre de caractère en entier correspondant en C

103

Existe-t-il un moyen de convertir un caractère en entier en C?

Par exemple, de '5'à 5?

Couler
la source

Réponses:

150

Comme pour d'autres réponses, c'est bien:

char c = '5';
int x = c - '0';

De plus, pour la vérification des erreurs, vous souhaiterez peut-être vérifier que isdigit (c) est vrai en premier. Notez que vous ne pouvez pas faire de même pour les lettres, par exemple:

char c = 'b';
int x = c - 'a'; // x is now not necessarily 1

La norme garantit que les valeurs char pour les chiffres «0» à «9» sont contiguës, mais n'offre aucune garantie pour les autres caractères comme les lettres de l'alphabet.

Chris Young
la source
3
@Paul Tomblin: Oui pour les chiffres et non les lettres, car, comme je l'ai dit dans la réponse, les garanties standard «0» à «9» sont contiguës mais ne font pas de telles garanties pour les autres caractères tels que «a» à «z».
Chris Young
char c = 'b'; int x = c - 'a'; alors x sera 1 seulement en ASCII?
Pan
@Pan Dans tout encodage, y compris ASCII, qui a «b» 1 plus que «a». Cela est toujours vrai dans EBCDIC, mais cela fait ('j' - 'i') == 8.
Chris Young
@ChrisYoung Pourquoi? Parce que dans EBCDIC, «j» n'est pas 1 de plus que «i»?
Pan
2
Que me manque-t-il là où atoi n'est pas utilisé?
Daniel
41

Soustrayez «0» comme ceci:

int i = c - '0';

La norme C garantit que chaque chiffre de la plage '0'..'9'est supérieur de un à son chiffre précédent (dans la section 5.2.1/3du projet C99 ). La même chose vaut pour C ++.

Johannes Schaub - litb
la source
1
Cette réponse serait meilleure si vous mentionniez qu'un caractère est / déjà / effectivement un entier, un albiet du signe défini par l'implémentation (c'est-à-dire qu'il peut être signé ou non signé) et qu'il est long de CHAR_BITS.
Arafangion
je n'étais pas sûr de savoir que cela l'aide vraiment. mais Chris a fait un bon point avec a..z n'étant pas nécessairement contigu. J'aurais dû le mentionner à la place. maintenant il a gagné la course :)
Johannes Schaub - litb
1
La vôtre est meilleure parce que vous avez nuancé votre réponse, cependant - Chris aurait très bien pu inventer ses affaires. :)
Arafangion
merci pour l'appréciation. J'admets que je n'étais pas sûr de l'état de C. alors j'ai levé les yeux et parce que
j'y étais
Et c'est pourquoi, monsieur, vous avez quelques points de plus que moi. :)
Arafangion
29

Si, par une folle coïncidence, vous voulez convertir une chaîne de caractères en entier, vous pouvez le faire aussi!

char *num = "1024";
int val = atoi(num); // atoi = ASCII TO Int

valest maintenant 1024. Apparemment atoi(), ça va, et ce que j'ai dit plus tôt ne s'applique qu'à moi (sur OS X (peut-être (insérer une blague Lisp ici))). J'ai entendu dire que c'est une macro qui correspond à peu près à l'exemple suivant, qui utilise strtol()une fonction plus générale pour effectuer la conversion à la place:

char *num = "1024";
int val = (int)strtol(num, (char **)NULL, 10); // strtol = STRing TO Long

strtol() fonctionne comme ceci:

long strtol(const char *str, char **endptr, int base);

Il se convertit *stren a long, le traitant comme s'il s'agissait d'un basenombre de base . S'il **endptrn'est pas nul, il contient le premier caractère non numérique strtol()trouvé (mais qui s'en soucie).

Chris Lutz
la source
Il n'y a aucun problème de thread avec atoi (il n'a pas de données statiques) et il n'est pas obsolète. En fait, il est fonctionnellement équivalent à: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran
5
Le problème avec atoi est qu'il utilise 0 comme valeur "impossible de trouver un nombre ici", donc atoi ("0") et atoi ("un") renvoient tous les deux 0. Si cela ne fonctionne pas pour ce que vous ' si vous l'utilisez pour, recherchez strtol () ou sscanf ().
David Thornley
L'autre avantage de strtol, bien sûr, est que vous devrez peut-être lire d'autres choses de la même chaîne qui viennent après le nombre.
dfeuer le
@EvanTeran Malheureusement, si vous exécutez Visual Studio, vous obtenez un avertissement de dépréciation (et vous ne compilez pas sans être désactivé). VS recommande maintenant itoa_s().
Simon le
7

Soustrayez le caractère '0' ou int 48 comme ceci:

char c = '5';
int i = c - '0';

Explication: En interne, il fonctionne avec la valeur ASCII . Dans la table ASCII, la valeur décimale du caractère 5 est 53 et 0 est 48 . Donc 53 - 48 = 5

OU

char c = '5';
int i = c - 48; // Because decimal value of char '0' is 48

Cela signifie que si vous déduisez 48 de n'importe quel caractère numérique, il convertira automatiquement l'entier.

Arif
la source
6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');
Kevin Conner
la source
numeralChar - '0'est déjà de type int, vous n'avez donc pas besoin de la distribution. Même si ce n'était pas le cas, le casting n'est pas nécessaire.
Alok Singhal
Hein, ouais ça contraindrait, n'est-ce pas? Peut-être que Java a coloré mes perceptions. Ou peut-être que je me trompe complètement et que cela contraindrait même Java. :)
Kevin Conner
6

Pour convertir un chiffre de caractère en entier correspondant. Faites comme indiqué ci-dessous:

char c = '8';                    
int i = c - '0';

La logique derrière le calcul ci-dessus est de jouer avec les valeurs ASCII. La valeur ASCII du caractère 8 est 56, la valeur ASCII du caractère 0 est 48. La valeur ASCII de l'entier 8 est 8.

Si nous soustrayons deux caractères, la soustraction se produira entre ASCII de caractères.

int i = 56 - 48;   
i = 8;
Ashish
la source
Pourquoi suis-je le seul à voter pour cela? L'explication est si simple et informative: +1:
Brandon Benefield
0

S'il ne s'agit que d'un seul caractère 0-9 en ASCII, la soustraction de la valeur du caractère zéro ASCII de la valeur ASCII devrait fonctionner correctement.

Si vous souhaitez convertir des nombres plus grands, procédez comme suit:

char *string = "24";

int value;

int assigned = sscanf(string, "%d", &value);

** n'oubliez pas de vérifier le statut (qui devrait être 1 si cela a fonctionné dans le cas ci-dessus).

Paul.

Paul W Homer
la source
0
char chVal = '5';
char chIndex;

if ((chVal >= '0') && (chVal <= '9')) {

    chIndex = chVal - '0';
}
else 
if ((chVal >= 'a') && (chVal <= 'z')) {

    chIndex = chVal - 'a';
}
else 
if ((chVal >= 'A') && (chVal <= 'Z')) {

    chIndex = chVal - 'A';
}
else {
    chIndex = -1; // Error value !!!
}
Alphaneo
la source
0

Quand j'ai besoin de faire quelque chose comme ça, je pré-cuit un tableau avec les valeurs que je veux.

const static int lookup[256] = { -1, ..., 0,1,2,3,4,5,6,7,8,9, .... };

Ensuite, la conversion est facile

int digit_to_int( unsigned char c ) { return lookup[ static_cast<int>(c) ]; }

C'est essentiellement l'approche adoptée par de nombreuses implémentations de la bibliothèque ctype. Vous pouvez facilement l'adapter pour qu'il fonctionne également avec des chiffres hexadécimaux.

Michael Anderson
la source
Cela semble extrêmement inefficace pour convertir un seul chiffre décimal (ou octal). Si la partie pertinente de votre table de recherche ne se trouve pas dans le cache L1, vous ferez un tas de cycles pour la récupérer juste pour obtenir une valeur. Franchement, j'ai tendance à douter que ce soit même une bonne idée si vous convertissez toute une série de chiffres, mais vous devrez mesurer cela. C'est bien plus compétitif pour l'hexagone, bien sûr.
dfeuer le
0

Vérifie ça,

char s='A';

int i = (s<='9')?(s-'0'):(s<='F')?((s-'A')+10):((s-'a')+10);

pour seulement 0,1,2, ...., E, F.

Shiva
la source
0

Utilisez simplement la atol()fonction:

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

int main() 
{
    const char *c = "5";
    int d = atol(c);
    printf("%d\n", d);

}
Salles Dylan
la source
0

Si votre chiffre est, par exemple, '5'en ASCII, il est représenté par le nombre binaire 0011 0101(53). Chaque chiffre a les quatre bits 0011les plus élevés et les 4 bits les plus bas représentent le chiffre en bcd. Alors tu fais juste

char cdig = '5';
int dig = cdig & 0xf; // dig contains the number 5

pour obtenir les 4 bits les plus bas, ou, quoi de neuf, le chiffre. Dans asm, il utilise l' andopération au lieu de sub(comme dans les autres réponses).

Garmekain
la source
'5'est 53 ( 00110101)
eyllanesc
@eyllanesc Au début, c'était un 4. Merci. Je l'ai édité.
Garmekain
0

Voici des fonctions d'assistance qui permettent de convertir un chiffre de char en int et vice versa:

int toInt(char c) {
    return c - '0';
}

char toChar(int i) {
    return i + '0';
}
Maxim Makhun
la source
-2

use function: atoi pour un tableau à un entier, atof pour un tableau à un type flottant; ou

char c = '5';
int b = c - 48;
printf("%d", b);
K. étain
la source
Plusieurs réponses couvraient déjà cela. Cela n'ajoute rien qu'ils n'aient déjà couvert.
ShadowRanger
-3

Vous le convertiriez en un int (ou float ou double ou tout ce que vous voulez en faire) et le stocker dans une variable.

SeanJA
la source