Converti la cifra di un carattere nel numero intero corrispondente in C


103

C'è un modo per convertire un carattere in un numero intero in C?

Ad esempio, da '5'a 5?

Risposte:


150

Come per altre risposte, va bene:

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

Inoltre, per il controllo degli errori, potresti voler controllare prima che isdigit (c) sia vero. Nota che non puoi fare lo stesso in modo completamente portabile per le lettere, ad esempio:

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

Lo standard garantisce che i valori dei caratteri per le cifre da "0" a "9" siano contigui, ma non garantisce per altri caratteri come le lettere dell'alfabeto.


3
@Paul Tomblin: Sì per le cifre, non per le lettere, perché, come ho detto nella risposta, lo standard garantisce che da "0" a "9" siano contigui ma non garantisce tali garanzie per altri caratteri come da "a" a "z".
Chris Young,

char c = 'b'; int x = c - 'a'; allora x sarà 1 solo in ASCII?
Pan

@Pan In qualsiasi codifica, incluso ASCII, che ha "b" 1 in più di "a". Questo è ancora vero in EBCDIC, tuttavia rende ('j' - 'i') == 8.
Chris Young

@ChrisYoung Why? Perché in EBCDIC, "j" non è maggiore di "i"?
Pan

2
Cosa mi manca qui dove non si usa atoi?
Daniel

41

Sottrai "0" in questo modo:

int i = c - '0';

Lo standard C garantisce che ogni cifra nell'intervallo '0'..'9'sia maggiore di una cifra rispetto alla cifra precedente (nella sezione 5.2.1/3della bozza C99 ). Lo stesso vale per C ++.


1
Questa risposta sarebbe migliore se dicessi che un carattere è / già / effettivamente un intero, albiet del segno definito dall'implementazione (cioè, potrebbe essere firmato o non firmato), ed è lungo CHAR_BITS.
Arafangion

Non ero sicuro di sapere che lo aiutasse davvero. ma Chris ha fatto un buon punto sul fatto che a..z non è necessariamente contigua. avrei dovuto menzionarlo invece. ora ha vinto la gara :)
Johannes Schaub - litb

1
La tua è migliore perché hai qualificato la tua risposta, però - Chris avrebbe potuto benissimo inventare le sue cose. :)
Arafangion

grazie per l'apprezzamento. ammetto che non ero sicuro dello stato di C. quindi ho guardato in alto e perché ci ero già ho incollato il riferimento nella risposta :)
Johannes Schaub - litb

E questo, signore, è il motivo per cui hai un paio di punti in più di me. :)
Arafangion

29

Se, per qualche folle coincidenza, vuoi convertire una stringa di caratteri in un intero, puoi farlo anche tu!

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

valora è 1024. Apparentemente atoi()va bene, e quello che ho detto prima vale solo per me (su OS X (forse (inserire la battuta Lisp qui))). Ho sentito che è una macro che mappa approssimativamente al prossimo esempio, che utilizza strtol(), invece, una funzione più generica per eseguire la conversione:

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

strtol() funziona così:

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

Si converte *strin a long, trattandolo come se fosse un basenumero base . Se **endptrnon è nullo, contiene il primo carattere non numerico strtol()trovato (ma a chi importa).


Non ci sono problemi di thread con atoi (non ha dati statici) e non è deprecato. Infatti è funzionalmente equivalente a: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran

5
Il problema con atoi è che utilizza 0 come valore "non riesco a trovare un numero qui", quindi atoi ("0") e atoi ("uno") restituiscono entrambi 0. Se non funziona per quello che tu ' lo stai usando per, cerca strtol () o sscanf ().
David Thornley,

L'altro vantaggio di strtol, ovviamente, è che potresti aver bisogno di leggere altre cose dalla stessa stringa che viene dopo il numero.
dfeuer

@EvanTeran Sfortunatamente se esegui Visual Studio ricevi un avviso di deprezzamento (e non si compila senza essere disabilitato). VS ora consiglia itoa_s().
Simon

7

Sottrai char '0' o int 48 in questo modo:

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

Spiegazione: Internamente funziona con il valore ASCII . Dalla tabella ASCII, il valore decimale del carattere 5 è 53 e 0 è 48 . Quindi 53-48 = 5

O

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

Ciò significa che se deduci 48 da qualsiasi carattere numerico, convertirà automaticamente il numero intero.


6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');

numeralChar - '0'è già di tipo int, quindi non hai bisogno del cast. Anche se non lo fosse, il cast non è necessario.
Alok Singhal,

Eh, sì, questo costringerebbe, no? Forse Java ha colorato le mie percezioni. O forse mi sbaglio completamente e potrebbe persino forzare in Java. :)
Kevin Conner

6

Per convertire la cifra del carattere nel numero intero corrispondente. Fai come mostrato di seguito:

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

La logica alla base del calcolo di cui sopra è giocare con i valori ASCII. Il valore ASCII del carattere 8 è 56, il valore ASCII del carattere 0 è 48. Il valore ASCII dell'intero 8 è 8.

Se sottraiamo due caratteri, la sottrazione avverrà tra ASCII di caratteri.

int i = 56 - 48;   
i = 8;

Perché sono l'unico a votare questo? La spiegazione è così semplice e istruttiva: +1:
Brandon Benefield

0

Se è solo un singolo carattere 0-9 in ASCII, la sottrazione del valore del carattere zero ASCII dal valore ASCII dovrebbe funzionare correttamente.

Se vuoi convertire numeri più grandi, allora farà quanto segue:

char *string = "24";

int value;

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

** non dimenticare di controllare lo stato (che dovrebbe essere 1 se ha funzionato nel caso precedente).

Paolo.


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

0

Quando ho bisogno di fare qualcosa del genere, preparo un array con i valori che desidero.

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

Quindi la conversione è facile

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

Questo è fondamentalmente l'approccio adottato da molte implementazioni della libreria ctype. Puoi banalmente adattarlo per funzionare anche con cifre esadecimali.


Sembra estremamente inefficiente per convertire una singola cifra decimale (o ottale). Se la parte rilevante della tua tabella di ricerca non si trova nella cache L1, farai saltare un sacco di cicli per inserirla solo per ottenere un valore. Francamente, tendo a dubitare che questa sia anche una buona idea se stai convertendo un'intera sfilza di cifre, ma dovresti misurarlo. È molto più competitivo per la maledizione, ovviamente.
dfeuer

0

Controllare questo,

char s='A';

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

solo per 0,1,2, ...., E, F.


0

Usa la atol()funzione:

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

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

}

0

Se la tua cifra è, diciamo, '5'in ASCII, è rappresentata come numero binario 0011 0101(53). Ogni cifra ha i quattro bit più alti 0011e i 4 bit più bassi rappresentano la cifra in bcd. Quindi fallo e basta

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

per ottenere i 4 bit più bassi o, cosa è uguale, la cifra. In asm, usa andoperation invece di sub(come nelle altre risposte).


'5'è 53 ( 00110101)
eyllanesc

@eyllanesc All'inizio era un 4. Grazie. Modificato.
Garmekain

0

Ecco le funzioni di supporto che consentono di convertire digit in char in int e viceversa:

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

char toChar(int i) {
    return i + '0';
}

-2

usa la funzione: atoi per array su intero, atof per array su float tipo; o

char c = '5';
int b = c - 48;
printf("%d", b);

Diverse risposte hanno già coperto questo. Questo non aggiunge nulla che non abbiano già trattato.
ShadowRanger

-3

Dovresti lanciarlo su un int (o float o double o qualsiasi altra cosa tu voglia fare con esso) e memorizzarlo in una variabile anoter.

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.