I found the code to convert a hexadecimal string into a signed int
using strtol
, but I can't find something for a 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
...
Edit : I already tried with the hex operator, but I still have to convert the string to an integer before doing so.
// This won't work as currentString is not an integer
myInt << std::hex << currentString.c_str();
Have you considered sscanf
with the "%hx" conversion qualifier?
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 ...
}
You can probably use stringtream class's >> operator with hex manipulator.
// 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
}
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());
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"
来源:https://stackoverflow.com/questions/1487440/convert-hexadecimal-string-with-leading-0x-to-signed-short-in-c