Zamień cyfrę znaku na odpowiednią liczbę całkowitą w C

103

Czy istnieje sposób przekonwertowania znaku na liczbę całkowitą w C?

Na przykład od '5'do 5?

Pływ
źródło

Odpowiedzi:

150

Jak w przypadku innych odpowiedzi, to jest w porządku:

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

Ponadto, aby sprawdzić błędy, możesz chcieć najpierw sprawdzić, czy isdigit (c) jest prawdziwe. Zauważ, że nie możesz całkowicie przenosić tego samego dla liter, na przykład:

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

Standard gwarantuje, że wartości znaków dla cyfr od „0” do „9” są ciągłe, ale nie gwarantuje, że będą stosowane inne znaki, takie jak litery alfabetu.

Chris Young
źródło
3
@Paul Tomblin: Tak dla cyfr, a nie liter, ponieważ, jak powiedziałem w odpowiedzi, standardowe gwarancje od „0” do „9” są ciągłe, ale nie zapewniają takich gwarancji dla innych znaków, takich jak „a” do „z”.
Chris Young
char c = 'b'; int x = c - 'a'; wtedy x będzie równe 1 tylko w ASCII?
Pan
@Pan W dowolnym kodowaniu, w tym ASCII, w którym „b” 1 jest większe niż „a”. To nadal jest prawdą w EBCDIC, jednak sprawia, że ​​('j' - 'i') == 8.
Chris Young
@ChrisYoung Dlaczego? Bo w EBCDIC „j” nie jest większe o 1 niż „i”?
Pan
2
Czego mi brakuje, gdy atoi nie jest używane?
Daniel
41

Odejmij „0” w ten sposób:

int i = c - '0';

C standardowe zapewnia każda cyfra w zakresie '0'..'9'jest większa od poprzedniej cyfry (w przekroju 5.2.1/3w zanurzeniu C99 ). To samo dotyczy C ++.

Johannes Schaub - litb
źródło
1
Ta odpowiedź byłaby lepsza, gdybyś wspomniał, że znak jest / już / efektywnie liczbą całkowitą, albiet ze znakiem zdefiniowanym w implementacji (tj. Może być podpisany lub bez znaku) i ma długość CHAR_BITS.
Arafangion
Nie byłam pewna, czy to naprawdę mu pomaga. ale Chris miał rację, mówiąc, że a..z niekoniecznie są ciągłe. Powinienem był o tym wspomnieć. teraz wygrał wyścig :)
Johannes Schaub - litb
1
Twoja jest lepsza, ponieważ masz kwalifikowaną odpowiedź - Chris mógł po prostu wymyślić swoje rzeczy. :)
Arafangion
dzięki za uznanie. przyznaję, że nie byłem pewien co do stanu C. więc spojrzałem w górę i ponieważ już na tym byłem, wkleiłem odniesienie do odpowiedzi :)
Johannes Schaub - litb
I dlatego, sir, ma pan kilka punktów więcej niż ja. :)
Arafangion
29

Jeśli jakimś szalonym zbiegiem okoliczności chcesz przekonwertować ciąg znaków na liczbę całkowitą, też możesz to zrobić!

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

valwynosi teraz 1024. Najwyraźniej atoi()jest w porządku, a to, co powiedziałem o tym wcześniej, dotyczy tylko mnie (na OS X (być może (wstaw żart Lispa tutaj))). Słyszałem, że jest to makro, które mapuje z grubsza do następnego przykładu, który używa strtol()funkcji bardziej ogólnego przeznaczenia, aby wykonać konwersję:

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

strtol() działa tak:

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

Przekształca *strsię w a long, traktując ją tak, jakby była baseliczbą podstawową . Jeśli **endptrnie jest null, przechowuje pierwszy strtol()znaleziony znak niebędący cyfrą (ale kogo to obchodzi).

Chris Lutz
źródło
Atoi nie ma problemów z wątkami (nie ma danych statycznych) i nie jest przestarzałe. W rzeczywistości jest on funkcjonalnie równoważne #define atoi (X) (int) (strtol ((x), zero, 10)
Evan Teran
5
Problem z atoi polega na tym, że używa 0 jako wartości „nie można tu znaleźć liczby”, więc atoi („0”) i atoi („jeden”) zwracają 0. Jeśli to nie zadziała w przypadku tego, co robisz ' ponownie go używać, poszukaj strtol () lub sscanf ().
David Thornley,
Inną zaletą strtol jest oczywiście to, że możesz potrzebować przeczytać inne rzeczy z tego samego ciągu, które pojawiają się po liczbie.
dfeuer,
@EvanTeran Niestety, jeśli uruchomisz Visual Studio, otrzymasz ostrzeżenie o deprecjacji (i nie będziesz kompilować bez wyłączania). VS teraz zaleca itoa_s().
Simon,
7

Odejmij znak „0” lub int 48 w ten sposób:

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

Objaśnienie: Wewnętrznie działa z wartością ASCII . W tabeli ASCII wartość dziesiętna znaku 5 to 53, a 0 to 48 . Czyli 53 - 48 = 5

LUB

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

Oznacza to, że jeśli odejmiesz 48 od dowolnego znaku liczbowego, automatycznie skonwertuje on liczbę całkowitą.

Arif
źródło
6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');
Kevin Conner
źródło
numeralChar - '0'jest już typu int, więc nie potrzebujesz obsady. Nawet gdyby tak nie było, obsada nie jest potrzebna.
Alok Singhal
Huh, tak, to by zmusiło, prawda? Może Java ubarwiła moje wyobrażenia. A może całkowicie się mylę i nawet w Javie to by się zmusiło. :)
Kevin Conner
6

Konwersja cyfry znaku na odpowiednią liczbę całkowitą. Zrób, jak pokazano poniżej:

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

Logika stojąca za powyższymi obliczeniami polega na zabawie z wartościami ASCII. Wartość ASCII znaku 8 to 56, wartość ASCII znaku 0 to 48. Wartość ASCII liczby całkowitej 8 to 8.

Jeśli odejmiemy dwa znaki, odejmowanie nastąpi między znakami ASCII.

int i = 56 - 48;   
i = 8;
Ashish
źródło
Dlaczego tylko ja głosuję za tym? Wyjaśnienie jest tak proste i pouczające: +1:
Brandon Benefield
0

Jeśli jest to tylko pojedynczy znak 0-9 w ASCII, odjęcie wartości znaku zerowego ASCII od wartości ASCII powinno działać poprawnie.

Jeśli chcesz przekonwertować większe liczby, wykonaj następujące czynności:

char *string = "24";

int value;

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

** nie zapomnij sprawdzić statusu (który powinien wynosić 1, jeśli zadziałał w powyższym przypadku).

Paweł.

Paul W. Homer
źródło
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
źródło
0

Kiedy muszę zrobić coś takiego, wstępnie wypalam tablicę z wartościami, które chcę.

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

Wtedy konwersja jest łatwa

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

Jest to w zasadzie podejście przyjęte przez wiele implementacji biblioteki ctype. Możesz to w prosty sposób dostosować do pracy z cyframi szesnastkowymi.

Michael Anderson
źródło
Wydaje się to wyjątkowo nieefektywne w przypadku konwersji pojedynczej cyfry dziesiętnej (lub ósemkowej). Jeśli odpowiednia część tabeli przeglądowej nie znajduje się w pamięci podręcznej L1, wydmuchasz kilka cykli, aby pobrać ją tylko po to, aby uzyskać jedną wartość. Szczerze mówiąc, wątpię, czy to nawet dobry pomysł, jeśli konwertujesz całą masę cyfr, ale musiałbyś to zmierzyć. Oczywiście jest znacznie bardziej konkurencyjny dla hexów.
dfeuer
0

Sprawdź to,

char s='A';

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

tylko za 0,1,2, ...., E, F.

siedmiodniowa żałoba
źródło
0

Po prostu użyj atol()funkcji:

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

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

}
Dylan halls
źródło
0

Jeśli twoja cyfra jest, powiedzmy, '5'w ASCII, jest reprezentowana jako liczba binarna 0011 0101(53). Każda cyfra ma najwyższe cztery bity, 0011a najniższe 4 bity reprezentują cyfrę w bcd. Więc po prostu to robisz

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

aby uzyskać najniższe 4 bity lub, co to jest, cyfrę. W asm używa andoperacji zamiast sub(jak w innych odpowiedziach).

Garmekain
źródło
'5'jest 53 ( 00110101)
eyllanesc
@eyllanesc Na początku było to 4. Dzięki. Edytował to.
Garmekain
0

Oto funkcje pomocnicze, które pozwalają konwertować cyfry w znakach na int i odwrotnie:

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

char toChar(int i) {
    return i + '0';
}
Maxim Makhun
źródło
-2

użyj funkcji: atoi dla tablicy na liczbę całkowitą, atof dla tablicy na typ zmiennoprzecinkowy; lub

char c = '5';
int b = c - 48;
printf("%d", b);
K.tin
źródło
Kilka odpowiedzi już to obejmowało. To dodaje niczego, czego jeszcze nie opisali.
ShadowRanger
-3

Rzutowałbyś go na int (lub float, double lub cokolwiek innego, co chcesz z nim zrobić) i przechowałbyś w innej zmiennej.

SeanJA
źródło