Интерпретация шестнадцатеричного числа как десятичного

У меня есть встроенная система с C-кодом, которая работает довольно просто; он считывает символы через последовательное соединение, интерпретирует полученные символы как шестнадцатеричные числа и в зависимости от того, что было получено, продолжает делать что-то еще. Однако есть один особый случай, когда полученные символы являются десятичными, а не шестнадцатеричными. Поскольку этот случай очень редок (вид ошибки в случае ошибки), я не хочу изменять фактическое получение символа, чтобы решить, следует ли интерпретировать полученное значение как десятичное или шестнадцатеричное, а скорее добавить быстрый алгоритм в обработка случая, когда я меняю число на десятичное.

Как бы вы сказали, что это самый быстрый (как наиболее эффективный с точки зрения процессора) способ сделать это? Поскольку программное обеспечение работает на небольшом микроконтроллере, любые функции библиотеки C не подходят, поскольку я не хочу добавлять больше ненужных #include, поэтому я ищу чисто математический алгоритм.

Просто для ясности, я не спрашиваю самый быстрый способ сделать базовое преобразование шестнадцатеричного в десятичное, как в 0x45 -> dec 69, но то, что я хочу сделать, это преобразовать, например. 0x120 в десятичное число 120.

Заранее спасибо!

РЕДАКТИРОВАТЬ: Извините, я постараюсь объяснить более подробно. Фактический код слишком длинный, и я думаю, что вставлять его сюда не нужно. Итак, вот что происходит:

Сначала я читаю полученное число из последовательной линии, скажем, "25". Затем я превращаю его в шестнадцатеричное число, поэтому у меня есть переменная со значением чтения, скажем, X = 0x25. Это уже работает нормально, и я не хочу вносить в это изменения. Что я хотел бы сделать сейчас в этом особом случае, так это просто изменить интерпретацию переменной так, чтобы вместо X == 0x25, X == 25. Шестнадцатеричное 0x25 превращается в десятичное 25. Должна ли быть какая-то математическая формула для такого изменения, без каких-либо инструкций для конкретного процессора или библиотечных функций?


person HughStevenJames    schedule 15.04.2014    source источник
comment
Он называется BCD. Если это редкий случай, я бы использовал библиотечные функции, если они доступны. Некоторые процессоры имеют инструкции, связанные с BCD.   -  person Basile Starynkevitch    schedule 15.04.2014
comment
если последовательность символов, которую вы ищете, равна 0x120, то просто создайте указатель на символ следующим образом: char *decimal = &inChar[2]; и int number = atoi(decimal);... хотя я подозреваю, что то, что вы ищете, немного сложнее. Вы действительно должны уточнить это (покажите код, будьте более конкретными)   -  person Elias Van Ootegem    schedule 15.04.2014
comment
Извините, попробую объяснить подробнее. Фактический код слишком длинный, и я думаю, что он не нужен. Итак, вот что происходит:   -  person HughStevenJames    schedule 15.04.2014
comment
Пожалуйста, отредактируйте свой вопрос, чтобы улучшить его.   -  person Basile Starynkevitch    schedule 15.04.2014
comment
откуда вы знаете, что это десятичное значение, которое вы получаете, поскольку вы говорите в комментарии, что вы не получаете 0x перед шестнадцатеричными значениями, например. 25 является допустимым шестнадцатеричным числом и допустимым десятичным числом.   -  person AndersK    schedule 15.04.2014
comment
Система также имеет другие интерфейсы к реальному миру, и на основе событий, зарегистрированных в них, принимается правильный курс действий. Именно поэтому и возникла необходимость в таком преобразовании; принимаются только цифры, и интерпретация зависит от ситуации.   -  person HughStevenJames    schedule 15.04.2014


Ответы (3)


Если я правильно понимаю, вы уже преобразовали поток символов ASCII в переменную char/int, считая их потоком шестнадцатеричных цифр. В некоторых случаях они на самом деле были потоком десятичных цифр (например, вы получили 45 и, обработав это как шестнадцатеричное, получили переменную со значением 69, когда — в одном особом случае — вы на самом деле хотите, чтобы ее значение было 45.

Предполагая два символа (в общем случае 00-ff, но для «предназначено быть десятичным» мы говорим 00-99), тогда:

int hexVal = GetHexStringFromSerialPort() ;
int decVal = 10*(hexVal >> 4) + (hexVal & 0x0f) ;

должен сделать трюк. Если у вас есть более длинные строки, вам нужно расширить концепцию.

person TripeHound    schedule 15.04.2014
comment
Это похоже на то, что я ищу, я посмотрю, где я закончу с этим. Спасибо! - person HughStevenJames; 15.04.2014

Просто выполните такой простой цикл while, предположив, что onum и dnum являются целыми числами без знака.

dnum = 0;
while (onum) {
  digit = onum & 0xF;
  dnum = dnum*10 + digit;
  onum >>= 4;
}

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

person Jens Gustedt    schedule 15.04.2014
comment
Это переворачивает число. Для onum = 0x1234 вы получите 4321 в dnum. - person Jabberwocky; 15.04.2014
comment
@MichaelWalz, верно. Нужно было бы сделать второй цикл, чтобы вернуть это снова. - person Jens Gustedt; 15.04.2014

Проверка того, начинается ли ваша строка с символов 0x, и их удаление должны помочь.

person Manuel Selva    schedule 15.04.2014
comment
Данные символов, которые я получаю, не имеют префикса 0x, я получаю только числа в форме, разделенной запятыми. Кроме того, я не хочу добавлять какие-либо проверки к фактической процедуре приема, я просто манипулирую полученным номером, если этого требует ситуация. - person HughStevenJames; 15.04.2014