Перетворити char в int в C і C ++


400

Як перетворити charв intв C і C ++?


1
@Matt: було б корисно бути більш конкретним. запитання про узагальнення просто запрошує узагальнені відповіді, які не застосовуються або навіть є правильними для вашого завдання. майте на увазі, коли вам доведеться запитати, ви, мабуть, не знаєте достатньо, щоб узагальнити правильно.
ура та хт. - Альф

@Alf P. Steinbach: Первісне питання було невиразним щодо мови. Що стосується ключових слів cі c++, я вважаю, відповіді, що стикаються з обома мовами, є розумними.
Метт Столяр

8
З мого великого досвіду на інших технічних форумах, моя інтуїція полягає в тому, що ОП насправді означає "як мені взяти текстове зображення числа (в базі 10) і перетворити його у відповідне число?" Взагалі, неофіти C і C ++ зазвичай мають неймовірно нечіткі уявлення про те, як працює текст на цих мовах і що charнасправді означає.
Карл Кнечтел

3
@KarlKnechtel: Якщо це правда (я даю це приблизно 50/50, оскільки багато ранніх підручників також заохочують виводити значення ASCII з символів, навіть якщо ASCII не охоплює повний діапазон), ОП потребує ясності - але це дуп of stackoverflow.com/questions/439573/… .
Фред Нурк

3
На роз'яснення цього питання в ОП було три години, а цього не вдалося. Як це є, немає способу дізнатися, що насправді задають. Проголосували за закриття.
sbi

Відповіді:


551

Залежить від того, що ви хочете зробити:

щоб прочитати значення як код ascii, ви можете написати

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

для перетворення символів '0' -> 0, '1' -> 1і т.д., ви можете написати

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

Пояснення :
a - '0'еквівалентно ((int)a) - ((int)'0'), що означає, що значення значень символів віднімаються один від одного. Оскільки 0надходить безпосередньо до 1таблиці ascii (і так далі до тих пір 9), різниця між ними дає число, яке aсимволізує.


14
ia = (a - '0')% 48;
Kshitij Banerjee

@KshitijBanerjee Це не дуже гарна ідея з двох причин: вона дає вам від'ємне число для символів ascii до '0' (наприклад &-> -10), а також дає цифри більше 10 (наприклад x-> 26)
SheetJS

2
int ia = a - '0' - ось що вам потрібно
фанк

5
@ kevin001 Якщо ви хочете перетворити char в int, а символ '1'надає число ascii, це не так 1, вам потрібно видалити зміщення, '0'щоб перерівняти його до 0-9. Послідовні числа 1-9 суміжні з цілим числом ascii.
krisdestruction

Жоден акторський склад не потрібен / бажаний
Крейг Есті

97

Ну а в коді ASCII цифри (цифри) починаються з 48 . Все, що вам потрібно зробити, це:

int x = (int)character - 48;

19
@chad: Не тільки читабельніше, але й більш портативно. C і C ++ не гарантують представлення ASCII, але вони гарантують, що яке б не було представлення, представлення 10-ти десяткових цифр є суміжними та в порядку числення.
Ben Voigt

Єдине, що я змінив би - це повернути 48, що здається трохи "магічним"'0'
ArielGro

59

C і C ++ завжди пропонують типи принаймні int. Крім того, букви символів мають тип intC і charC ++.

Ви можете перетворити charтип, просто призначивши його int.

char c = 'a'; // narrowing on C
int a = c;

3
Для цієї мети ви також можете використати сильно недооцінену унійну operator+() .
Cubbi

24
-1 Відповідь неправильна для єдиного змістовного тлумачення питання. Цей (код int a = c;) зберігатиме будь-які негативні значення, з якими стандартні функції бібліотеки C не можуть впоратися. Функції бібліотеки С встановлюють стандарт для того, що означає обробляти charзначення int.
ура та хт. - Альф

6
@Matt: Я зберігаю сутичку. Я б зміцнив це, якщо можливо! Інтерпретація питань, яку ви та інші припускали, не має сенсу, оскільки це надто тривіально і тому, що для конкретної комбінації типів ОП існує не дуже тривіальне дуже важливе практичне питання. Поради, які ви даєте, прямо небезпечні для новачка. Це, швидше за все, призведе до не визначеної поведінки для їхніх програм, які використовують стандартні функції класифікації символів бібліотеки С. Повторна реф. до відповіді @ Саяма він видалив цю відповідь.
ура та хт. - Альф

3
-1 за неправильність: isupper () матиме невизначені результати, якщо передасть 1252 високорозрядний символ.
Кріс Бекк

1
Що ви маєте на увазі під «завжди рекламувати»? Значення підвищуються під час неявних перетворень, певних типів параметрів, що передаються (наприклад, функції varargs), і коли оператор повинен зробити свої операнди сумісними типами. Але, безумовно, є випадки, коли значення не рекламується (наприклад, якщо я передаю знак символу функції, що очікує знака), інакше у нас не було б типів, менших за цілий.
Адріан Маккарті

31

char - це лише 1 байт. Немає нічого магічного з типом char! Так само, як ви можете призначити короткий до int або int до long, ви можете призначити знак char.

Так, ім'я примітивного типу даних буває "char", що говорить про те, що він повинен містити лише символи. Але насправді "чар" - це лише бідний вибір імені, щоб заплутати всіх, хто намагається вивчити мову. Краще ім'я для нього - int8_t, і ви можете використовувати це ім'я замість цього, якщо ваш компілятор відповідає останньому стандарту C.

Хоча, звичайно, слід використовувати тип char при обробці рядків, тому що індекс класичної таблиці ASCII відповідає 1 байту. Тим не менш, ти можеш робити обробку рядків і звичайними вкладками, хоча в реальному світі немає жодної практичної причини, чому б ти хотів це зробити. Наприклад, ідеально працює наступний код:

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

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

Ви повинні усвідомити, що символи та рядки - це просто цифри, як і все, що є в комп'ютері. Коли ви пишете "a" у вихідному коді, він попередньо обробляється на число 97, яке є цілою постійною.

Тож якщо ви пишете такий вираз, як

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

це фактично рівнозначно

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

який проходить через цілі акції мови С

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

а потім усікається до знака, щоб відповідати типу результату

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

Існує багато тонких речей, як це відбувається між рядками, де char неявно трактується як int.


Оскільки питання не позначене тегом ascii, не слід припускати будь-яке конкретне кодування. Установка , charяка дорівнює int8_tне так , тому що це може в рівній мірі ймовірно , буде uint8_tабо uint24_t.
Роланд Ілліг

1
@RolandIllig Ні, a char- це завжди 1 байт, і якщо типи int8_t/ uint8_tіснують у даній системі (що дуже ймовірно), вони зможуть відповідати результату a char, оскільки тоді це буде 8 біт. У високо екзотичних системах, таких як різні застарілі DSP, charбуде 16 біт, і uint8_tне буде існувати. Написання коду для сумісності із застарілими DSP - це нісенітниця, як і сумісність із системами доповнення чи знаків та величин. Величезна трата часу, оскільки такі системи ледь існують у реальному світі.
Лундін

18

(Ця відповідь стосується C ++ сторони речей, але проблема розширення знаків існує і в C.)

Поводження з усіма трьома charтипами ( signed, unsignedі char) є більш делікатним, ніж спочатку. Значення в діапазоні від 0 до SCHAR_MAX(що становить 127 для 8-бітових char):

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

Але, коли somevalueвиходить за межі цього діапазону, лише проходження unsigned charдає вам стійкі результати для "однакових" charзначень у всіх трьох типах:

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.

Це важливо при використанні функцій ctype.h , таких як isupperабо toupperчерез розширення знаків:

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

Зверніть увагу, що перетворення через int неявне; у цього ж UB:

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

Щоб виправити це, перейдіть до цього unsigned char, що легко зробити, обернувши функції ctype.h через 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.

Це працює, тому що будь-яка функція, яка бере будь-який із трьох типів знаків, також може приймати інші два типи символів. Це призводить до двох функцій, які можуть працювати з будь-яким із типів:

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)завжди дає вам негативне значення - навіть коли воно передано негативне charчи негативне signed char- і chrприймає будь-яке значення, яке ordвиробляє і повертає те саме char.

На практиці я, ймовірно, просто передавав це unsigned charзамість цього, але вони лаконічно обертають кастинг, надають зручне місце для додавання перевірки помилок на int-to- char, і будуть коротшими та зрозумілішими, коли вам потрібно використовувати їх кілька разів в безпосередній близькості.



7

Це свого роду залежить від того, що ви маєте на увазі під "конвертувати".

Якщо у вас є серія символів, яка представляє ціле число, наприклад, "123456", то в C є два типові способи зробити це: Використовуйте перетворення спеціального призначення, наприклад atoi () або strtol () , або sscanf загального призначення () . C ++ (що насправді є іншою мовою, що маскується як оновлення) додає третій, рядковий потік.

Якщо ви хочете сказати, що ви хочете, щоб точний зразок бітів в одній зі intзмінних трактувався як a char, це простіше. У C цілі цілі типи справді більше стану душі, ніж фактичні окремі "типи". Просто почніть використовувати його там, де charвас просять, і вам повинно бути все в порядку. Можливо, вам знадобиться явна конверсія, щоб змусити компілятор кинути нюхати, але все, що потрібно зробити, це скинути зайві біти минулого 256.


6

У мене абсолютно nullнавички роботи з C, але для простого розбору:

char* something = "123456";

int number = parseInt(something);

... це працювало для мене:

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

Цей код швидко викликає не визначене поведінку, тому не підходить для копіювання та вставлення. (int overflow)
Roland Illig

4

Імовірно, ви хочете, щоб це перетворення використовувало функції зі стандартної бібліотеки С.

У цьому випадку зробіть (синтаксис C ++)

typedef unsigned char UChar;

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

Вираз UChar( c )перетворюється unsigned charв, щоб позбутися від негативних значень, які, крім EOF, не підтримуються функціями C.

Тоді результат цього виразу використовується як фактичний аргумент для int формального аргументу. Де ви отримаєте автоматичне просування до int. Можна альтернативно написати цей останній крок явно, як int( UChar( c ) ), але особисто я вважаю це занадто багатослівним.

Ура & hth.,


0

У мене виникли проблеми з перетворенням типу масиву char "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e" у його фактичне ціле значення, яке могло б бути представлене `7C 'як одне шістнадцяткове значення. Отож, після того, як виїхали на допомогу, я створив це і подумав, що було б здорово поділитися.

Це розділяє рядок char на його правильні цілі числа, і може бути корисним для більшої кількості людей, ніж лише я;)

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

Сподіваюся, це допомагає!


Ви коли-небудь тестували цей код? 50 повинен бути 48, 55 працює лише для великих літер ASCII, тоді як ваш приклад містить малі літери.
Roland Illig

0

Для char або короткого до int потрібно просто призначити значення.

char ch = 16;
int in = ch;

Те саме, що і int64.

long long lo = ch;

Усі значення будуть 16.


-1
int charToint(char a){
char *p = &a;
int k = atoi(p);
return k;
}

Ви можете використовувати цей метод atoi для перетворення char в int. Для отримання додаткової інформації можна звернутися до цього http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/string/stoi/ .


1
Це невизначена поведінка. Прийняття адреси змінної char дасть вам знак *, але не C-рядок, на що очікує atoi.
luizfls
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.