Conversion d'une chaîne hexadécimale avec le premier « 0x » à court signé en C ++?
Question
J'ai trouvé le code pour convertir une chaîne hexadécimale en utilisant signed int
strtol
, mais je ne peux pas trouver quelque chose pour un short int (2 octets). Voici mon morceau de code:
while (!sCurrentFile.eof() )
{
getline (sCurrentFile,currentString);
sOutputFile<<strtol(currentString.c_str(),NULL,16)<<endl;
}
Mon idée est de lire un fichier avec 2 octets de large (comme valeurs 0xFFEE), le convertir en entier signé et écrire le résultat dans un fichier de sortie. La vitesse d'exécution est pas un problème.
Je pourrais trouver des moyens d'éviter le problème, mais je voudrais utiliser une solution « une ligne », alors peut-être vous pouvez aider à cela:)
Edit: Les fichiers ressemblent à ceci:
0x0400
0x03fe
0x03fe
...
Modifier. Je l'ai déjà essayé avec l'opérateur hexagonal, mais je dois encore convertir la chaîne en un entier avant de le faire
// This won't work as currentString is not an integer
myInt << std::hex << currentString.c_str();
La solution
Avez-vous envisagé sscanf
avec le qualificatif de conversion "% hx"?
Autres conseils
Cela devrait être 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";
}
Alors que nous parlons de fichiers:
Vous devez pas faire ceci:
while (!sCurrentFile.eof() )
{
getline (sCurrentFile,currentString);
... STUFF ...
}
En effet, lorsque vous lisez la dernière ligne Finalité pas définir l'EOF. Ainsi, lorsque vous boucle autour, puis lisez la ligne après la dernière ligne, getline () échouera et vous allez faire STUFF sur ce qui était dans CurrentString de la dernière fois qu'il a été mis en place. Donc, en effet vous aurez traite la dernière ligne deux fois.
La bonne façon de boucle sur un fichier est le suivant:
while (getline(sCurrentFile,currentString))
{
// If the get fails then you have read past EOF and loop is not entered.
... STUFF ...
}
Vous pouvez probablement utiliser stringtream de classe >> opérateur avec manipulateur hexagonal.
// 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
}
Si vous êtes sûr que les données peuvent être dignes de confiance currentString.c_str()
, alors vous pouvez aussi le faire facilement
myInt << std::hex << atoi(currentString.c_str());
Si vous connaissez les données sont toujours va être dans ce format, vous ne pourriez pas faire quelque chose comme:
myInt << std::hex << currentString.c_str() +2; // skip the leading "0x"