views:

706

answers:

6

Hi, I could find the code to convert a hexadecimal string into a signed int (using strtol), but I can't find something for short int (2 bytes). Here' my piece of code :

while (!sCurrentFile.eof() )
{
 getline (sCurrentFile,currentString);
 sOutputFile<<strtol(currentString.c_str(),NULL,16)<<endl;
}

My idea is to read a file with 2 bytes wide values (like 0xFFEE), convert it to signed int and write the result in an output file. Execution speed is not an issue.

I could find some ways to avoid the problem, but I'd like to use a "one line" solution, so maybe you can help for this :)

Edit : The files look like this :

0x0400
0x03fe
0x03fe
etc...

Edit : I already tried with the hex operator, but I still have to convert the string to an integer before doing so.

myInt<<std::hex<<currentString.c_str(); //This won't work as currentString is no integer.

Thanks to ChrisV, the answer is:

 sscanf(currentString.c_str(),"%hx",&myVar); 
 sOutputFile << myVar << endl;
+3  A: 

Have you considered sscanf with the "%hx" conversion qualifier?

ChrisV
Or, if you don't have any particular need to use C++ I/O streams, go straight to fscanf... Depends on how much of that code you control.
ChrisV
fscanf and sscanf are how I usually handle this. I have a program right now that reads CRC hex strings similar to this: sscanf(cstr_fileCRC, "%lX",
John D.
+4  A: 

You can probably use stringtream class's >> operator with hex manipulator.

Naveen
Exactly what I needed, it's just one line big !
gramm
A: 

If you're sure the data can be trusted from currentString.c_str(), then you could also easily do

myInt << std::hex << atoi(currentString.c_str());
Chaosteil
Why use the C functions when the C++ stream aleady does all the work.
Martin York
A: 

If you know the data is always going to be in that format, couldn't you just do something like:

myInt << std::hex << currentString.c_str() +2; // skip the leading "0x"
Here the std::hex does nothing as it processing a string. You are just re-printing the string you read (minus the first two characters).
Martin York
+1  A: 

This should be simple:

std::ifstream   file("DataFile");
int             value;

while(file >> std::hex >> value)  // Reads a hex string and converts it to an int.
{
    std::cout << "Value: " << std::hex << value << "\n";
}

While we are talking about files:
You should NOT do this:

while (!sCurrentFile.eof() )
{
    getline (sCurrentFile,currentString);
    ... STUFF ...
}

This is because when you read the last line it does NOT set the EOF. So when you loop around and then read the line after the last line, getline() will fail and you will be doing STUFF on what was in currentString from the last time it was set up. So in-effect you will processes the last line twice.

The correct way to loop over a file is:

while (getline(sCurrentFile,currentString))
{
    // If the get fails then you have read past EOF and loop is not entered.
    ... STUFF ...
}
Martin York
A: 
// convert unsigned-integer to it's hexadecimal string represention
// 0x12345678 -> '12345678'
// N is BYTE/WORD/UINT/ULONGLONG
// T is char or wchar_t
template <class N, class T> inline T* UnsignedToHexStr(N    n             ,  // [i  ]
                                                       T*   pcStr         ,  // [i/o] filled with string
                                                       UINT nDigits       ,  // [i  ] number of digits in output string / 0 (auto)
                                                       bool bNullTerminate ) // [i  ] whether to add NULL termination
{
    if ((N)-1 < (N)1)              // if type of N is floating-point / signed-integer
        if (::IsDebuggerPresent())
        {
            ::OutputDebugString(_T("UnsignedToHexStr: Incorrect type passed\n"));
            ::DebugBreak();
        }

    if (!nDigits)
        nDigits= GetUnsignedHexDigits(n);

    if (1 == sizeof(T))
    {
        const char _czIntHexConv[]= "0123456789ABCDEF";
        for (int i= nDigits-1; i>= 0; i--)
        {
            char* pLoc= (char*)&pcStr[i];
            *pLoc= _czIntHexConv[n & 0x0F];
            n >>= 4;
        }
    }
    else
    {
        const wchar_t _czIntHexConv[]= L"0123456789ABCDEF";
        for (int i= nDigits-1; i>= 0; i--)
        {
            wchar_t* pLoc= (wchar_t*)&pcStr[i];
            *pLoc= _czIntHexConv[n & 0x0F];
            n >>= 4;
        }
    }

    if (bNullTerminate)
        pcStr[nDigits]= 0;

    return pcStr;
}



// --------------------------------------------------------------------------
// convert unsigned-integer in HEX string represention to it's numerical value
// '1234' -> 0x1234
// N is BYTE/WORD/UINT/ULONGLONG
// T is char or wchar_t
template <class N, class T> inline bool HexStrToUnsigned(const T* pczSrc                    ,
                                                         N&       n                         ,
                                                         bool     bSpecificTerminator= false,  // whether string should terminate with specific terminating char
                                                         T        cTerminator        = 0     ) // specific terminating char
{
    n= 0;

    if (!pczSrc)
        return false;

    while ((32 == *pczSrc) || (9 == *pczSrc))
        pczSrc++;

    bool bLeadZeros= *pczSrc == _T('0');
    while (*pczSrc == _T('0')) // skip leading zeros
        pczSrc++;

    BYTE nMaxDigits= 2*sizeof(N);
    BYTE nDigits   = 0          ;

    while (true)
    {
        if ( (*pczSrc >= _T('0')) && (*pczSrc <= _T('9')))
        { if (nDigits==nMaxDigits) return false; n= (n<<4) + (*pczSrc-_T('0')   ); pczSrc++; nDigits++; continue; }

        if ( (*pczSrc >= _T('A')) && (*pczSrc <= _T('F')))
        { if (nDigits==nMaxDigits) return false; n= (n<<4) + (*pczSrc-_T('A')+10); pczSrc++; nDigits++; continue; }

        if ( (*pczSrc >= _T('a')) && (*pczSrc <= _T('f')))
        { if (nDigits==nMaxDigits) return false; n= (n<<4) + (*pczSrc-_T('a')+10); pczSrc++; nDigits++; continue; }

        if (bSpecificTerminator)
            if (*pczSrc != cTerminator)
                return false;

        break;
    }

    return (nDigits>0) || bLeadZeros; // at least one digit
}
Lior Kogan
You are obviously quite mad :-)
Martin York