Converta um dígito de caractere para o número inteiro correspondente em C

103

Existe uma maneira de converter um caractere em um inteiro em C?

Por exemplo, de '5'a 5?

Fluxo
fonte

Respostas:

149

De acordo com outras respostas, está bom:

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

Além disso, para verificação de erros, você pode desejar verificar se isdigit (c) é verdadeiro primeiro. Observe que você não pode fazer o mesmo de forma totalmente portátil para letras, por exemplo:

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

O padrão garante que os valores de char para os dígitos de '0' a '9' sejam contíguos, mas não oferece garantia para outros caracteres, como letras do alfabeto.

Chris Young
fonte
3
@Paul Tomblin: Sim para dígitos e não letras, porque, como eu disse na resposta, o padrão garante '0' a '9' são contíguos, mas não oferece tais garantias para outros caracteres como 'a' a 'z'.
Chris Young
char c = 'b'; int x = c - 'a'; então x será 1 apenas em ASCII?
Pan de
@Pan Em qualquer codificação, incluindo ASCII, que tenha 'b' 1 a mais do que 'a'. Isso ainda é verdadeiro em EBCDIC, no entanto, torna ('j' - 'i') == 8.
Chris Young
@ChrisYoung Por quê? Porque em EBCDIC, 'j' não é 1 mais do que 'i'?
Pan
2
O que estou perdendo aqui onde o atoi não é usado?
Daniel
41

Subtraia '0' assim:

int i = c - '0';

O padrão C garante que cada dígito no intervalo '0'..'9'seja um maior que o dígito anterior (na seção 5.2.1/3do rascunho C99 ). O mesmo vale para C ++.

Johannes Schaub - litb
fonte
1
Esta resposta seria melhor se você mencionasse que um char é / já / efetivamente um inteiro, um sinal definido de implementação (ou seja, pode ser assinado ou não assinado) e é CHAR_BITS longo.
Arafangion
Eu não tinha certeza de saber que isso realmente o ajuda. mas Chris fez uma boa observação com a..z sendo não necessariamente contíguo. eu deveria ter mencionado isso em vez disso. agora ele ganhou a corrida :)
Johannes Schaub - litb
1
A sua é melhor porque você qualificou sua resposta, porém - Chris poderia muito bem ter inventado suas coisas. :)
Arafangion
obrigado pela apreciação. Admito que não tinha certeza sobre o estado de C. então olhei para cima e, como já estava lá, colei a referência na resposta :)
Johannes Schaub - litb
E é por isso, senhor, que tem mais alguns pontos do que eu. :)
Arafangion
29

Se, por alguma coincidência maluca, você quiser converter uma sequência de caracteres em um inteiro, você também pode fazer isso!

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

valagora é 1024. Aparentemente atoi()está bem, e o que eu disse sobre isso antes só se aplica a mim (no OS X (talvez (insira a piada do Lisp aqui))). Ouvi dizer que é uma macro que mapeia aproximadamente para o próximo exemplo, que usa strtol()uma função de uso mais geral para fazer a conversão:

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

strtol() funciona assim:

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

Ele é convertido *strem um long, tratando-o como se fosse um basenúmero base . Se **endptrnão for nulo, ele contém o primeiro caractere diferente de dígito strtol()encontrado (mas quem se importa com isso).

Chris Lutz
fonte
Não há problemas de thread com atoi (não tem dados estáticos) e não está obsoleto. Na verdade, é funcionalmente equivalente a: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran
5
O problema com atoi é que ele usa 0 como um valor "não é possível encontrar um número aqui", então atoi ("0") e atoi ("um") retornam 0. Se isso não funcionar para o que você ' se estiver usando, procure strtol () ou sscanf ().
David Thornley,
A outra vantagem do strtol, claro, é que você pode precisar ler outras coisas da mesma string que vem depois do número.
dia
@EvanTeran Infelizmente, se você executar o Visual Studio, receberá um aviso de depreciação (e não compilará sem ser desabilitado). VS agora recomenda itoa_s().
Simon
7

Subtraia char '0' ou int 48 assim:

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

Explicação: Internamente, funciona com valor ASCII . Na tabela ASCII, o valor decimal do caractere 5 é 53 e 0 é 48 . Então 53 - 48 = 5

OU

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

Isso significa que se você deduzir 48 de qualquer caractere numérico, ele converterá o inteiro automaticamente.

Arif
fonte
6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');
Kevin Conner
fonte
numeralChar - '0'já é do tipo int, então você não precisa do elenco. Mesmo se não fosse, o gesso não é necessário.
Alok Singhal
Huh, sim, isso coagiria, não é? Talvez Java tenha colorido minhas percepções. Ou talvez eu esteja completamente enganado e isso até coagiria em Java. :)
Kevin Conner,
5

Para converter o dígito do caractere em um inteiro correspondente. Faça como mostrado abaixo:

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

A lógica por trás do cálculo acima é brincar com os valores ASCII. O valor ASCII do caractere 8 é 56, o valor ASCII do caractere 0 é 48. O valor ASCII do inteiro 8 é 8.

Se subtrairmos dois caracteres, a subtração acontecerá entre ASCII de caracteres.

int i = 56 - 48;   
i = 8;
Ashish
fonte
Por que eu sou o único a votar a favor disso? A explicação é tão simples e informativa: +1:
Brandon Benefield
0

Se for apenas um único caractere 0-9 em ASCII, subtrair o valor do caractere ASCII zero do valor ASCII deve funcionar bem.

Se você deseja converter números maiores, faça o seguinte:

char *string = "24";

int value;

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

** não se esqueça de verificar o status (que deve ser 1 se funcionou no caso acima).

Paulo.

Paul W Homer
fonte
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
fonte
0

Quando preciso fazer algo assim, pré-preparo um array com os valores que desejo.

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

Então a conversão é fácil

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

Essa é basicamente a abordagem adotada por muitas implementações da biblioteca ctype. Você pode adaptar isso trivialmente para funcionar com dígitos hexadecimais também.

Michael Anderson
fonte
Isso parece extremamente ineficiente para converter um único dígito decimal (ou octal). Se a parte relevante de sua tabela de pesquisa não estiver no cache L1, você vai gastar vários ciclos para puxá-la apenas para obter um valor. Francamente, tendo a duvidar que isso seja uma boa ideia se você estiver convertendo uma grande quantidade de dígitos, mas você teria que medir isso. É muito mais competitivo para hex, é claro.
dfeuer
0

Verifique isso,

char s='A';

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

para apenas 0,1,2, ...., E, F.

Shiva
fonte
0

Basta usar a atol()função:

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

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

}
Corredores Dylan
fonte
0

Se o seu dígito for, digamos, '5'em ASCII, ele será representado como o número binário 0011 0101(53). Cada dígito tem os quatro bits mais altos 0011e os 4 bits mais baixos representam o dígito em bcd. Então você apenas faz

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

para obter os 4 bits mais baixos, ou, o que é igual, o dígito. Em asm, ele usa andoperação em vez de sub(como nas outras respostas).

Garmekain
fonte
'5'é 53 ( 00110101)
eyllanesc de
@eyllanesc No começo foi um 4. Obrigado. Editado.
Garmekain de
0

Aqui estão as funções auxiliares que permitem converter dígito em char para int e vice-versa:

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

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

use a função: atoi para array para inteiro, atof para array para tipo float; ou

char c = '5';
int b = c - 48;
printf("%d", b);
K.tin
fonte
Várias respostas já abordaram isso. Isso não adiciona nada que já não tenham abordado.
ShadowRanger
-3

Você o lançaria em um int (ou float ou double ou o que quer que você queira fazer com ele) e o armazenaria em outra variável.

SeanJA
fonte