开发者

Convert Hex Char To Int - Is there a better way?

I have written a function to take in the data from a Sirit IDentity MaX AVI read开发者_如何学运维er and parse out the facility code and keycard number. How I am currently doing it works, but is there a better way? Seems little hackish... buff & buf are size 264

buf and buff are char

Data received from reader:

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
}


Just use 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;
}

You can also use strtol from straight-up C:

#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;
    }
}


Here's an easy way to get at the data you want. I do work in the access control business so this was something that interested me...

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
}


Since you are already using sscanf, why not have it parse the hex numbers for you:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜