Conversion d'une chaîne hexadécimale avec le premier « 0x » à court signé en C ++?

StackOverflow https://stackoverflow.com/questions/1487440

  •  18-09-2019
  •  | 
  •  

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(); 
Était-ce utile?

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"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top