Шестнадцатеричный символ для int в C ++ - PullRequest
3 голосов
/ 23 июня 2011

Как я могу изменить шестнадцатеричный символ, а не строку, в числовое значение?

При наборе этого вопроса я нашел много ответов о том, как преобразовать шестнадцатеричные строки в значения.Тем не менее, никто не работает для символов.Я помню, как читал где-то, что это работает для строк:

std::string mystr = "12345";
unsigned int myval;
std::stringstream(mystr) >> std::hex >> myval;

Однако, если я сделаю mystr[x] в цикле, этот код не будет работать.Я попытался добавить новую строку с std::string temp = mystr[x] и изменить std::stringstream(mystr) на std::stringstream(temp), но это тоже не работает.

Так как мне это сделать?В настоящее время я ищу строку шестнадцатеричных символов ("0123456789abcdef".find(mystr[x]);) и использую индекс для значения.Однако, поскольку он выполняет поиск, он работает медленно, даже если он ищет только 16 символов.

http://ideone.com/dIyD4

Ответы [ 4 ]

8 голосов
/ 23 июня 2011
int intval = (hexchar >= 'A') ? (hexchar - 'A' + 10) : (hexchar - '0');
4 голосов
/ 13 февраля 2017

Тройка от levis501 может быть расширена до:

int v = (c >= 'A') ? (c >= 'a') ? (c - 'a' + 10) : (c - 'A' + 10) : (c - '0');

Но если вам нужна проверка ошибок, она становится немного грязной:

int v = (c < '0')  ? -1 :
        (c <= '9') ? (c - '0') :
        (c < 'A')  ? v = -1 :
        (c <= 'F') ? (c - 'A' + 10) :
        (c < 'a')  ? v = -1 :
        (c <= 'f') ? (c - 'a' + 10) : -1;

В блоках if-else это выглядит не намного лучше:

int v = -1;
if ((c >= '0') && (c <= '9'))
    v = (c - '0');
else if ((c >= 'A') && (c <= 'F'))
    v = (c - 'A' + 10);
else if ((c >= 'a') && (c <= 'f'))
    v = (c - 'a' + 10);

Поскольку я хотел быструю реализацию и проверку, я обратился к таблице поиска:

int ASCIIHexToInt[] =
{
    // ASCII
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

    // 0x80-FF (Omit this if you don't need to check for non-ASCII)
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
};

В данном случае это просто:

int v = ASCIIHexToInt[c];
if (v < 0)
    // Invalid input

Работоспособные примеры (надеюсь) здесь и здесь .

2 голосов
/ 23 июня 2011

У вас уже есть решение, которое работает со строками.Используйте его также для char с:

#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
  char val = 'A';
  unsigned int myval;
  std::stringstream ss;
  ss << val;
  ss >> std::hex >> myval;
  cout << myval << endl;
}

Код

0 голосов
/ 23 июня 2011

Что-то вроде следующего?

//!         \return
//!             The numeric value of ch, if it is hex, otherwise -1
int
fromHexChar( char ch )
{
    static char const hexChars[] = "0123456789ABCDEF";
    char const* p = std::find( begin( hexChars ), end( hexChars ),
                               ::tolower( (unsigned char)ch ) );
    return p == end( hexChars )
        ? -1
        : p - begin( hexChars );
}
...