Converti char in int in C e C ++


401

Come posso convertire a charin un intin C e C ++?


1
@Matt: sarebbe una buona idea essere più concreti. chiedere una generalizzazione invita solo risposte generalizzate che non sono applicabili o addirittura corrette per il tuo compito. tieni presente che, quando devi chiedere, probabilmente non sai abbastanza per generalizzare correttamente.
Saluti e hth. - Alf,

@Alf P. Steinbach: la domanda originale era vaga riguardo a quale lingua. Con le parole chiave ce c++, penso che le risposte che affrontano entrambe le lingue siano ragionevoli.
Matt Joiner,

8
Dalla mia vasta esperienza su altri forum tecnici, la mia intuizione è che il PO significhi davvero "come posso prendere la rappresentazione testuale di un numero (in base 10) e convertirlo nel numero corrispondente?" In generale, i neofiti C e C ++ di solito hanno idee incredibilmente confuse su come funziona il testo in quelle lingue e cosa charsignifica veramente.
Karl Knechtel,

3
@KarlKnechtel: se questo è vero (lo do circa il 50/50 dato che molti tutorial iniziali incoraggiano anche a ottenere valori ASCII dai caratteri, anche se ASCII non copre l'intero intervallo), l'OP deve fare chiarezza, ma questo è un dupe di stackoverflow.com/questions/439573/… .
Fred Nurk,

3
Il PO ha avuto tre ore per chiarire questa domanda e non è riuscito a farlo. Così com'è, non c'è modo di sapere cosa viene effettivamente chiesto. Votato per chiudere.
sabato

Risposte:


552

Dipende da cosa vuoi fare:

per leggere il valore come codice ASCII, è possibile scrivere

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

per convertire il carattere '0' -> 0, '1' -> 1ecc, è possibile scrivere

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

Spiegazione :
a - '0'è equivalente a ((int)a) - ((int)'0'), il che significa che i valori ascii dei caratteri vengono sottratti l'uno dall'altro. Poiché 0viene direttamente prima 1nella tabella ASCII (e così via fino a 9), la differenza tra i due dà il numero che il personaggio arappresenta.


14
ia = (a - '0')% 48;
Kshitij Banerjee,

@KshitijBanerjee Non è una buona idea per due motivi: ti dà un numero negativo per i caratteri ASCII prima di '0' (come &-> -10) e ti dà numeri maggiori di 10 (come x-> 26)
SheetJS

2
int ia = a - '0' - ecco di cosa hai bisogno
funk

5
@ kevin001 Se si desidera convertire il carattere in int e un carattere '1'fornisce un numero ASCII che non lo è 1, è necessario rimuovere l'offset '0'per riallinearlo per contare da 0-9. I numeri consecutivi 1-9 sono adiacenti al numero intero ASCII.
krisdestruction,

Nessun cast è richiesto / desiderato
Craig Estey,

97

Bene, nel codice ASCII, i numeri (cifre) iniziano da 48 . Tutto quello che devi fare è:

int x = (int)character - 48;

19
@chad: non solo più leggibile, ma anche più portatile. C e C ++ non garantiscono una rappresentazione ASCII, ma garantiscono che qualunque rappresentazione sia in uso, le rappresentazioni delle 10 cifre decimali sono contigue e in ordine numerico.
Ben Voigt,

L'unica cosa che avrei cambiato è girare la 48, che sembra un po '"magica" a'0'
ArielGro

59

C e C ++ promuovono sempre i tipi almeno int. Inoltre i caratteri letterali sono di tipo intin C e charin C ++.

È possibile convertire un chartipo semplicemente assegnando a un int.

char c = 'a'; // narrowing on C
int a = c;

3
A questo scopo potresti anche usare l'unicamente gravemente sottovalutato operator+() .
Cubbi,

24
-1 La risposta è errata per l'unica interpretazione significativa della domanda. Questo (codice int a = c;) manterrà tutti i valori negativi, che le funzioni di libreria C standard non possono gestire. Le funzioni della libreria standard C definiscono lo standard per ciò che significa gestire i charvalori come int.
Saluti e hth. - Alf,

6
@Matt: sto mantenendo il downvote. Lo rafforzerei se possibile! L'interpretazione della domanda che tu e gli altri avete assunto non è significativa, perché è troppo del tutto banale e perché per la particolare combinazione di tipi del PO c'è una questione pratica non così banale molto importante. Il consiglio che dai è direttamente pericoloso per il principiante. Molto probabilmente comporterà un comportamento indefinito per i loro programmi che utilizzano le funzioni di classificazione dei caratteri della libreria C standard. Rif. alla risposta di @ Sayam, ha eliminato quella risposta.
Saluti e hth. - Alf,

3
-1 per essere errato: isupper () avrà risultati indefiniti se viene passato un carattere highbit 1252.
Chris Becke,

1
Cosa intendi con "promuovi sempre"? I valori vengono promossi durante le conversioni implicite, alcuni tipi di parametri che passano (ad es. A una funzione varargs) e quando un operatore deve rendere i suoi operandi tipi compatibili. Ma ci sono certamente momenti in cui un valore non viene promosso (come se un I passi un carattere a una funzione in attesa di un carattere), altrimenti non avremmo alcun tipo più piccolo di un int.
Adrian McCarthy,

31

char è solo un numero intero di 1 byte. Non c'è nulla di magico con il tipo di carattere! Così come puoi assegnare un short a un int o un int a un long, puoi assegnare un char a un int.

Sì, il nome del tipo di dati primitivo sembra essere "char", il che insinua che dovrebbe contenere solo caratteri. Ma in realtà, "char" è solo un povero nome scelto per confondere tutti coloro che cercano di imparare la lingua. Un nome migliore per questo è int8_t, e puoi invece usare quel nome, se il tuo compilatore segue l'ultimo standard C.

Sebbene, naturalmente, dovresti usare il tipo char quando esegui la gestione delle stringhe, perché l'indice della classica tabella ASCII si adatta a 1 byte. Si potrebbe tuttavia fare la gestione delle stringhe con interi normale così, anche se non v'è alcuna ragione pratica nel mondo reale motivo per cui si vorrebbe mai farlo. Ad esempio, il seguente codice funzionerà perfettamente:

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

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

Devi capire che i caratteri e le stringhe sono solo numeri, come tutto il resto nel computer. Quando scrivi 'a' nel codice sorgente, viene pre-elaborato nel numero 97, che è una costante intera.

Quindi se scrivi un'espressione simile

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

questo è in realtà equivalente a

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

che passa quindi attraverso le promozioni di numeri interi in linguaggio C.

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

e quindi troncato a un carattere per adattarsi al tipo di risultato

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

Ci sono molte cose sottili come questa tra le righe, in cui char è implicitamente trattato come un int.


Poiché la domanda non è taggata con ascii, non dovresti assumere alcuna codifica specifica. L'impostazione charuguale a int8_tè errata perché potrebbe ugualmente essere uint8_to uint24_t.
Roland Illig,

1
@RolandIllig No, a charè sempre 1 byte e se i tipi int8_t/ uint8_tesistono su un determinato sistema (che è molto probabile), saranno in grado di adattarsi al risultato di un char, perché sarà quindi di 8 bit. Su sistemi altamente esotici come vari DSP obsoleti, charsaranno 16 bit e uint8_tnon esisteranno. Scrivere codice per la compatibilità con DSP obsoleti non ha senso, così come scrivere per la compatibilità con i propri sistemi di complemento o segno e grandezza. Enorme perdita di tempo, dal momento che tali sistemi a malapena esistono nel mondo reale.
Lundin,

18

(Questa risposta si rivolge al lato C ++ delle cose, ma il problema dell'estensione del segno esiste anche in C).

Manipolazione tutti e tre i chartipi ( signed, unsigned, e char) è più delicato di quello che appare prima. I valori nell'intervallo da 0 a SCHAR_MAX(che è 127 per un 8 bit char) sono semplici:

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

Ma, quando somevalueè al di fuori di tale intervallo, solo passare attraverso unsigned charti dà risultati coerenti per gli "stessi" charvalori in tutti e tre i tipi:

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.

Questo è importante quando si usano le funzioni di ctype.h , come isuppero toupper, a causa dell'estensione del segno:

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

Si noti che la conversione tramite int è implicita; questo ha lo stesso UB:

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

Per risolvere questo problema, vai avanti unsigned char, cosa che si può fare facilmente avvolgendo le funzioni ctype.h tramite 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.

Questo funziona perché qualsiasi funzione che accetta uno dei tre tipi di carattere può prendere anche gli altri due tipi di carattere. Porta a due funzioni che possono gestire qualsiasi tipo:

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)ti dà sempre un valore non negativo - anche quando viene passato un valore negativo charo negativo signed char- e chrprende qualsiasi valore ordproduce e restituisce esattamente lo stesso char.

In pratica, probabilmente verrei semplicemente a sfogliarlo unsigned charinvece di usarli, ma avvolgono in modo succinto il cast, forniscono un posto conveniente per aggiungere il controllo degli errori per int-to- chare sarebbero più brevi e più chiari quando è necessario utilizzarli più volte nelle vicinanze.



7

Dipende da cosa intendi per "convertire".

Se hai una serie di caratteri che rappresenta un numero intero, come "123456", allora ci sono due modi tipici per farlo in C: Usa una conversione per scopi speciali come atoi () o strtol () o lo sscanf per scopi generici () . Il C ++ (che in realtà è un linguaggio diverso mascherato da aggiornamento) aggiunge un terzo, stringhe di stream.

Se vuoi dire che vuoi che lo schema di bit esatto in una delle tue intvariabili sia trattato come un char, è più facile. In C i diversi tipi interi sono in realtà più di uno stato d'animo rispetto ai "tipi" separati effettivi. Inizia a usarlo dove charsono richiesti e dovresti essere OK. Potresti aver bisogno di una conversione esplicita per far sì che il compilatore smetta di piagnucolare occasionalmente, ma tutto ciò che dovrebbe fare è eliminare eventuali bit extra oltre 256.


6

Ho delle nullabilità assolute in C, ma per una semplice analisi:

char* something = "123456";

int number = parseInt(something);

... questo ha funzionato per me:

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

Questo codice richiama rapidamente comportamenti indefiniti e non è quindi adatto per copia e incolla. (int overflow)
Roland Illig

4

Presumibilmente vuoi questa conversione per usare le funzioni della libreria standard C.

In tal caso, do (sintassi C ++)

typedef unsigned char UChar;

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

L'espressione viene UChar( c )convertita unsigned charin per eliminare i valori negativi che, ad eccezione di EOF, non sono supportati dalle funzioni C.

Quindi il risultato di quell'espressione viene usato come argomento effettivo per un intargomento formale. Dove si ottiene la promozione automatica int. In alternativa puoi scrivere esplicitamente l'ultimo passaggio, come int( UChar( c ) ), ma personalmente lo trovo troppo dettagliato.

Saluti e hth.,


0

Avevo problemi a convertire un array di caratteri come "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"nel suo valore intero effettivo che sarebbe stato rappresentato da `7C 'come un valore esadecimale. Quindi, dopo aver navigato per chiedere aiuto, l'ho creato e ho pensato che sarebbe stato bello condividerlo.

Questo separa la stringa di caratteri nei suoi numeri interi giusti e può essere utile a più persone rispetto a me;)

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

Spero che sia d'aiuto!


Hai mai provato questo codice? Il 50 dovrebbe essere un 48, il 55 funziona solo per lettere ASCII maiuscole mentre il tuo esempio contiene lettere minuscole.
Roland Illig,

0

Per char o short to int, devi solo assegnare il valore.

char ch = 16;
int in = ch;

Lo stesso per int64.

long long lo = ch;

Tutti i valori saranno 16.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.