Преобразование символьной цифры в соответствующее целое число в 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 ++.


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

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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.