Перетворіть символьну цифру у відповідне ціле число в C


103

Чи існує спосіб перетворення символу в ціле число в C?

Наприклад, від '5'5?

Відповіді:


148

Як і в інших відповідях, це добре:

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

Також для перевірки помилок ви можете спочатку перевірити isdigit (c). Зверніть увагу, що ви не можете повністю переносити те саме для листів, наприклад:

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

Стандарт гарантує, що значення знаків для цифр '0' до '9' є суміжними, але не дає гарантій для інших символів, таких як букви алфавіту.


3
@Paul Tomblin: Так, для цифр, а не для літер, тому що, як я вже сказав у відповіді, стандартні гарантії "0" до "9" є суміжними, але не дають таких гарантій для інших символів, як "a" to "z".
Кріс Янг

char c = 'b'; int x = c - 'a'; то х буде 1 лише в ASCII?
Пан

@Pan У будь-якому кодуванні, включаючи ASCII, у якого "b" на 1 більше, ніж у "a". Це все ще справедливо в EBCDIC, однак це робить ('j' - 'i') == 8.
Кріс Янг

@ChrisYoung Чому? Причина в EBCDIC, 'j' не на 1 більше, ніж 'i'?
Пан

2
Що я пропускаю тут, де атої не використовуються?
Даніель

41

Віднімаємо «0» так:

int i = c - '0';

C Стандарт гарантує кожна цифра в діапазоні '0'..'9'на одиницю більше , ніж його попередній цифрі (в розділі 5.2.1/3про проект C99 ). Те саме вважається для C ++.


1
Ця відповідь буде кращою, якби ви згадали, що знак знаку - це / вже / фактично ціле число, албіт визначеного знаком реалізації (тобто, може бути підписаний або непідписаний) і триває CHAR_BITS.
Арафангіон

я не був впевнений, знаючи, що йому справді допомагає. але Кріс зробив добру думку, коли я не обов'язково суперечив. я повинен був сказати, що замість цього. тепер він виграв гонку :)
Йоханнес Шауб - ліб

1
З вами краще, адже ви кваліфікували свою відповідь, - Кріс цілком міг би просто скласти свої речі. :)
Арафангіон

дякую за вдячність я визнаю , я не був упевнений , що про стан для З , так що я подивився вгору і тому я вже був у нього я вставив посилання у відповідь :)
Johannes Schaub - LITB

І це, пане, чому ви маєте на пару більше очок, ніж я. :)
Арафангіон

29

Якщо за якимось шаленим збігом обставин ви хочете перетворити рядок символів у ціле число, ви можете зробити це теж!

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

valзараз 1024. Мабуть, atoi()це добре, і те, що я говорив про це раніше, стосується лише мене (на OS X (можливо (тут вставити жарт Lisp))). Я чув, що це макрос, який орієнтується приблизно на наступний приклад, який використовує strtol(), більш загальну функцію, для перетворення замість цього:

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

strtol() працює так:

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

Він перетворюється *strна a long, трактуючи його як би базове baseчисло. Якщо **endptrце не нуль, він містить перший strtol()знайдений нецифровий символ (але кого це хвилює).


Немає проблем з потоками з atoi (у нього немає статичних даних) і він не застарілий. Насправді він функціонально еквівалентний: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran

5
Проблема з atoi полягає в тому, що він використовує 0 як значення "не можна знайти тут число", тому atoi ("0") і atoi ("one") обидва повертають 0. Якщо це не працює для того, що ви повторно використовуючи його, шукайте strtol () або sscanf ().
Девід Торнлі

Інша перевага strtol, звичайно, полягає в тому, що вам може знадобитися читати інші речі з того самого рядка, які приходять після числа.
dfeuer

@EvanTeran На жаль, якщо ви запускаєте Visual Studio, ви отримуєте попередження про амортизацію (і виграєте компіляцію без відключення). Тепер VS рекомендує itoa_s().
Саймон

7

Віднімаємо знак "0" або int 48 так:

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

Пояснення: Всередині він працює зі значенням ASCII . З таблиці ASCII десяткове значення символу 5 дорівнює 53, а 0 - 48 . Отже 53 - 48 = 5

АБО

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

Це означає, що якщо ви вирахуєте 48 з будь-якого числового символу, воно перетвориться цілим числом автоматично.


6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');

numeralChar - '0'вже є тип int, тому вам не потрібен акторський склад. Навіть якщо цього не було, акторський склад не потрібен.
Алок Сінгал

Ага, так, це би примусило, чи не так? Можливо, Java забарвила моє сприйняття. Або, можливо, я абсолютно помиляюся, і це навіть примушує Java. :)
Кевін Коннер

5

Для перетворення символьної цифри у відповідне ціле число. Зробіть, як показано нижче:

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

Логіка, що стоїть за вищезазначеним розрахунком, - це грати зі значеннями ASCII. Значення ASCII символу 8 - 56, значення ASCII символу 0 - 48. Значення ASCII цілого числа 8 дорівнює 8.

Якщо відняти два символи, віднімання відбудеться між символами ASCII.

int i = 56 - 48;   
i = 8;

Чому я єдиний, хто підтримав це? Пояснення настільки просте та інформативне: +1:
Брендон Бенефілд

0

Якщо це просто один символ 0-9 в ASCII, то віднімання значення нульового символу ASCII від значення ASCII повинно працювати нормально.

Якщо ви хочете перетворити великі числа, зробіть наступне:

char *string = "24";

int value;

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

** не забудьте перевірити стан (який повинен бути 1, якщо він працював у наведеному вище випадку).

Пол.


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

0

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

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

Тоді перетворення легко

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

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


Це здається вкрай неефективним для перетворення однієї десяткової (або восьмеричної) цифри. Якщо відповідна частина таблиці пошуку не трапляється в кеш-пам'яті L1, ви спустите купу циклів, щоб витягнути її лише для отримання одного значення. Чесно кажучи, я, як правило, сумніваюся, що це навіть гарна ідея, якщо ви перетворюєте цілий ряд цифр, але вам доведеться це виміряти. Звичайно, це набагато конкурентоспроможніше для шестигранників.
dfeuer

0

Перевір це,

char s='A';

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

лише для 0,1,2, ...., E, F.


0

Просто скористайтеся atol()функцією:

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

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

}

0

Якщо ваша цифра, скажімо, '5'в ASCII, вона представлена ​​як двійкове число 0011 0101(53). Кожна цифра має найвищі чотири біти, 0011а найнижчі 4 біти представляють цифру у bcd. Так ви просто зробите

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

щоб отримати найменші 4 біти, або, що це те саме, цифру. У asm він використовує andоперацію замість sub(як в інших відповідях).


'5'є 53 ( 00110101)
eyllanesc

@eyllanesc Спочатку це було 4. Спасибі. Редагував це.
Garmekain

0

Ось допоміжні функції, які дозволяють перетворити цифру в char в int і навпаки:

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

char toChar(int i) {
    return i + '0';
}

-2

використання функції: atoi для масиву до цілого числа, atof для масиву для плаваючого типу; або

char c = '5';
int b = c - 48;
printf("%d", b);

Кілька відповідей уже висвітлювали це. Це додає нічого, чого вони вже не висвітлювали.
ShadowRanger

-3

Ви б кинули його до int (або float, або double або що-небудь ще, що ви хочете зробити з ним) і зберігаєте його в іншій змінній.

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