Конвертировать char в int в C и C ++

232

Как преобразовать char в int в C и С++?

  • 1
    @Matt: было бы неплохо быть более конкретным. вопрос об обобщении просто предлагает обобщенные ответы, которые не применимы или даже не подходят для вашей задачи. имейте в виду, что когда вам приходится спрашивать, вы, вероятно, не знаете достаточно, чтобы правильно обобщать.
  • 0
    @Alf P. Steinbach: Первоначальный вопрос был неопределенным в отношении того, на каком языке. С ключевыми словами c и c++ , я думаю, ответы на оба языка являются разумными.
Показать ещё 6 комментариев
Теги:
gcc

11 ответов

340

Зависит от того, что вы хотите сделать:

чтобы прочитать значение как код 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 */
  • 8
    а = (а - "0")% 48;
  • 0
    @KshitijBanerjee Это не очень хорошая идея по двум причинам: он дает вам отрицательное число для символов ascii перед '0' (например, & -> -10), и это дает вам числа больше 10 (например, x -> 26)
Показать ещё 6 комментариев
53

C и С++ всегда поддерживают типы по меньшей мере int. Кроме того, символьные литералы имеют тип int в C и char в С++.

Вы можете преобразовать тип char, просто назначив int.

char c = 'a'; // narrowing on C
int a = c;
  • 3
    Вы также можете использовать крайне недооцененный унарный operator+() для этой цели.
  • 23
    -1 Ответ неверен только для осмысленного толкования вопроса. Это (code int a = c; ) сохранит любые отрицательные значения, с которыми стандартные функции библиотеки C не могут иметь дело. Стандартные библиотечные функции C устанавливают стандарт того, что значит обрабатывать значения char как int .
Показать ещё 8 комментариев
40

Ну, в ascii коды начинаются от 48. Все, что вам нужно сделать, это:

int x = (int)character - 48;
  • 42
    Или более читабельно: ' int x = character - '0'
  • 13
    @chad: не только более читабельный, но и более портативный. C и C ++ не гарантируют представление ASCII, но они гарантируют, что независимо от того, какое представление используется, представления десяти десятичных цифр являются смежными и в числовом порядке.
22

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

Да, имя примитивного типа данных оказывается "char", что указывает на то, что оно должно содержать только символы. Но на самом деле "char" - это просто плохой выбор имени, чтобы смутить всех, кто пытается выучить язык. Лучшее имя для него - int8_t, и вы можете использовать это имя вместо этого, если ваш компилятор следует последнему стандарту C.

Хотя при обработке строк вы должны использовать тип char, потому что индекс классической таблицы ASCII соответствует 1 байту. Тем не менее, вы могли бы обрабатывать строки с помощью обычных ints, хотя в реальном мире нет практической причины, почему вы когда-либо захотите это сделать. Например, следующий код будет работать отлично:

  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;

который затем проходит целые рекламные акции на языке C

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

а затем усечен до char, чтобы соответствовать типу результата

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

Там много таких тонких вещей, которые происходят между строками, где char неявно рассматривается как int.

  • 0
    Поскольку вопрос не помечен ascii , вы не должны предполагать какую-либо конкретную кодировку. Установка char равной int8_t , неверна, поскольку она также может быть uint8_t или uint24_t .
  • 0
    @RolandIllig Нет, char всегда равен 1 байту, и если в int8_t uint8_t существуют типы int8_t / uint8_t (что весьма вероятно), они смогут соответствовать результату char , потому что тогда он будет 8 бит. В очень экзотических системах, таких как различные устаревшие DSP, char будет 16 бит, а uint8_t не будет. Написание кода для совместимости с устаревшими DSP не имеет смысла, так же как написание для совместимости с системами дополнения или знака и величины. Огромная трата времени, поскольку такие системы практически не существуют в реальном мире.
10

(Этот ответ относится к С++ стороне вещей, но проблема расширения знака существует и в C.)

Обработка всех трех типов char (подписанный, неподписанный и "char" ) более деликатный, чем первый. Значения в диапазоне от 0 до SCHAR_MAX (что составляет 127 для 8-бит char):

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

Но когда какое-то значение выходит за пределы этого диапазона, только просмотр без знака 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> , таких как 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, что легко сделать с помощью функций wrapping <ctype> через 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.

Это работает, потому что любая функция, берущая любой из трех типов char, может также принимать два других типа char. Это приводит к двум функциям, которые могут обрабатывать любой из типов:

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 или отрицательный знак char - и chr принимает любое значение ord производит и возвращает тот же самый char.

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

6

Используйте static_cast<int>:

int num = static_cast<int>(letter); // if letter='a', num=97

Изменить: Вероятно, вам следует избегать использования (int)

int num = (int) letter;

проверить Зачем использовать static_cast <int> (x) вместо (int) x? для получения дополнительной информации.

6

Это зависит от того, что вы подразумеваете под "convert".

Если у вас есть серия символов, которая представляет целое число, например "123456", тогда есть два типичных способа сделать это на C: используйте специальное преобразование, например atoi() или strtol() или универсальный sscanf(). С++ (который на самом деле является другим языком, маскирующимся под обновление) добавляет третий, строковый поток.

Если вы хотите, чтобы точная битовая диаграмма в одной из ваших переменных int рассматривалась как char, это проще. В C разные целые типы действительно более состоятельны, чем фактические отдельные "типы". Просто начните использовать его там, где запрашивается char, и вы должны быть в порядке. Возможно, вам понадобится явное преобразование, чтобы заставить компилятор иногда выходить из-за нытья, но все, что нужно сделать, это сбросить любые дополнительные биты за 256.

2

У меня есть абсолютно навыки 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 + pow(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}
  • 0
    Этот код быстро вызывает неопределенное поведение и поэтому не подходит для копирования и вставки. (переполнение int)
2

Предположительно вы хотите использовать это преобразование для использования функций из стандартной библиотеки 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.,

1

Для char или short для int вам просто нужно назначить значение.

char ch = 16;
int in = ch;

То же самое для int64.

long long lo = ch;

Все значения будут 16.

1

У меня возникли проблемы с преобразованием массива 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;
}

Надеюсь, что это поможет!

  • 0
    Вы когда-нибудь проверяли этот код? 50 должно быть 48, 55 работает только для прописных букв ASCII, в то время как ваш пример содержит строчные буквы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню