Konwertuj char na int w C #

148

Mam znak w C #:

char foo = '2';

Teraz chcę wstawić 2 do int. Uważam, że Convert.ToInt32 zwraca rzeczywistą wartość dziesiętną znaku, a nie liczbę 2. Działa to:

int bar = Convert.ToInt32(new string(foo, 1));

int.parse działa również tylko na stringach.

Czy nie ma natywnej funkcji w C #, aby przejść od znaku do int bez tworzenia ciągu? Wiem, że to trywialne, ale wydaje się dziwne, że nie ma nic rodzimego, który mógłby bezpośrednio dokonać konwersji.

KeithA
źródło

Odpowiedzi:

143

Ciekawe odpowiedzi, ale doktorzy mówią inaczej:

Użyj GetNumericValuemetod, aby przekonwertować Charobiekt, który reprezentuje liczbę na typ wartości liczbowej. Użyj Parsei, TryParseaby przekonwertować znak w ciągu na Char obiekt. Służy ToStringdo konwersji Char obiektu na Stringobiekt.

http://msdn.microsoft.com/en-us/library/system.char.aspx

Chad Grant
źródło
ach! więc jest coś rodzimego! Dziwne, że zwraca podwójną. Ta odpowiedź podoba mi się bardziej. Dzięki za wskazanie tego.
KeithA
92
@KeithA: Jest powód, dla którego zwraca wartość double: char.GetNumericValue('¼')daje 0,25. Radości z Unicode ... ;-)
Heinzi
1
To nie jest odpowiedź, która odpowiada na rzeczywiste pytanie, Char.GetNumericValue ('o'), Char.GetNumericValue ('w'), a każdy nienumeryczny znak zawsze zwróci -1 - Jeremy Ruten opublikował poprawną odpowiedź
Rusty Nail
2
@RustyNail w przypadku oryginalnego pytania - pytając konkretnie, gdzie wie, że znak reprezentuje liczbę - to jest właściwa odpowiedź
Don Cheadle
@mmcrae Nie sądzę - pierwotne pytanie prosi o to, charaby intnie używać stringnajpierw.
NetMage,
163

Spowoduje to przekonwertowanie go na int:

char foo = '2';
int bar = foo - '0';

To działa, ponieważ każdy znak jest wewnętrznie reprezentowany przez liczbę. Znaki od „0” do „9” są reprezentowane przez kolejne liczby, więc znalezienie różnicy między znakami „0” i „2” daje w wyniku liczbę 2.

Jeremy Ruten
źródło
5
Zakłada określony zestaw znaków.
EricSchaefer
8
Nie, nie, tak długo, jak cyfry są w porządku (których kompilatory wymagają zestawu znaków), będzie działać, bez względu na to, od jakiej wartości zaczną.
Jeremy Ruten
2
To jest w porządku, z wyjątkiem tego, że nadal musisz najpierw sprawdzić granice, a na tym etapie nie jestem pewien, czy int.parse (foo.ToString ()) jest szybsze.
Matthew Flaschen
7
@EricSchaefer Ale to bezpieczne założenie w C #: charto zawsze UTF-16.
svick
2
@svick mały punkt i teraz stary, ale od czasu, gdy to opublikowałeś, wyszedł Core, który używa UTF-8. Wciąż jednak bezpieczne założenie.
Joel Coehoorn
84

Czy ktoś rozważał użycie int.Parse()i int.TryParse()jak to

int bar = int.Parse(foo.ToString());

Jeszcze lepiej

int bar;
if (!int.TryParse(foo.ToString(), out bar))
{
    //Do something to correct the problem
}

Jest dużo bezpieczniejszy i mniej podatny na błędy

wadliwy
źródło
2
Absolutnie właściwe podejście. Wybierz pierwszą, jeśli chcesz, aby dane wejściowe inne niż int są rzucane, a drugą, jeśli chcesz zrobić coś innego.
Jay Bazuzi
To dobre podejście w przypadku ogólnej metody konwersji. Na marginesie, jest to kolejny przykład tego, jak .NET promuje oprogramowanie typu bloatware. (Mam na myśli kontynuowanie i test jednostkowy TryParse () i ToString () - nie możesz, praktycznie nie).
wyloguj się
5
@logout nie, to przykład tego, jak odpowiedź na StackOverflow promuje oprogramowanie typu bloatware. To jest rzeczywiście niepotrzebnie rozdęte i nie rozumiem, dlaczego uważa się to za lepsze od odejmowania '0'od znaku.
Roman Starkov
26
char c = '1';
int i = (int)(c-'0');

i możesz z tego stworzyć statyczną metodę:

static int ToInt(this char c)
{
    return (int)(c - '0');
}
sontek
źródło
To jest to, czego szukałem. Mógłbyś może wyjaśnić, co robisz z częścią minus zero.
Xonatron
10

Spróbuj tego

char x = '9'; // '9' = ASCII 57

int b = x - '0'; //That is '9' - '0' = 57 - 48 = 9
RollerCosta
źródło
Twój komentarz mówi '9', ale twój kod tak 9, co się nie kompiluje.
svick
7

Domyślnie używasz UNICODE, więc sugeruję użycie metody wadliwego

int bar = int.Parse(foo.ToString());

Mimo że wartości numeryczne pod są takie same dla cyfr i podstawowych znaków łacińskich.

Nikolay
źródło
4

To konwertuje na liczbę całkowitą i obsługuje Unicode

CharUnicodeInfo.GetDecimalDigitValue('2')

Możesz przeczytać więcej tutaj .

Dan Friedman
źródło
4

Prawdziwy sposób to:

int theNameOfYourInt = (int) .Char.GetNumericValue (theNameOfYourChar);

„theNameOfYourInt” - int, w jaki chcesz przekształcić postać.

"theNameOfYourChar" - Char, którego chcesz użyć, aby został przekształcony w int.

Zostaw wszystko inne.

Normantas Stankevičius
źródło
2

Zasada:

char foo = '2';
int bar = foo & 15;

Binarny z znaków ASCII 0-9 to:

0   -   0011 0000
1   -   0011 0001
2   -   0011 0010
3   -   0011 0011
4   -   0011 0100
5   -   0011 0101
6   -   0011 0110
7   -   0011 0111
8   -   0011 1000
9   -   0011 1001

a jeśli weźmiesz do każdego z nich pierwsze 4 LSB (używając bitowego AND z 8'b00001111, co równa się 15), otrzymasz rzeczywistą liczbę (0000 = 0,0001 = 1,0010 = 2, ...)

Stosowanie:

public static int CharToInt(char c)
{
    return 0b0000_1111 & (byte) c;
}
Tomer Wolberg
źródło
2
Chociaż ten fragment kodu może być rozwiązaniem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod.
yivi
2

Zgadzam się z @Chad Grant

Również dobrze, jeśli przekonwertujesz na łańcuch, możesz użyć tej wartości jako wartości liczbowej, jak powiedziano w pytaniu

int bar = Convert.ToInt32(new string(foo, 1)); // => gives bar=2

Starałem się stworzyć prostszy i bardziej zrozumiały przykład

char v = '1';
int vv = (int)char.GetNumericValue(v); 

char.GetNumericValue (v) zwraca jako double i konwertuje na (int)

Bardziej zaawansowane zastosowanie jako tablica

int[] values = "41234".ToArray().Select(c=> (int)char.GetNumericValue(c)).ToArray();
Hamit YILDIRIM
źródło
0

Porównanie niektórych metod opartych na wyniku, gdy znak nie jest cyfrą ASCII:

char c = '\n';                              
Debug.Print($"{c & 15}");                   // 10
Debug.Print($"{c ^ 48}");                   // 58
Debug.Print($"{c - 48}");                   // -38
Debug.Print($"{(uint)c - 48}");             // 4294967258
Debug.Print($"{char.GetNumericValue(c)}");  // -1 
Slai
źródło
0

Używam Compact Framework 3.5 i nie mam metody „char.Parse”. Myślę, że nie jest źle używać klasy Convert. (Zobacz CLR przez C #, Jeffrey Richter)

char letterA = Convert.ToChar(65);
Console.WriteLine(letterA);
letterA = 'あ';
ushort valueA = Convert.ToUInt16(letterA);
Console.WriteLine(valueA);
char japaneseA = Convert.ToChar(valueA);
Console.WriteLine(japaneseA);

Działa ze znakami ASCII lub Unicode

antonio
źródło
-4

To zadziałało dla mnie:

int bar = int.Parse("" + foo);
Renán Díaz
źródło
5
Czym się to różni od tego int.Parse(foo.ToString()), że jest mniej czytelne?
svick
-5

Widziałem wiele odpowiedzi, ale wydają mi się one zagmatwane. Nie możemy po prostu użyć rzutowania typów.

Na przykład: -

int s;
char i= '2';
s = (int) i;
Uczeń
źródło
1
To zwróci kod ASCII znaku 2, a nie wartość 2.
cavpollo
A co powiesz na użycie char.GetNumericValue (zwraca podwójną wartość) i rzutowanie jej na int.
Learner
Tak, to właśnie proponuje zaakceptowana odpowiedź @Chad Grant
Cavpollo