Konwertuj char na int w C i C ++

400

Jak przekonwertować charna A intw C i C ++?

mainajaved
źródło
1
@Matt: Byłoby dobrym pomysłem być bardziej konkretnym. pytanie o uogólnienie po prostu zaprasza uogólnione odpowiedzi, które nie mają zastosowania, a nawet nie są poprawne dla twojego zadania. pamiętaj, że kiedy musisz zapytać, prawdopodobnie nie wiesz wystarczająco dużo, aby poprawnie uogólnić.
Pozdrawiam i hth. - Alf
@Alf P. Steinbach: Pierwotne pytanie było niejasne co do tego, który język. Ze słowami kluczowymi ci c++myślę, że odpowiedzi na oba języki są rozsądne.
Matt Joiner
8
Z mojego bogatego doświadczenia na innych forach technicznych, intuicję, że OP naprawdę oznacza „jak wziąć tekstową reprezentację liczby (w bazie 10) i przekonwertować ją na odpowiedni numer?” Ogólnie rzecz biorąc, neofici C i C ++ zwykle mają bardzo niewyraźne wyobrażenia o tym, jak tekst działa w tych językach i co chartak naprawdę oznacza.
Karl Knechtel
3
@KarlKnechtel: Jeśli to prawda (podaję około 50/50, ponieważ wiele wczesnych samouczków zachęca również do uzyskiwania wartości ASCII z znaków, nawet jeśli ASCII nie obejmuje pełnego zakresu), OP musi być klarowne - ale to jest dupek z stackoverflow.com/questions/439573/... .
Fred Nurk
3
OP miał trzy godziny na wyjaśnienie tego pytania i tego nie zrobił. W tej chwili nie ma sposobu, aby dowiedzieć się, o co tak naprawdę pytano. Zagłosowano zamknąć.
sbi

Odpowiedzi:

551

Zależy od tego, co chcesz zrobić:

aby odczytać wartość jako kod ascii, możesz napisać

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

przekształcić charakter '0' -> 0, '1' -> 1itd, można napisać

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

Objaśnienie :
a - '0'jest równoważne ((int)a) - ((int)'0'), co oznacza, że ​​wartości ascii znaków są odejmowane od siebie. Ponieważ 0pojawia się bezpośrednio 1w tabeli ascii (i tak dalej 9), różnica między nimi daje liczbę areprezentowaną przez postać .

Foo Bah
źródło
14
ia = (a - „0”)% 48;
Kshitij Banerjee
@KshitijBanerjee To nie jest dobry pomysł z dwóch powodów: podaje liczbę ujemną dla znaków ascii przed „0” (jak &-> -10) i daje liczby większe niż 10 (jak x-> 26)
SheetJS
2
int ia = a - „0” - to jest to, czego potrzebujesz
funk
5
@ kevin001 Jeśli chcesz przekonwertować znak na int, a znak '1'podaje liczbę ascii, której nie ma 1, musisz usunąć przesunięcie, '0'aby wyrównać go, aby liczyć od 0-9. Kolejne liczby 1-9 sąsiadują z liczbą całkowitą ascii.
krisdestruction
Nie jest wymagana / wymagana obsada
Craig Estey
97

Cóż, w kodzie ASCII cyfry (cyfry) zaczynają się od 48 . Wszystko, co musisz zrobić, to:

int x = (int)character - 48;
Vlad Isoc
źródło
19
@chad: Nie tylko bardziej czytelny, ale także bardziej przenośny. C i C ++ nie gwarantują reprezentacji ASCII, ale gwarantują, że niezależnie od reprezentacji, która jest używana, reprezentacje 10 cyfr dziesiętnych są ciągłe i w kolejności numerycznej.
Ben Voigt
Jedyne, co bym zmienił, to obrócenie 48, co wydaje się nieco „magiczne” dla'0'
ArielGro
59

C i C ++ zawsze promują typy przynajmniej do int. Ponadto literały znakowe są typu intC i charC ++.

Możesz przekonwertować chartyp, po prostu przypisując do int.

char c = 'a'; // narrowing on C
int a = c;
Matt Joiner
źródło
3
Możesz również użyć do tego celu bardzo niedocenionego unarskiego operator+() .
Cubbi
24
-1 Odpowiedź jest nieprawidłowa dla jedynej sensownej interpretacji pytania. Ten (kod int a = c;) zachowuje wszelkie wartości ujemne, z którymi standardowe funkcje biblioteki C nie mogą sobie poradzić. Funkcje biblioteki standardowej C określają standard obsługi charwartości jako int.
Pozdrawiam i hth. - Alf
6
@Matt: Trzymam głos. Wzmocnię to, jeśli to możliwe! Interpretacja pytania, którą przyjęliście ty i inni, nie jest znacząca, ponieważ jest zbyt trywialna, a ponieważ dla szczególnej kombinacji typów PO istnieje nie tak trywialna bardzo ważna kwestia praktyczna. Porady, które udzielasz, są bezpośrednio niebezpieczne dla nowicjusza. Najprawdopodobniej spowoduje to niezdefiniowane zachowanie ich programów, które używają standardowych funkcji klasyfikacji znaków w bibliotece C. Re ref. na odpowiedź @ Sayama usunął tę odpowiedź.
Pozdrawiam i hth. - Alf
3
-1 za niepoprawne: isupper () będzie miał niezdefiniowane wyniki, jeśli przejdzie znak 1252 highbit.
Chris Becke,
1
Co rozumiesz przez „zawsze promuj”? Wartości są promowane podczas niejawnych konwersji, przekazywania pewnych typów parametrów (np. Do funkcji varargs) i gdy operator musi ustawić typy operandów na kompatybilne. Ale z pewnością są chwile, kiedy wartość nie jest promowana (np. Jeśli przekazuję znak do funkcji oczekującej znaku), w przeciwnym razie nie mielibyśmy żadnych typów mniejszych niż int.
Adrian McCarthy
31

char jest tylko 1-bajtową liczbą całkowitą. W typie char nie ma nic magicznego! Tak jak możesz przypisać skrót do int lub int do long, możesz przypisać char do int.

Tak, nazwa pierwotnego typu danych to „char”, co sugeruje, że powinien on zawierać tylko znaki. Ale w rzeczywistości „char” to po prostu kiepskie imię, które może dezorientować każdego, kto próbuje nauczyć się języka. Lepszą nazwą jest int8_t i możesz użyć tej nazwy, jeśli kompilator jest zgodny z najnowszym standardem C.

Chociaż oczywiście powinieneś używać typu char podczas obsługi łańcucha, ponieważ indeks klasycznej tabeli ASCII mieści się w 1 bajcie. Państwo mogli jednak zrobić obsługę łańcuchów z regularnych wskazówki jak dobrze, chociaż nie ma praktycznego powodu, w realnym świecie, dlaczego kiedykolwiek chcesz to zrobić. Na przykład następujący kod będzie działał idealnie:

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

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

Musisz zdać sobie sprawę, że znaki i ciągi są po prostu cyframi, jak wszystko inne na komputerze. Kiedy piszesz „a” w kodzie źródłowym, jest on wstępnie przetwarzany na liczbę 97, która jest stałą całkowitą.

Więc jeśli napiszesz wyrażenie podobne do

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

jest to faktycznie równoważne z

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

który następnie przechodzi przez promocje liczb całkowitych w języku C.

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

a następnie obcięty do znaku, aby dopasować do typu wyniku

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

Między wierszami dzieje się wiele subtelnych rzeczy, takich jak char, domyślnie traktowanych jako int.

Lundin
źródło
Ponieważ pytanie nie jest oznaczone ascii, nie należy zakładać żadnego konkretnego kodowania. Ustawienie charrówności int8_tjest nieprawidłowe, ponieważ równie prawdopodobne może być uint8_tlub uint24_t.
Roland Illig
1
@RolandIllig Nie, a charma zawsze 1 bajt, a jeśli typy int8_t/ uint8_tistnieją w danym systemie (co jest bardzo prawdopodobne), będą one w stanie dopasować wynik a char, ponieważ będzie to wtedy 8 bitów. W wysoce egzotycznych systemach, takich jak różne przestarzałe DSP, charbędzie 16 bitów i uint8_tnie będzie istniał. Pisanie kodu dla zgodności z przestarzałymi procesorami DSP jest nonsensem, podobnie jak pisanie dla zgodności z własnymi systemami komplementarnymi lub znakowymi i wielkościowymi. Ogromna strata czasu, ponieważ takie systemy prawie nie istnieją w prawdziwym świecie.
Lundin,
18

(Ta odpowiedź dotyczy strony C ++, ale problem rozszerzenia znaku istnieje również w C.)

Obsługa wszystkich trzech chartypów ( signed, unsignedi char) jest delikatniejsza niż się wydaje. Wartości w zakresie od 0 do SCHAR_MAX(czyli 8 dla 8-bitów char) są łatwe:

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

Ale gdy somevalueznajduje się poza tym zakresem, przejście tylko unsigned chardaje spójne wyniki dla „tych samych” charwartości we wszystkich trzech typach:

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.

Jest to ważne, gdy używasz funkcji z ctype.h , takich jak isupperlub toupper, z powodu rozszerzenia znaku:

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

Zauważ, że konwersja przez int jest niejawna; to ma ten sam UB:

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

Aby to naprawić, przejdź przez unsigned char, co można łatwo zrobić, pakując funkcje ctype.h poprzez 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.

Działa to, ponieważ dowolna funkcja przyjmująca dowolny z trzech typów znaków może również przyjmować pozostałe dwa typy znaków. Prowadzi to do dwóch funkcji, które mogą obsługiwać dowolny z typów:

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)zawsze daje wartość nieujemną - nawet jeśli minęła wartość ujemna charlub ujemna signed char- i chrprzyjmuje dowolną wartość ordprodukowaną i zwraca dokładnie to samo char.

W praktyce prawdopodobnie po prostu przerzuciłbym unsigned charzamiast ich używać, ale zwięźle owijają one obsadę, zapewniają wygodne miejsce do dodawania sprawdzania błędów dla int-to- char, i byłyby krótsze i wyraźniejsze, gdy trzeba ich użyć kilka razy w bliskiej odległości.

Fred Nurk
źródło
7

To zależy od tego, co rozumiesz przez „konwersję”.

Jeśli masz serię znaków reprezentujących liczbę całkowitą, na przykład „123456”, możesz to zrobić w C na dwa typowe sposoby: użyj konwersji specjalnego przeznaczenia, takiej jak atoi () lub strtol () , lub ogólnego przeznaczenia sscanf () . C ++ (który tak naprawdę jest innym językiem udającym uaktualnienie) dodaje trzeci ciąg znaków.

Jeśli masz na myśli, że chcesz, aby dokładny wzór bitowy w jednej ze intzmiennych był traktowany jako a char, to łatwiejsze. W C różne typy liczb całkowitych są bardziej stanem umysłu niż rzeczywiste osobne „typy”. Po prostu zacznij go używać tam, gdzie charsą o to poproszone, i powinieneś być OK. Możesz potrzebować wyraźnej konwersji, aby kompilator przestał narzekać, ale wszystko, co powinieneś zrobić, to usunąć wszelkie dodatkowe bity powyżej 256.

PRZETRZĄSAĆ
źródło
6

Mam absolutnie nullumiejętności w C, ale do prostej analizy:

char* something = "123456";

int number = parseInt(something);

... to zadziałało dla mnie:

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
źródło
Ten kod szybko wywołuje niezdefiniowane zachowanie, dlatego nie nadaje się do kopiowania i wklejania. (int przelew)
Roland Illig
4

Prawdopodobnie chcesz tej konwersji do korzystania z funkcji ze standardowej biblioteki C.

W takim przypadku wykonaj (składnia C ++)

typedef unsigned char UChar;

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

Wyrażenie UChar( c )konwertuje na unsigned char, aby pozbyć się wartości ujemnych, które oprócz EOF nie są obsługiwane przez funkcje C.

Następnie wynik tego wyrażenia jest używany jako rzeczywisty argument argumentu intformalnego. Gdzie otrzymujesz automatyczną promocję na int. Możesz alternatywnie napisać ten ostatni krok wprost, na przykład int( UChar( c ) ), ale osobiście uważam, że jest to zbyt szczegółowe.

Pozdrawiam i hth.,

Pozdrawiam i hth. - Alf
źródło
0

Miałem problemy z konwersją tablicy znaków jak "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"na jej rzeczywistą wartość całkowitą, którą można by przedstawić jako `7C 'jako jedną wartość szesnastkową. Więc po tym, jak poprosiłem o pomoc, stworzyłem to i pomyślałem, że fajnie byłoby się z tym podzielić.

To rozdziela ciąg znaków na właściwe liczby całkowite i może być pomocny dla większej liczby osób niż dla mnie;)

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

Mam nadzieję, że to pomoże!

Mathorlaz
źródło
Czy kiedykolwiek testowałeś ten kod? 50 powinno być 48, 55 działa tylko na wielkie litery ASCII, podczas gdy twój przykład zawiera małe litery.
Roland
0

Dla znaków char lub short to int, wystarczy przypisać wartość.

char ch = 16;
int in = ch;

To samo co int64.

long long lo = ch;

Wszystkie wartości będą wynosić 16.

Riwels
źródło