Преобразование символьной цифры в соответствующее целое число в C

103

Есть ли способ преобразовать символ в целое число в C?

Например, от '5'до 5?

поток
источник

Ответы:

150

Согласно другим ответам, это нормально:

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

Кроме того, для проверки ошибок вы можете сначала проверить, что isdigit (c) истинно. Обратите внимание, что вы не можете полностью перенести то же самое для букв, например:

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

Стандарт гарантирует, что значения char для цифр от «0» до «9» являются смежными, но не дает никаких гарантий для других символов, таких как буквы алфавита.

Крис Янг
источник
3
@Paul Tomblin: Да, для цифр, а не букв, потому что, как я сказал в ответе, стандартные гарантии от 0 до 9 являются смежными, но не дают таких гарантий для других символов, таких как от a до z.
Крис Янг
char c = 'b'; int x = c - 'а'; тогда x будет 1 только в ASCII?
Pan
@Pan В любой кодировке, включая ASCII, в которой 'b' на 1 больше, чем 'a'. Это по-прежнему верно в EBCDIC, однако он делает ('j' - 'i') == 8.
Крис Янг,
@ChrisYoung Почему? Потому что в EBCDIC «j» не на 1 больше, чем «i»?
Pan
2
Что мне здесь не хватает, где не используется атой?
Daniel
41

Вычтем «0» следующим образом:

int i = c - '0';

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

Йоханнес Шауб - litb
источник
1
Этот ответ был бы лучше, если бы вы упомянули, что char является / уже / эффективно целым числом, определенным знаком реализации (т.е. может быть подписанным или беззнаковым) и имеет длину CHAR_BITS.
Арафангион,
я не был уверен, что знал, что это действительно помогает ему. но Крис подчеркнул, что a..z не обязательно должны быть смежными. я должен был упомянуть это вместо этого. теперь он выиграл гонку :)
Йоханнес Шауб - литб
1
Ваш ответ лучше, потому что вы уточнили свой ответ - Крис вполне мог просто выдумать свои вещи. :)
Арафангион
спасибо за признательность. Признаюсь, я не был уверен в состоянии C., поэтому я посмотрел и, потому что я уже был в нем, я вставил ссылку в ответ :)
Йоханнес Шауб - litb
И поэтому, сэр, у вас на пару очков больше, чем у меня. :)
Арафангион
29

Если по какому-то безумному совпадению вы захотите преобразовать строку символов в целое число, вы тоже можете это сделать!

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

valтеперь 1024. По-видимому, atoi()все в порядке, и то, что я сказал об этом ранее, применимо только ко мне (в OS X (возможно (вставьте шутку о Лиспе))). Я слышал, что это макрос, который примерно соответствует следующему примеру, который 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в long, рассматривая его как базовое baseчисло. Если **endptrне null, он содержит первый strtol()найденный нецифровой символ (но кого это волнует).

Крис Лутц
источник
У atoi нет проблем с потоками (у него нет статических данных), и он не является устаревшим. Фактически, это функционально эквивалентно: #define atoi (x) (int) (strtol ((x), NULL, 10)
Эван Теран,
5
Проблема с atoi заключается в том, что он использует 0 как значение «не могу найти здесь число», поэтому atoi («0») и atoi («one») оба возвращают 0. Если это не сработает для того, что вы ' Если вы его используете, найдите strtol () или sscanf ().
Дэвид Торнли,
Другое преимущество strtol, конечно, заключается в том, что вам может потребоваться читать другие вещи из той же строки, которая идет после числа.
dfeuer
@EvanTeran К сожалению, если вы запустите Visual Studio, вы получите предупреждение об устаревании (и не сможете компилировать без отключения). VS теперь рекомендует itoa_s().
Саймон
7

Вычтите char '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 изменила мое восприятие. А может я совершенно ошибаюсь и на Яве даже принудит. :)
Кевин Коннер
6

Преобразовать символьную цифру в соответствующее целое число. Сделайте как показано ниже:

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 !!!
}
Alphaneo
источник
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а четыре младших бита представляют цифру в двоично-десятичном формате. Так ты просто делаешь

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

чтобы получить младшие 4 бита или, что то же самое, цифру. В asm он использует andоперацию вместо sub(как в других ответах).

Гармекаин
источник
'5'is 53 ( 00110101)
eyllanesc
@eyllanesc Сначала было 4. Спасибо. Отредактировал это.
Гармекаин
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, или что-нибудь еще, что вы хотите с ним сделать) и сохранить в переменной anoter.

SeanJA
источник