【问题标题】:Convert Hex Char To Int - Is there a better way?将十六进制字符转换为整数 - 有更好的方法吗?
【发布时间】:2010-12-31 04:40:45
【问题描述】:

我编写了一个函数来从 Sirit IDentity MaX AVI 阅读器中获取数据并解析出设施代码和钥匙卡号。我目前的工作方式如何,但有更好的方法吗?似乎有点 hackish...buff 和 buf 的大小为 264

bufbuff 是字符

从阅读器收到的数据:

2009/12/30 14:56:18 epc0 LN:001 C80507A0008A19FA 0000232F Xlat'd

char TAccessReader::HexCharToInt(char n)
{
    if (n >= '0' && n <= '9')
        return (n-'0');
    else

    if (n >= 'A' && n <= 'F')
        return (n-'A'+10);
    else
        return 0;
}

bool TAccessReader::CheckSirit(char *buf, long *key_num, unsigned char *fac) {

   unsigned short i, j, k;

   *key_num = 0; // Default is zero
   memset(buff, 0, sizeof(buff));

   i = sscanf(buf, "%s %s %s %s %s %s %s", &buff[0], &buff[20], &buff[40],
              &buff[60], &buff[80], &buff[140], &buff[160]);
   if (i == 7 && buff[147] && !buff[148]) {
       // UUGGNNNN UU=spare, GG=Facility Code, NNNN=Keycard Number (all HEX)

       // get facility code

       *fac = HexCharToInt(buff[142]) * 16 + HexCharToInt(buff[143]);
       *key_num = (unsigned short)HexCharToInt(buff[144]) * 4096 +
                  (unsigned short)HexCharToInt(buff[145]) * 256 +
                  (unsigned short)HexCharToInt(buff[146]) * 16 +
                  HexCharToInt(buff[147]);
   }
   // do some basic checks.. return true or false
}

【问题讨论】:

  • 您可以使用 C 标准库中的 strtoul()
  • strtolstrtoul 是我最喜欢的函数,因为它们非常灵活。他们可以使用十六进制、十进制、八进制和二进制(实际上是从 2 到 36 的任何基数),如果你说以 0 为基数,他们将使用 C 风格的前缀(0 表示八进制,0x 表示十六进制,小数点没有前缀)来计算基数。非常适合解析参数。他们唯一不做的是base 64。

标签: c++ parsing hex


【解决方案1】:

只需使用std::stringstream:

#include <sstream>
#include <iostream>

using namespace std;

int main() {
    unsigned int x;   
    stringstream ss;
    ss << hex << "ff";
    ss >> x;
    // output it as a signed type
    cout << static_cast<int>(x) << endl;
}

您也可以直接使用 C 中的strtol

#include <cstdlib>
#include <iostream>

using namespace std;

int main() {
    string s = "ff";
    char *p;
    long n = strtol(s.c_str(), &p, 16);
    if (*p != 0) {
        cout << "fail" << endl;
    }
    else {
        cout << n << endl;
    }
}

【讨论】:

  • 如果问题可能很常见(将输入字符串解析为数字),几乎可以肯定已经有一个库函数可以为您处理。
  • char *p; *key_num = strtol(&amp;buff[140], &amp;p, 16); 工作 - 谢谢!
  • @Roboto:太好了,很高兴我能帮上忙。
【解决方案2】:

这是获取所需数据的简单方法。我确实在访问控制业务中工作,所以这是我感兴趣的事情......

template<typename TRet, typename Iterator>
TRet ConvertHex(Iterator begin) {
    unsigned long result;

    Iterator end = begin + (sizeof(TRet) * 2);
    std::stringstream ss(std::string(begin, end));
    ss >> std::hex >> result;

    return result;
}

bool TAccessReader::CheckSirit(char *buf, long *key_num, unsigned char *fac) {
   *key_num = 0; // Default is zero

   std::istringstream sbuf(std::string(buf, buf+264));

   // Stuff all of the string elements into a vector
   std::vector<std::string> elements;
   std::copy (std::istream_iterator<std::string>(sbuf), std::istream_iterator<std::string>(), std::back_inserter (elements));

   // We're interested in the 6th element
   std::string read = elements[5];

   if (read.length() == 8) {
       // UUGGNNNN UU=spare, GG=Facility Code, NNNN=Keycard Number (all HEX)

       // get facility and card code
       std::string::const_iterator iter = read.begin();
       *fac = ConvertHex<unsigned char>(iter + 2);
       *key_num = ConvertHex<unsigned short>(iter + 4);
   }
   // do some basic checks.. return true or false
}

【讨论】:

  • 收到此错误:'operator
  • 是的,很抱歉,应该是>>而不是
  • 我认为它缺少一些东西,因为它没有正确编译.. undefined symbol is and read
  • 是的,这就是我没有真正尝试过的结果。我已经编译了它,代码现在应该可以工作了。我不确定你想在if 语句中检查什么,所以我只是检查了长度。
  • return result; 被调用时,它会杀死我的线程。我猜这不是线程安全的?
【解决方案3】:

既然您已经在使用 sscanf,为什么不让它为您解析十六进制数字:

sscanf(buff, "%x %x", &val1, &val2);

【讨论】:

  • &buf[140] 当你这样做时会显示为 /#
猜你喜欢
  • 2015-11-29
  • 2013-09-07
  • 2010-10-16
  • 2017-08-12
  • 2015-07-28
  • 2014-12-15
相关资源
最近更新 更多