Converter char para int em C e C ++

401

Como converter um charpara um intem C e C ++?

mainajaved
fonte
11
@ Matt: seria uma boa idéia ser mais concreto. perguntar sobre uma generalização apenas convida respostas generalizadas que não são aplicáveis ou mesmo corretas para sua tarefa. tenha em mente que, quando precisar perguntar, provavelmente não sabe o suficiente para generalizar corretamente.
Saúde e hth. - Alf
@Alf P. Steinbach: A pergunta original era vaga em relação a qual idioma. Com palavras c- chave e c++, acho que as respostas que confrontam os dois idiomas são razoáveis.
Matt Joiner
8
Da minha vasta experiência em outros fóruns técnicos, minha intuição é que o OP realmente significa "como faço para pegar a representação textual de um número (na base 10) e convertê-la no número correspondente?" De um modo geral, os neófitos C e C ++ geralmente têm idéias incrivelmente nebulosas sobre como o texto funciona nessas linguagens e o que charrealmente significa.
Karl Knechtel
3
@KarlKnechtel: Se isso é verdade (eu dou cerca de 50/50, pois muitos tutoriais iniciais também incentivam a obtenção de valores ASCII de caracteres, mesmo que o ASCII não cubra toda a gama), o OP precisa ser esclarecido - mas isso é uma bobagem de stackoverflow.com/questions/439573/… .
Fred Nurk
3
O PO teve três horas para esclarecer esta questão e não conseguiu. Como é, não há como saber o que realmente é perguntado. Votou para fechar.
SBI

Respostas:

552

Depende do que você quer fazer:

para ler o valor como um código ascii, você pode escrever

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

para converter o personagem '0' -> 0, '1' -> 1, etc, você pode escrever

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

Explicação :
a - '0'é equivalente a ((int)a) - ((int)'0'), o que significa que os valores ascii dos caracteres são subtraídos um do outro. Como 0vem diretamente antes 1na tabela ascii (e assim por diante até 9), a diferença entre os dois fornece o número que o caractere arepresenta.

Foo Bah
fonte
14
ia = (a - '0')% 48;
Kshitij Banerjee
@KshitijBanerjee Essa não é uma boa ideia por dois motivos: fornece um número negativo para caracteres ascii antes de '0' (como &-> -10) e números maiores que 10 (como x-> 26)
SheetJS
2
int ia = a - '0' - que é o que você precisa
o funk
5
@ kevin001 Se você deseja converter o caractere para int e um caractere '1'fornece um número ASCII que não é 1, você precisa remover o deslocamento '0'para realinhar o número de 0 a 9. Os números consecutivos 1-9 são adjacentes no número inteiro ascii.
Krisdestruction
Nenhum elenco é obrigatório / desejado
Craig Estey
97

Bem, no código ASCII, os números (dígitos) começam em 48 . Tudo que você precisa fazer é:

int x = (int)character - 48;
Vlad Isoc
fonte
19
@chad: Não apenas mais legível, como também mais portátil. C e C ++ não garantem uma representação ASCII, mas garantem que, independentemente da representação em uso, as representações dos 10 dígitos decimais sejam contíguas e em ordem numérica.
Ben Voigt
A única coisa que eu teria mudado seria fazer 48 anos, o que parece um pouco "mágico" para'0'
ArielGro
59

C e C ++ sempre promovem tipos para pelo menos int. Além disso, literais de caracteres são do tipo intem C e charem C ++.

Você pode converter um chartipo simplesmente atribuindo a um int.

char c = 'a'; // narrowing on C
int a = c;
Matt Joiner
fonte
3
Você também pode usar o unário extremamente subestimado operator+()para esse fim.
Cubbi
24
-1 A resposta está incorreta para a única interpretação significativa da pergunta. Este (código int a = c;) manterá quaisquer valores negativos, com os quais as funções da biblioteca padrão C não podem lidar. As funções da biblioteca padrão C definem o padrão para o que significa manipular charvalores como int.
Saúde e hth. - Alf
6
@ Matt: Eu estou mantendo o voto negativo. Eu o reforçaria se possível! A interpretação da pergunta que você e outras pessoas assumiram não é significativa, porque é totalmente trivial e, porque, para a combinação específica de tipos do OP, existe uma questão prática muito importante e não tão trivial. O conselho que você dá é diretamente perigoso para o novato. Provavelmente resultará em Comportamento indefinido para seus programas que usam funções de classificação de caracteres de biblioteca padrão C. Ref. para a resposta de @ Sayam, ele excluiu essa resposta.
Saúde e hth. - Alf
3
-1 por estar incorreto: isupper () terá resultados indefinidos se for passado um caractere de 1252 highbit.
precisa
11
O que você quer dizer com "sempre promover"? Os valores são promovidos durante conversões implícitas, certos tipos de parâmetros passando (por exemplo, para uma função varargs) e quando um operador deve tornar seus operandos tipos compatíveis. Mas certamente há momentos em que um valor não é promovido (como se eu passar um caractere para uma função que espera um caractere); caso contrário, não teríamos nenhum tipo menor que um int.
Adrian McCarthy
31

char é apenas um número inteiro de 1 byte. Não há nada mágico com o tipo de caractere! Assim como você pode atribuir um curto a um int, ou um int a um longo, também pode atribuir um char a um int.

Sim, o nome do tipo de dados primitivo passa a ser "char", o que insinua que ele deve conter apenas caracteres. Mas, na realidade, "char" é apenas uma má escolha para confundir todos que tentam aprender o idioma. Um nome melhor para ele é int8_t e você pode usá-lo, se o seu compilador seguir o padrão C mais recente.

Embora, é claro, você deva usar o tipo char ao manipular string, porque o índice da tabela ASCII clássica cabe em 1 byte. No entanto, você também pode manipular cordas com ints regulares, embora não exista uma razão prática no mundo real para fazer isso. Por exemplo, o código a seguir funcionará perfeitamente:

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

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

Você precisa entender que caracteres e seqüências de caracteres são apenas números, como tudo o mais no computador. Quando você escreve 'a' no código-fonte, ele é pré-processado no número 97, que é uma constante inteira.

Então, se você escrever uma expressão como

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

isso é realmente equivalente a

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

que passa pelas promoções de números inteiros da linguagem C

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

e, em seguida, truncado para um caractere para caber no tipo de resultado

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

Há muitas coisas sutis como essas acontecendo nas entrelinhas, onde char é implicitamente tratado como int.

Lundin
fonte
Como a pergunta não está marcada ascii, você não deve assumir nenhuma codificação específica. Definir charigual a int8_testá errado porque poderia igualmente ser uint8_tou uint24_t.
Roland Illig 31/03
11
@RolandIllig Não, a charé sempre 1 byte e se os tipos int8_t/ uint8_texistirem no sistema fornecido (o que é muito provável), eles poderão ajustar o resultado de a char, porque serão 8 bits. Em sistemas altamente exóticos, como vários DSPs obsoletos, charhaverá 16 bits e uint8_teles não existirão. Escrever código para compatibilidade com DSPs obsoletos não faz sentido, assim como escrever para compatibilidade com os sistemas de complemento ou sinal e magnitude. Enorme perda de tempo, uma vez que tais sistemas mal existem no mundo real.
Lundin
18

(Esta resposta aborda o lado C ++, mas o problema de extensão de sinal também existe em C).

O manuseio dos três chartipos ( signed, unsignede char) é mais delicado do que parece à primeira vista. Os valores no intervalo de 0 a SCHAR_MAX(que é 127 para um de 8 bits char) são fáceis:

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

Mas, quando somevalueestá fora desse intervalo, apenas a unsigned charexecução fornece resultados consistentes para os "mesmos" charvalores nos três tipos:

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.

Isso é importante ao usar funções de ctype.h , como isupperou toupper, devido à extensão de sinal:

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

Observe que a conversão através de int está implícita; isso tem o mesmo UB:

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

Para corrigir isso, prossiga unsigned char, o que é feito facilmente, envolvendo as funções ctype.h por 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.

Isso funciona porque qualquer função que aceite um dos três tipos de caracteres também pode aceitar os outros dois tipos de caracteres. Isso leva a duas funções que podem lidar com qualquer um dos tipos:

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)sempre fornece um valor não negativo - mesmo quando passado como negativo charou negativo signed char- e chraceita qualquer valor que ordproduz e devolve exatamente o mesmo char.

Na prática, eu provavelmente apenas transmiti-lo em unsigned charvez de usá-los, mas eles encapsulam sucintamente o elenco, fornecem um local conveniente para adicionar verificação de erros para - e - e intfica charmais curto e mais claro quando você precisa usá-los várias vezes nas proximidades.

Fred Nurk
fonte
12

Use static_cast<int>:

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

Edit: Você provavelmente deve tentar evitar o uso(int)

int num = (int) letra;

confira Por que usar static_cast <int> (x) em vez de (int) x? para mais informações.

herohuyongtao
fonte
7

Depende do que você quer dizer com "converter".

Se você possui uma série de caracteres que representam um número inteiro, como "123456", existem duas maneiras comuns de fazer isso em C: Use uma conversão de finalidade especial como atoi () ou strtol () ou sscanf de uso geral () . O C ++ (que é realmente uma linguagem diferente que se disfarça de atualização) adiciona uma terceira sequência de strings.

Se você quer que o padrão de bits exato em uma de suas intvariáveis ​​seja tratado como um char, é mais fácil. Em C, os diferentes tipos de números inteiros são realmente mais um estado de espírito do que os "tipos" reais separados. Basta começar a usá-lo onde charfor solicitado e você deve estar bem. Você pode precisar de uma conversão explícita para fazer com que o compilador pare de choramingar de vez em quando, mas tudo o que você deve fazer é eliminar quaisquer bits extras além de 256.

TED
fonte
6

Eu tenho absolutamente nullhabilidades em C, mas para uma análise simples:

char* something = "123456";

int number = parseInt(something);

... isso funcionou para mim:

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
fonte
Esse código chama rapidamente um comportamento indefinido e, portanto, não é adequado para copiar e colar. (int overflow)
Roland Illig 31/03
4

Presumivelmente, você deseja essa conversão para usar funções da biblioteca padrão C.

Nesse caso, faça (sintaxe C ++)

typedef unsigned char UChar;

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

A expressão é UChar( c )convertida unsigned charem para se livrar de valores negativos, que, exceto o EOF, não são suportados pelas funções C.

Em seguida, o resultado dessa expressão é usado como argumento real para um intargumento formal. Para onde você recebe a promoção automática int. Como alternativa, você pode escrever explicitamente esse último passo int( UChar( c ) ), mas pessoalmente acho isso muito detalhado.

Cheers & hth.,

Felicidades e hth. - Alf
fonte
0

Eu estava tendo problemas para converter uma matriz de caracteres "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"em seu valor inteiro real que poderia ser representado por `7C 'como um valor hexadecimal. Então, depois de procurar ajuda, criei isso e achei que seria legal compartilhar.

Isso separa a sequência de caracteres char em seus números inteiros certos e pode ser útil para mais pessoas do que apenas para mim;)

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

Espero que ajude!

Mathorlaz
fonte
Você já testou esse código? O 50 deve ser 48, o 55 funciona apenas para letras ASCII maiúsculas, enquanto o seu exemplo contém letras minúsculas.
Roland Illig 31/03/19
0

Para char ou short para int, você só precisa atribuir o valor.

char ch = 16;
int in = ch;

O mesmo que o int64.

long long lo = ch;

Todos os valores serão 16.

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

Você pode usar esse método atoi para converter char para int. Para obter mais informações, você pode consultar este http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/string/stoi/ .

pranav suresh
fonte
11
Esse é um comportamento indefinido. Tomar o endereço de uma variável char fornecerá um char *, mas não uma string C, que é o que atoi espera.
luizfls