Click here to Skip to main content
Click here to Skip to main content

Convert a "Hex String" to an Integer

By , 15 Jan 2001
 
  • Download demo project - 8 Kb
  • Convert a "Hex String" to an Integer

    Sometimes I have had a string containing a Hex Value like char s[10] = "0xFDE8"; that I would like to convert to an integer (in this case it would of course get the value 65000). I have not been able to find any standard C or C++ functions to do that, so I decided to write my own. It's declared as _httoi(const TCHAR *value) and is coded using TCHAR so it works both with and without UNICODE defined

    It's possible it could be done smarter and faster, but it works and if you like it it's yours to use for free.

    Here is the code to a small console application that uses the function, and demostrates its use.

    #include "stdafx.h"
    #include <tchar.h>
    #include <malloc.h>
    
    int _httoi(const TCHAR *value)
    {
      struct CHexMap
      {
        TCHAR chr;
        int value;
      };
      const int HexMapL = 16;
      CHexMap HexMap[HexMapL] =
      {
        {'0', 0}, {'1', 1},
        {'2', 2}, {'3', 3},
        {'4', 4}, {'5', 5},
        {'6', 6}, {'7', 7},
        {'8', 8}, {'9', 9},
        {'A', 10}, {'B', 11},
        {'C', 12}, {'D', 13},
        {'E', 14}, {'F', 15}
      };
      TCHAR *mstr = _tcsupr(_tcsdup(value));
      TCHAR *s = mstr;
      int result = 0;
      if (*s == '0' && *(s + 1) == 'X') s += 2;
      bool firsttime = true;
      while (*s != '\0')
      {
        bool found = false;
        for (int i = 0; i < HexMapL; i++)
        {
          if (*s == HexMap[i].chr)
          {
            if (!firsttime) result <<= 4;
            result |= HexMap[i].value;
            found = true;
            break;
          }
        }
        if (!found) break;
        s++;
        firsttime = false;
      }
      free(mstr);
      return result;
    }
    
    int main(int argc, char* argv[])
    {
      TCHAR *test[4] = {_T("0xFFFF"), _T("0xabcd"), _T("ffff"), _T("ABCD")};
      for (int i = 0; i < 4; i++)
        _tprintf(_T("Hex String: %s is int: %d\n\r"), test[i], _httoi(test[i]));
      return 0;
    }
    

    Well, that's all there is to it. You can either copy the code from your browser, or download the project for Visual C++ 6.0.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    About the Author

    Anders Molin
    Software Developer (Senior)
    Denmark Denmark
    Member
    Huh! Wink | ;-)

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    QuestionLicense?memberMember 896106510 Jul '12 - 2:50 
    Could you please tell which OSS license applies?
    Thanks.
    GeneralInteger string (64bit) to hex having only 32 bitmemberRomanoScuri13 Sep '10 - 22:41 
    //----------------------------------------------------------
    //
    // Intstring2hex.c
    //
    //----------------------------------------------------------
     
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    //----------------------------------------------------------
     
    typedef struct {
    unsigned lo;
    unsigned hi;
    } int64bit;
     
    //----------------------------------------------------------
     
    static int64bit add_int64bit(int64bit op1,int64bit op2)
    {
    int64bit sum;
     

    sum.lo = op1.lo+op2.lo;
    sum.hi = op1.hi+op2.hi;
     
    if ((0xFFFFFFFF - op1.lo) < op2.lo) {
    ++sum.hi;
    }
     
    return(sum);
    }
     
    //----------------------------------------------------------
    // la moltiplicazione è ottenuta come somma (n x val = val + val +val...)
    // dato che "fat" dovrebbe essere un intero minore o uguale a 10
     
    static int64bit mul_int64bit(int64bit val,int fat)
    {
    int64bit res;
    int i;
     

    res.lo = 0;
    res.hi = 0;
     
    for (i = 0; i<fat; i++) {
    res = add_int64bit(res,val);
    }
     
    return(res);
    }
     
    //----------------------------------------------------------
     
    static int intstr2int64bit(char *s,int64bit *pint64bit)
    {
    int len = strlen(s);
    int i,n;
    int64bit val;
    int64bit num;
    int64bit inc;
     

    pint64bit->lo = 0;
    pint64bit->hi = 0;
     
    val.lo = 0;
    val.hi = 0;
     
    for (i = (len-1); i>=0; i--) {
    if (isdigit(s[i])) {
    n = s[i]-'0';
     
    if (i==(len-1)) {
    inc.hi = 0;
    inc.lo = n;
    num.hi = 0;
    num.lo = 1;
    }
    else {
    num = mul_int64bit(num,10);
    inc = mul_int64bit(num,n);
    }
     
    val = add_int64bit(val,inc);
    }
    else {
    return(0);
    }
    }
     
    pint64bit->lo = val.lo;
    pint64bit->hi = val.hi;
     
    return(1);
    }
     
    //----------------------------------------------------------
     
    static int intstr2hex(char *src,char *dst)
    {
    int64bit val;
     

    if (intstr2int64bit(src,&val)) {
    sprintf(dst,"%08X%08X",val.hi,val.lo);
     
    return(1);
    }
     
    return(0);
    }
     
    //----------------------------------------------------------
     
    void main(void)
    {
    char s[80];
    char ss[80];
     

    printf("? ");
    gets(s);
     
    if (intstr2hex(s,ss)) {
    printf("\n[%s] =---> [%s]\n",s,ss);
    }
    }
     
    //----------------------------------------------------------
    GeneralOh my god- so much code and for what??? Something that is already done with one line using "strtol"memberTheBishop7 May '09 - 5:39 
    Mad | :mad:
     
    The whole concept of code reuse has been trampled upon. And for what??? What advantages does it bring? Here is one line solution:
     
    strtol({HEX_NUMBER_STRING}, NULL, 16)
    Generalefficient & no library dependencies:membertektor15 Dec '08 - 12:04 
    unsigned int HexStringToUInt(char* s)
    {
    unsigned int v = 0;
    while (char c = *s++)
    {
    if (c < '0') return 0; //invalid character
    if (c > '9') //shift alphabetic characters down
    {
    if (c >= 'a') c -= 'a' - 'A'; //upper-case 'a' or higher
    if (c > 'Z') return 0; //invalid character
    if (c > '9') c -= 'A'-1-'9'; //make consecutive with digits
    if (c < '9' + 1) return 0; //invalid character
    }
    c -= '0'; //convert char to hex digit value
    v = v << 4; //shift left by a hex digit
    v += c; //add the current digit
    }
     
    return v;
    }
     
    Most of the branches can be eliminated (and thus any cost of their potentially failed prediction) with 'select' operations, depending on your processor.
    Generaldead horsememberc. leamon11 Sep '07 - 4:08 
    not to beat a dead horse, but if you want to use this rather than some of the slower methods suggested by others, you can eliminate the use of the variable 'firsttime', since it's only used to eliminate shifting (<<4) on the first hex digit. That one shift is probably faster than the test for firsttime (occurs for every digit), and it's OK to shift unconditioinally since shifting those zeros has no affect on the results.

    QuestionWhy re-invent the wheel ?memberdamnedyankee8 Dec '06 - 1:10 
    stringstream ss;
    long val;
    ss << setbase(16) << "0xFDE8";
    ss >> val;

    AnswerRe: Why re-invent the wheel ?memberFrancesco Pratolongo4 Apr '07 - 9:22 
    How beautyful is the Standard Library!!!!!
    Thank you, you save me a lot of time (and lines of code...Big Grin | :-D )
    GeneralShorter Codemembernfalabi29 Oct '06 - 19:08 
    It can also be done like this:
     
    UINT HexToDec(const TCHAR *szValue)
    {
    UINT iValue;
    _stscanf(szValue, _TEXT("%x"), &iValue);
    return iValue;
    }
     
    I think it's much cleaner and simpler Smile | :)
    GeneralRe: Shorter Codememberas_sound_as6 May '07 - 6:56 
    'swscanf' was declared deprecated
     
    you can use also
     
    CString s = _T("1A");
    long k = wcstol( _T("0x") + s , 0, 0 );
     
    Smile | :)

    General:) nice but...membernicekr14 Aug '06 - 4:12 
    what about 0x0000ea64 style?
    i try to convert hex string but return 0...

     
    nicekr

    Generalgreat!!memberKIM HyunJoong3 Jul '06 - 19:05 
    good~~
     
    gogogo!!
    Generalsscanf will do too ...sussAnonymous27 Sep '05 - 3:08 


    CString hex_num("FDE8");
    int dec_num;
    sscanf(hex_num,"%x",&dec_num);

    GeneralRe: sscanf will do too ...memberspinoza4 Jan '06 - 15:53 
    this will also do but it is to slow..
     

    bool CCoder::HexEncode(BYTE*pData,TCHAR*pCode)
    {
    TCHAR buffer[3];
    BYTE b=*pData;
     
    if (b<16)
    {
    buffer[0]='0';
    _itoa(b,buffer+1,16);
    }else
    _itoa(b,buffer,16);
     
    memcpy(pCode,buffer,2);
    return true;
    }
     
    bool CCoder::HexDecode(TCHAR*pCode,BYTE*pData)
    {
    TCHAR nr[3];
    BYTE i;
    nr[2]='\0';
    memcpy(nr,pCode,2);
     
    sscanf(nr,"%x",&i);
    *pData=i;
     
    return true;
    }
     
    //Spinoza
    GeneralThanksmemberCodin' Carlos16 Oct '02 - 19:58 
    It's 2am here. This converter did the trick. I didn't think about strtol either, but i can tell you i chaff at doing cstring.GetBuffer's etc, esp in unicode CE. Thanks for saving me a headache!
    GeneralRe: ThankssussAnonymous17 Nov '04 - 5:00 
    Yep good job, remember that strtol only returns a long so easy to overflow! Change your _httoi to return dword/unsigned long, cheers! Smile | :)
    GeneralRe: Thanksmemberc4l23 Apr '06 - 11:26 
    Thanks Anders, It works !!!!!!!
     
    Big Grin | :-D
    General;P If you speaking about C++ then this is the solution for converting a hexadecimal string to an integermemberAnonymous12 Jun '02 - 2:19 
    Cry | :((
    I look on the net by 2 hours ago for thsi but I didn't found anything. Then I tried this:
    OMG | :OMG:
    -char Str[]={"0x00f"};
    -int n;
    -sscanf(Str,"%x",&n);
    now n is 15
    And work.
    So simple. Poke tongue | ;-P
    for converting a string to int then use atoi forint or atof for float
    Cool | :cool:
     
    SilverStar
    GeneralUse strtol.sussAnonymous25 Jul '02 - 11:00 
    You guys ever try strtol.. Check it out.. you didn't have to write anything.
    GeneralString to IntmemberKomtiki21 Apr '02 - 22:01 
    Nice peace of work. I found it very helpfull. Now can you tell me how can I can I convert a normal string to an integer. I have tried StrToInt but I cant get it to work. I don't know maybe I'm stupid but it says StrToInt Undeclared identifier. Can you help.OMG | :OMG:
    GeneralRe: String to IntmemberAnders Molin8 May '02 - 11:33 
    int i = atoi("55");
     
    That does the trick...
     
    - Anders
     
    Money talks, but all mine ever says is "Goodbye!"
    GeneralTry This alsomemberNMS10 Aug '01 - 0:45 
    long BinfromHex(CString sz)
    {
    // This code is used to get the decimal value from given hexadecimal string
     
    long m_nbinVal=0; // stores the decimal value
    int cnt=0;
    for (int i = sz.GetLength()-1; i>=0; i--)
    {
    TCHAR psz;
    int val;
    lstrcpy(&psz,(LPCTSTR)sz.Mid(i,1)); // gets the one by one each character or numeric value and assign the according no
    switch (psz)
    {
    case 'A' :
    case 'a' : val = 10;
    break;
    case 'B' :
    case 'b' : val = 11;
    break;
    case 'C' :
    case 'c' : val = 12;
    break;
    case 'D' :
    case 'd' : val = 13;
    break;
    case 'E' :
    case 'e' : val = 14;
    break;
    case 'F' :
    case 'f' : val = 15;
    break;
    default : val = atoi(&psz);
    }
    m_nbinVal = m_nbinVal + long(pow(16,cnt) * val); // gets the according decimal value of hexadecimal value
    cnt++;
    }
    return m_nbinVal; // return s the converted value
    }
    Blush | :O
    GeneralUsing CString again...memberLiqo14 Mar '01 - 5:03 
    CString szHex = "FF";
    int i = (int)strtol(szHex+'\n',(char **)NULL,16);
    GeneralSlooooooow lookupmemberOz Solomonovich17 Jan '01 - 6:33 
    You're using a lookup structure, but with a for() loop to scan through it! This is very inefficient.
     
    If you are already using a lookup, why not go all the way? Create a 256 entry lookup (actually less - you need only to go up to "f"), so, given a character you can do
     
    value = lookup[ch];
     
    Another, more efficient way than you present is:
     
    if (isdigit(ch))
    {
    value = ch - '0';
    }
    else
    {
    value = (ch | 0x20) - 'a' + 10;
    }
     
    This is assuming valid input (i.e. no "g"'s in the input, etc.)
     
    -Oz
     

    ---
    Grab WndTabs from http://www.wndtabs.com to make your VC++ experience that much more comfortable...
    GeneralAnother way -- using CStringmemberPaul Wolfensberger14 Jan '01 - 5:32 
    // Convert a hexencode string to a "long" value
    // Only pass the hex "digits"...no symbols like "0x..."
    static long HexToLong(CString& szHexValue)
    {
    // Make the string a set of upper case, spaceless values
    szHexValue.MakeUpper();
    szHexValue.TrimLeft();
    szHexValue.TrimRight();
     
    // Convert the digits number to values
    long lDigitCount = szHexValue.GetLength();
    for (long lDigit=0, lValue=0; lDigit < lDigitCount; ++lDigit)
    {
    // Make a "space" for the next hex value
    lValue *= 16;
     
    // Now convert a single digit to a number
    TCHAR cDigit = szHexValue.GetAt(lDigit);
    if (cDigit >= '0' && cDigit <= '9')
    lValue += cDigit - '0';
    else if (cDigit >= 'A' && cDigit <= 'F')
    lValue += 10 + cDigit - 'A';
    else
    throw "Bad digit in Hex value string\nCStringConvert::HexToLong()";
    }
    return lValue;
    }

    Generalstd::stringstreammemberWilka12 Jan '01 - 12:33 
    You could use std::stringstream, e.g.
     
    const char* str = "0xFF";
     
    std::stringstream stream;
     
    stream << str;
     
    int n;
     
    stream >> std::hex >> n;
     
    assert(n == 255);

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Permalink | Advertise | Privacy | Mobile
    Web04 | 2.6.130516.1 | Last Updated 16 Jan 2001
    Article Copyright 2001 by Anders Molin
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid