@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ć .
@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:
@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.
Możesz również użyć do tego celu bardzo niedocenionego unarskiegooperator+() .
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.
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;signedchar sc = c;unsignedchar 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;signedchar sc = c;unsignedchar uc = c;// Might not be true: int(c) == int(sc) and int(c) == int(uc).int nc =(unsignedchar)c;int nsc =(unsignedchar)sc;int nuc =(unsignedchar)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(unsignedchar 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(unsignedchar)c;}char chr(int n){assert(0<= n);// Or other error-/sanity-checking.assert(n <= UCHAR_MAX);return(unsignedchar)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.
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.
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;}
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 ++)
typedefunsignedcharUChar;char myCppFunc(char c ){returnchar( 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.
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;)
c
ic++
myślę, że odpowiedzi na oba języki są rozsądne.char
tak naprawdę oznacza.Odpowiedzi:
Zależy od tego, co chcesz zrobić:
aby odczytać wartość jako kod ascii, możesz napisać
przekształcić charakter
'0' -> 0
,'1' -> 1
itd, można napisać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ż0
pojawia się bezpośrednio1
w tabeli ascii (i tak dalej9
), różnica między nimi daje liczbęa
reprezentowaną przez postać .źródło
&
-> -10) i daje liczby większe niż 10 (jakx
-> 26)'1'
podaje liczbę ascii, której nie ma1
, 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.Cóż, w kodzie ASCII cyfry (cyfry) zaczynają się od 48 . Wszystko, co musisz zrobić, to:
źródło
'0'
C i C ++ zawsze promują typy przynajmniej do
int
. Ponadto literały znakowe są typuint
C ichar
C ++.Możesz przekonwertować
char
typ, po prostu przypisując doint
.źródło
operator+()
.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ługichar
wartości jakoint
.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:
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
jest to faktycznie równoważne z
który następnie przechodzi przez promocje liczb całkowitych w języku C.
a następnie obcięty do znaku, aby dopasować do typu wyniku
Między wierszami dzieje się wiele subtelnych rzeczy, takich jak char, domyślnie traktowanych jako int.
źródło
ascii
, nie należy zakładać żadnego konkretnego kodowania. Ustawieniechar
równościint8_t
jest nieprawidłowe, ponieważ równie prawdopodobne może byćuint8_t
lubuint24_t
.char
ma zawsze 1 bajt, a jeśli typyint8_t
/uint8_t
istnieją w danym systemie (co jest bardzo prawdopodobne), będą one w stanie dopasować wynik achar
, ponieważ będzie to wtedy 8 bitów. W wysoce egzotycznych systemach, takich jak różne przestarzałe DSP,char
będzie 16 bitów iuint8_t
nie 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.(Ta odpowiedź dotyczy strony C ++, ale problem rozszerzenia znaku istnieje również w C.)
Obsługa wszystkich trzech
char
typów (signed
,unsigned
ichar
) jest delikatniejsza niż się wydaje. Wartości w zakresie od 0 doSCHAR_MAX
(czyli 8 dla 8-bitówchar
) są łatwe:Ale gdy
somevalue
znajduje się poza tym zakresem, przejście tylkounsigned char
daje spójne wyniki dla „tych samych”char
wartości we wszystkich trzech typach:Jest to ważne, gdy używasz funkcji z ctype.h , takich jak
isupper
lubtoupper
, z powodu rozszerzenia znaku:Zauważ, że konwersja przez int jest niejawna; to ma ten sam UB:
Aby to naprawić, przejdź przez
unsigned char
, co można łatwo zrobić, pakując funkcje ctype.h poprzez safe_ctype :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:
ord(c)
zawsze daje wartość nieujemną - nawet jeśli minęła wartość ujemnachar
lub ujemnasigned char
- ichr
przyjmuje dowolną wartośćord
produkowaną i zwraca dokładnie to samochar
.W praktyce prawdopodobnie po prostu przerzuciłbym
unsigned char
zamiast ich używać, ale zwięźle owijają one obsadę, zapewniają wygodne miejsce do dodawania sprawdzania błędów dlaint
-to-char
, i byłyby krótsze i wyraźniejsze, gdy trzeba ich użyć kilka razy w bliskiej odległości.źródło
Użyj
static_cast<int>
:Edycja: Prawdopodobnie powinieneś spróbować uniknąć używania
(int)
sprawdź Dlaczego warto używać static_cast <int> (x) zamiast (int) x? po więcej informacji.
źródło
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
int
zmiennych był traktowany jako achar
, 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, gdziechar
są 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.źródło
Mam absolutnie
null
umiejętności w C, ale do prostej analizy:... to zadziałało dla mnie:
źródło
Prawdopodobnie chcesz tej konwersji do korzystania z funkcji ze standardowej biblioteki C.
W takim przypadku wykonaj (składnia C ++)
Wyrażenie
UChar( c )
konwertuje naunsigned 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
int
formalnego. Gdzie otrzymujesz automatyczną promocję naint
. Możesz alternatywnie napisać ten ostatni krok wprost, na przykładint( UChar( c ) )
, ale osobiście uważam, że jest to zbyt szczegółowe.Pozdrawiam i hth.,
źródło
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;)
Mam nadzieję, że to pomoże!
źródło
Dla znaków char lub short to int, wystarczy przypisać wartość.
To samo co int64.
Wszystkie wartości będą wynosić 16.
źródło
Możesz użyć tej metody atoi do konwersji char na int. Więcej informacji można znaleźć w tym http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/string/stoi/ .
źródło