Conversion Char en int en C
Si je veux convertir un seul char
numérique en sa valeur numérique, par exemple, si:
char c = '5';
Et je veux que c
tienne 5
au lieu de '5'
, est-ce 100% portable qui le fait comme ça?
c = c - '0';
J'ai entendu dire que tous les jeux de caractères stockent les nombres dans un ordre consécutif, donc je suppose, mais j'aimerais savoir s'il existe une fonction de bibliothèque organisée pour faire cette conversion, et comment cela se fait de manière conventionnelle. Je suis un vrai débutant :)
10 réponses
Oui, c'est une conversion sûre. C l'exige pour fonctionner. Cette garantie figure au paragraphe 2 de la section 5.2.1 de la dernière norme ISO C, dont un projet récent est N1570 :
Les jeux de caractères source de base et d'exécution de base doivent avoir les caractéristiques suivantes membres:
[...]
le 10 décimal chiffres0 1 2 3 4 5 6 7 8 9
[...]
Dans les jeux de caractères de base source et d'exécution, le la valeur de chaque caractère après 0 dans la liste ci-dessus les chiffres décimaux doivent être un plus grand que la valeur de la précédente.
ASCII et EBCDIC, ainsi que les jeux de caractères qui en découlent, satisfont à cette exigence, ce qui explique pourquoi la norme C a pu l'imposer. Notez que les lettres sontPas contiguës dans EBCDIC, et C ne nécessite pas qu'elles soient.
Il N'y a pas de fonction de bibliothèque pour le faire pour un seul char
, vous devez d'abord construire une chaîne:
int digit_to_int(char d)
{
char str[2];
str[0] = d;
str[1] = '\0';
return (int) strtol(str, NULL, 10);
}
Vous pouvez également utiliser la fonction atoi()
pour conversion, une fois que vous avez une chaîne, mais strtol()
est meilleur et plus sûr.
Comme les commentateurs l'ont souligné, il est extrêmement exagéré d'appeler une fonction pour faire cette conversion; votre approche initiale pour soustraire '0' est la bonne façon de le faire. Je voulais juste montrer comment l'approche standard recommandée de conversion d'un nombre en tant que chaîne en un nombre "vrai" serait utilisée, ici.
int i = c - '0';
Vous devez savoir que cela n'effectue aucune validation par rapport au caractère - par exemple, si le caractère était 'a', vous obtiendriez 91 - 48 = 49. Surtout si vous avez affaire à une entrée utilisateur ou réseau, vous devriez probablement effectuer une validation pour éviter un mauvais comportement dans votre programme. Il suffit de vérifier la plage:
if ('0' <= c && c <= '9') {
i = c - '0';
} else {
/* handle error */
}
Notez que si vous voulez que votre conversion gère les chiffres hexadécimaux, vous pouvez vérifier la plage et effectuer le calcul approprié.
if ('0' <= c && c <= '9') {
i = c - '0';
} else if ('a' <= c && c <= 'f') {
i = 10 + c - 'a';
} else if ('A' <= c && c <= 'F') {
i = 10 + c - 'A';
} else {
/* handle error */
}
Que convertira un seul caractère hexadécimal, indépendant des majuscules ou des minuscules, en un entier.
Puisque vous ne convertissez qu'un caractère, la fonction atoi() est exagérée. atoi() est utile si vous convertissez des représentations de chaînes de nombres. Les autres postes ont donné des exemples de cela. Si je lis votre message correctement, vous ne convertissez qu'un caractère numérique. Donc, vous allez seulement convertir un caractère qui est la plage 0 à 9. Dans le cas de la conversion d'un seul caractère numérique, votre suggestion de soustraire '0' vous donnera le résultat que vous voulez. La raison pour laquelle cela fonctionne parce que les valeurs ASCII sont consécutives (comme vous l'avez dit). Ainsi, soustraire la valeur ASCII de 0 (valeur ASCII 48 - voir Table ASCII pour les valeurs) d'un caractère numérique donnera la valeur du nombre. Donc, votre exemple de c = C - ' 0 'où c = '5', ce qui se passe vraiment Est 53 (la valeur ASCII de 5) - 48 ( la valeur ASCII de 0) = 5.
Quand j'ai posté cette réponse pour la première fois, je n'ai pas pris en considération votre commentaire sur le fait d'être 100% portable entre différents les jeux de caractères. J'ai fait un peu plus loin en regardant autour et il semble que votre réponse est encore la plupart du temps correcte. Le problème est que vous utilisez un char qui est un 8 bits type de données. Ce qui ne fonctionnerait pas avec tous les types de caractères. Lisez cet article de Joel Spolsky sur Unicode pour beaucoup plus d'informations sur Unicode. Dans cet article, il dit qu'il utilise wchar_t pour les personnages. Cela a bien fonctionné pour lui et il publie son site Web en 29 langues. Donc, vous auriez besoin de les changer votre char à un wchar_t. autre que cela, il dit que le caractère sous la valeur 127 et ci-dessous sont fondamentalement les mêmes. Cela inclurait des caractères qui représentent des nombres. Cela signifie que les mathématiques de base que vous avez proposées devraient fonctionner pour ce que vous essayiez d'atteindre.
Oui. Ceci est sûr tant que vous utilisez des caractères ASCII standard, comme vous l'êtes dans cet exemple.
Normalement, s'il n'y a aucune garantie que votre entrée est dans le '0'..'9' range, vous devrez effectuer une vérification comme ceci:
if (c >= '0' && c <= '9') {
int v = c - '0';
// safely use v
}
Une alternative consiste à utiliser une table de recherche. Vous obtenez une vérification de plage simpleet une conversion avec moins de code (et peut-être plus rapide):
// one-time setup of an array of 256 integers;
// all slots set to -1 except for ones corresponding
// to the numeric characters
static const int CHAR_TO_NUMBER[] = {
-1, -1, -1, ...,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // '0'..'9'
-1, -1, -1, ...
};
// Now, all you need is:
int v = CHAR_TO_NUMBER[c];
if (v != -1) {
// safely use v
}
P. S. I savoir, que c'est un overkill. Je voulais juste le présenter comme une solution alternative qui peut ne pas être immédiatement évidente.
Comme d'autres l'ont suggéré, mais enveloppée dans une fonction:
int char_to_digit(char c) {
return c - '0';
}
Maintenant, il suffit d'utiliser la fonction. Si, en bas de la ligne, vous décidez d'utiliser une méthode différente, il vous suffit de changer l'implémentation (performance, différences de jeu de caractères, peu importe), vous n'aurez pas besoin de changer les appelants.
Cette version suppose que c contient un caractère qui représente un chiffre. Vous pouvez vérifier cela avant d'appeler la fonction, en utilisant ctype.fonction isdigit de h.
Depuis les codes ASCII pour '0','1','2'.... sont placés de 48 à 57 ils sont essentiellement continu. Maintenant, les opérations arithmétiques nécessitent la conversion de char datatype en int datatype.Par conséquent ce que vous faites essentiellement est: 53-48 et donc il stocke la valeur 5 avec laquelle vous pouvez faire des opérations entières.Notez que lors de la conversion de int en char, le compilateur ne donne aucune erreur mais effectue simplement une opération modulo 256 pour placer la valeur dans sa plage acceptable
Vous pouvez simplement utiliser la fonctionatol()
:
#include <stdio.h>
#include <stdlib.h>
int main()
{
const char *c = "5";
int d = atol(c);
printf("%d\n", d);
}