C++中将十六进制字符转换为整数

9

如何将十六进制字符转换为数字值?

在提问时,我发现很多答案都是关于如何将十六进制字符串转换为数值的。然而,对于字符来说,这些方法都不适用。我记得在某个地方读到过这个方法适用于字符串:

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

1
很难理解你尝试了什么。为什么不发布你尝试过的所有变体,并解释每个变体为什么不起作用。 - Martin York
4个回答

11
int intval = (hexchar >= 'A') ? (hexchar - 'A' + 10) : (hexchar - '0');

你的代码是否有适用于不同大小写十六进制字符的版本?(例如,“a”、“A”) - quamrana
只需在使用该表达式之前将十六进制字符转换为大写字母即可。 - Ajay
@quamrana:我在我的答案中添加了小写支持。 - Nick Westgate

8
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

可以在这里(链接)和这里(链接)找到可运行的示例。


一个通用的数字转换为值的程序,支持36进制(/[0-9A-Za-z]+/),可以表示如下: byte digit(signed char c) { if (c<='9') return c-'0'; c&=~0x20; // 将小写字母转换为大写字母 if (c<'A') return 0xFF; return c-'A'+10; 所有返回值大于或等于所需基数的字符都被视为无效字符。 - Henrik Haftmann

3

你已经有一个适用于字符串的解决方案。同样可以用于 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;
}

Code


一种好的方法,但如果输入字符超出有效范围,则无法抛出错误。在这种情况下,stringstream 总是返回 0 - dizcza

-1

类似以下的内容?

//!         \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 );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接