Char для преобразования int в C

Если я хочу преобразовать одно числовое число char в это числовое значение, например, если:

char c = '5';

и я хочу, чтобы c удерживал 5 вместо '5', он на 100% переносится так, как это?

c = c - '0';

Я слышал, что все наборы символов сохраняют числа в последовательном порядке, поэтому я так предполагаю, но я хотел бы знать, есть ли организованная библиотечная функция для этого преобразования и как это делается традиционно. Я настоящий новичок:)

Ответ 1

Да, это безопасное преобразование. C требует, чтобы он работал. Эта гарантия содержится в разделе 5.2.1 параграфа 2 последнего стандарта ISO C, последний проект которого N1570:

Оба базовых набора символов основного и основного исполнений должны иметь следующее Участники:
[...]
10 десятичных цифр
       0 1 2 3 4 5 6 7 8 9
[...]
Как в базовых наборах символов источника, так и для исполнения значение каждого символа после 0 в приведенном выше списке десятичных цифр должно быть больше, чем значение предыдущего.

И ASCII, и EBCDIC, и наборы символов, полученные из них, удовлетворяют этому требованию, поэтому стандарт C смог навязать его. Обратите внимание, что буквы не смежны iN EBCDIC, а C не требует их.

Нет никакой функции библиотеки, чтобы сделать это для одного char, вам нужно сначала создать строку:

int digit_to_int(char d)
{
 char str[2];

 str[0] = d;
 str[1] = '\0';
 return (int) strtol(str, NULL, 10);
}

Вы также можете использовать функцию atoi() для преобразования, как только у вас есть строка, но strtol() лучше и безопаснее.

Как уже отмечали комментаторы, экстремальным излишеством является вызов функции для этого преобразования; ваш первоначальный подход к вычитанию "0" - это правильный способ сделать это. Я просто хотел показать, как здесь будет использоваться рекомендованный стандартный подход к преобразованию числа в виде строки в "истинный" номер.

Ответ 2

Попробуйте следующее:

char c = '5' - '0';

Ответ 3

Вы можете использовать atoi, который является частью стандартной библиотеки.

Ответ 4

int i = c - '0';

Вы должны знать, что это не выполняет никакой проверки против символа - например, если символ был "a", тогда вы получите 91 - 48 = 49. Особенно, если вы имеете дело с пользовательским или сетевым вводом, вы должны, вероятно, выполнить проверку, чтобы избежать плохого поведения в вашей программе. Просто проверьте диапазон:

if ('0' <= c &&  c <= '9') {
    i = c - '0';
} else {
    /* handle error */
}

Обратите внимание, что если вы хотите, чтобы ваше преобразование обрабатывало шестнадцатеричные цифры, вы можете проверить диапазон и выполнить соответствующий расчет.

if ('0' <= c && c <= '9') {
    i = c - '0';
} else if ('a' <= c && c <= 'f') {
    i = 10 + c - 'a';
} else if ('A' <= c && c <= 'F') {
    i = 10 + c - 'A';
} else {
    /* handle error */
}

Это приведет к преобразованию одного шестнадцатеричного символа, независимого от верхнего или нижнего регистра, в целое число.

Ответ 5

Поскольку вы только конвертируете один символ, функция atoi() переполнена. atoi() полезен, если вы преобразовываете строковые представления чисел. На других примерах приведены примеры этого. Если я правильно прочитал ваше сообщение, вы преобразовываете только один цифровой символ. Таким образом, вы собираетесь преобразовать символ, который находится в диапазоне от 0 до 9. В случае преобразования только одного числового символа ваше предложение вычесть "0" даст вам результат, который вы хотите. Причина этого заключается в том, что значения ASCII являются последовательными (как вы сказали). Таким образом, вычитая значение ASCII 0 (значение ASCII 48 - см. ASCII Table для значений) от числового символа будет выдавать значение числа, Итак, ваш пример c = c - '0', где c = '5', то, что действительно происходит, 53 (значение ASCII 5) - 48 (значение ASCII 0) = 5.

Когда я впервые опубликовал этот ответ, я не принял во внимание ваш комментарий о том, что он на 100% переносится между разными наборами символов. Я немного поглядел вокруг, и кажется, что ваш ответ по-прежнему в основном правилен. Проблема в том, что вы используете char, который является 8-битным типом данных. Это не будет работать со всеми типами символов. Прочтите эту статью Joel Spolsky в Юникоде для получения более подробной информации о Unicode. В этой статье он говорит, что использует символы wchar_t для символов. Это хорошо сработало для него, и он публикует свой веб-сайт на 29 языках. Итак, вам нужно будет изменить ваш char на wchar_t. Помимо этого, он говорит, что персонаж под значением 127 и ниже в основном тот же. Это будет включать символы, которые представляют числа. Это означает, что основная математика, которую вы предложили, должна работать на то, чего вы пытались достичь.

Ответ 6

Да. Это безопасно, если вы используете стандартные символы ascii, например, вы находитесь в этом примере.

Ответ 7

Обычно, если нет гарантии, что ваш вход находится в диапазоне "0".. "9", вам необходимо выполнить проверку следующим образом:

if (c >= '0' && c <= '9') {
    int v = c - '0';
    // safely use v
}

Альтернативой является использование таблицы поиска. Вы получаете простой диапазон проверки и с меньшим (и, возможно, быстрее) кодом:

// one-time setup of an array of 256 integers;
// all slots set to -1 except for ones corresponding
// to the numeric characters
static const int CHAR_TO_NUMBER[] = {
    -1, -1, -1, ...,
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // '0'..'9'
    -1, -1, -1, ...
};

// Now, all you need is:

int v = CHAR_TO_NUMBER[c];

if (v != -1) {
    // safely use v
}

P.S. Я знаю, что это перебор. Я просто хотел представить его в качестве альтернативного решения, которое может не сразу проявиться.

Ответ 8

Как предлагали другие, но завернуты в функцию:

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

Теперь просто используйте функцию. Если, по линии, вы решили использовать другой метод, вам просто нужно изменить реализацию (производительность, различия между наборами символов и т.д.), Вам не нужно будет изменять вызывающих абонентов.

В этой версии предполагается, что c содержит char, который представляет цифру. Вы можете проверить это до вызова функции, используя функцию ctype.h isdigit.

Ответ 9

Так как коды ASCII для '0', '1', '2'.... помещаются от 48 до 57, они по существу непрерывны. Теперь для арифметических операций требуется преобразование типа данных char в int datatype.Hence, что вы в основном делаете:  53-48 и, следовательно, он сохраняет значение 5, с помощью которого вы можете выполнять любые целые операции. Обратите внимание, что при преобразовании из int в char компилятор не дает ошибки, а просто выполняет операцию по модулю 256, чтобы поместить значение в допустимый диапазон

Ответ 10

Вы можете просто использовать функцию atol():

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

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

}