2009-12-30 8 views
1

J'ai écrit une fonction pour prendre les données d'un lecteur Sirit IDitity MaX AVI et analyser le code d'installation et le numéro de carte-clé. Comment je le fais actuellement fonctionne, mais y a-t-il un meilleur moyen? Semble peu hackish ... buff & buf sont de taille 264Convertir Hex Char en Int - Y at-il un meilleur moyen?

buf et buff sont carboniser

Les données reçues du lecteur:

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 
} 
+0

Quel est le format de buf? –

+0

Vous pouvez utiliser 'strtoul()' dans la bibliothèque standard C. –

+0

'strtol' et' strtoul' sont mes fonctions préférées pour cela parce qu'ils sont si flexibles. Ils peuvent faire hex, décimal, octal et binaire (n'importe quelle base de 2 à 36, vraiment), et si vous dites base 0, ils vont utiliser des préfixes de style C ('0' pour octal,' 0x' pour hex, pas de préfixe pour décimal) pour comprendre la base. Idéal pour les paramètres d'analyse. La seule chose qu'ils ne font pas est la base 64. –

Répondre

1

Voici un moyen facile d'obtenir les données que vous voulez . Je travaille dans le domaine du contrôle d'accès, donc c'était quelque chose qui m'intéressait ...

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 
} 
+0

obtenir cette erreur: 'opérateur <<' pas mis en œuvre dans le type 'chaîne' pour les arguments de type 'istringstream' –

+0

Ouais, désolé à ce sujet, il aurait dû être> > pas <<. J'ai changé le code de toute façon, alors essayez les nouveaux produits. – joshperry

+0

Je pense que c'est quelque chose qui manque parce qu'il ne compile pas correctement .. symbole indéfini 'is' et' read' –

8

Il suffit d'utiliser 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; 
} 

Vous pouvez également utiliser strtol de 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; 
    } 
} 
+0

Si c'est un problème qui est susceptible d'être commun (analyser les chaînes d'entrée en nombres) il y a presque sûrement une fonction de bibliothèque pour le gérer déjà pour vous. – jason

+1

'char * p; * key_num = strtol (& buff [140], & p, 16); 'travaillé - merci! –

+0

@Roboto: Super, contente que je puisse aider. – jason

1

Puisque vous utilisez déjà sscanf, pourquoi ne pas avoir analyser les nombres hexadécimaux pour vous:

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

& buf [140] sort comme/# lorsque vous faites cela –