Question

Je veux convertir une chaîne hexadécimale à un entier signé 32 bits en C ++.

Ainsi, par exemple, j'ai la chaîne hexagonale « de fffefffe ». La représentation binaire de c'est 11111111111111101111111111111110. La représentation entière signée de c'est: -65538.

Comment dois-je faire cette conversion en C ++? Cela doit aussi travailler pour les nombres non négatifs. Par exemple, la chaîne hexagonale « 0000000A », qui est 00000000000000000000000000001010 en binaire, et 10 en décimal.

Était-ce utile?

La solution

Utilisation std::stringstream

unsigned int x;   
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;

l'exemple suivant produit comme résultat -65538:

#include <sstream>
#include <iostream>

int main() {
    unsigned int x;   
    std::stringstream ss;
    ss << std::hex << "fffefffe";
    ss >> x;
    // output it as a signed type
    std::cout << static_cast<int>(x) << std::endl;
}

Dans la nouvelle norme C ++ 11, il y a quelques nouvelles fonctions utilitaires que vous pouvez faire usage de! Plus précisément, il y a une famille de fonctions « chaîne à numéro » ( http: // fr .cppreference.com / w / cpp / string / basic_string / stol et http://en.cppreference.com/w/cpp/string/basic_string/stoul ). Ce sont essentiellement minces emballages autour de la chaîne de C à des fonctions de conversion de nombre, mais savent comment faire face à une std::string

Alors, la réponse la plus simple pour le code plus récent serait probablement ressembler à ceci:

std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);

Remarque: Voici ma réponse originale, qui, comme l'édition dit n'est pas une réponse complète. Pour une solution fonctionnelle, coller le code ci-dessus la ligne: -.)

Il semble que depuis est défini lexical_cast<> avoir une sémantique de conversion de flux. Malheureusement, les flux ne comprennent pas la notation « 0x ». Donc, à la fois la main et boost::lexical_cast roulé un ne traitent pas correctement avec des chaînes hexagonales. La solution ci-dessus qui définit manuellement le flux d'entrée à HEX gérer très bien.

Boost a quelques trucs pour faire en bien, qui a une erreur belle vérification des capacités aussi bien. Vous pouvez l'utiliser comme ceci:

try {
    unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
    // whatever you want to do...
}

Si vous ne vous sentez pas comme l'utilisation de boost, voici une version allégée de cast lexical qui ne vérifie pas d'erreur:

template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
    T2 out;
    std::stringstream ss;
    ss << in;
    ss >> out;
    return out;
}

que vous pouvez utiliser comme ceci:

// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef"); 

Autres conseils

Pour une méthode qui fonctionne à la fois C et C ++, vous voudrez peut-être envisager d'utiliser la fonction de bibliothèque standard strtol ().

#include <cstdlib>
#include <iostream>
using namespace std;

int main() {
    string s = "abcd";
    char * p;
    long n = strtol( s.c_str(), & p, 16 );
    if ( * p != 0 ) { //my bad edit was here
        cout << "not a number" << endl;
    }
    else {
        cout << n << endl;
    }
}

Andy Buchanan, pour autant que coller à C ++ va, j'aimé le vôtre, mais j'ai quelques mods:

template <typename ElemT>
struct HexTo {
    ElemT value;
    operator ElemT() const {return value;}
    friend std::istream& operator>>(std::istream& in, HexTo& out) {
        in >> std::hex >> out.value;
        return in;
    }
};

Utilisé comme

uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");

De cette façon, vous n'avez pas besoin d'un impl par type int.

Exemple de travail sera avec strtoul:

#include <cstdlib>
#include <iostream>
using namespace std;

int main() { 
    string s = "fffefffe";
    char * p;
    long n = strtoul( s.c_str(), & p, 16 ); 
    if ( * p != 0 ) {  
        cout << "not a number" << endl;
    }    else {  
        cout << n << endl;
    }
}

strtol convertit à string long. Sur mon ordinateur donne numeric_limits<long>::max() 0x7fffffff. Il est évident que est supérieur à 0xfffefffe MAX_LONG. Alors retourne unsigned long au lieu de la valeur -65538 désirée. <=> convertit en <=> c'est pourquoi <=> pas de débordement dans ce cas.

Ok, <=> envisage chaîne d'entrée non comme nombre entier signé de 32 bits avant convertation. échantillon drôle avec <=>:

#include <cstdlib>
#include <iostream>
using namespace std;

int main() { 
    string s = "-0x10002";
    char * p;
    long n = strtol( s.c_str(), & p, 16 ); 
    if ( * p != 0 ) {  
        cout << "not a number" << endl;
    }    else {  
        cout << n << endl;
    }
}

Le code ci-dessus dans la console imprime <=>.

Voici une méthode simple et le travail que je trouve nulle part ailleurs:

string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);

S'il vous plaît noter que vous pouvez préférer utiliser entier unsigned long / entier long, pour recevoir la valeur. Une autre note, la fonction c_str () convertit seulement la std :: string à const char *.

Donc, si vous avez un const char * prêt, juste aller de l'avant avec l'utilisation de ce nom de variable directement, comme indiqué ci-dessous [Je montre aussi l'utilisation de la variable unsigned long pour un nombre hexadécimal plus grand. Ne pas confondre avec le cas d'avoir const char * au lieu de chaîne]:

const char *hexString = "7FFEA5"; //Just to show the conversion of a bigger hex number
unsigned long hexNumber; //In case your hex number is going to be sufficiently big.
sscanf(hexString, "%x", &hexNumber);

Cela fonctionne parfaitement bien (à condition que vous utilisez des types de données appropriés selon vos besoins).

J'ai eu le même problème aujourd'hui, voici comment je l'ai résolu pour que je puisse garder lexical_cast <>

typedef unsigned int    uint32;
typedef signed int      int32;

class uint32_from_hex   // For use with boost::lexical_cast
{
    uint32 value;
public:
    operator uint32() const { return value; }
    friend std::istream& operator>>( std::istream& in, uint32_from_hex& outValue )
    {
        in >> std::hex >> outValue.value;
    }
};

class int32_from_hex   // For use with boost::lexical_cast
{
    uint32 value;
public:
    operator int32() const { return static_cast<int32>( value ); }
    friend std::istream& operator>>( std::istream& in, int32_from_hex& outValue )
    {
        in >> std::hex >> outvalue.value;
    }
};

uint32 material0 = lexical_cast<uint32_from_hex>( "0x4ad" );
uint32 material1 = lexical_cast<uint32_from_hex>( "4ad" );
uint32 material2 = lexical_cast<uint32>( "1197" );

int32 materialX = lexical_cast<int32_from_hex>( "0xfffefffe" );
int32 materialY = lexical_cast<int32_from_hex>( "fffefffe" );
// etc...

(trouvé cette page quand je cherchais une façon moins sucky: -)

Cordialement, A.

Cela a fonctionné pour moi:

string string_test = "80123456";
unsigned long x;
signed long val;

std::stringstream ss;
ss << std::hex << string_test;
ss >> x;
// ss >> val;  // if I try this val = 0
val = (signed long)x;  // However, if I cast the unsigned result I get val = 0x80123456 

autre méthode

using namespace System;

template <typename NUM>
NUM hexstr2num(String^ h)
{
    NUM v=0;
    String^ k=L"0123456789ABCDEF";
    short l=h->Length;
    char off;
    h=h->ToUpper();

    if(h->Substring(0,1)!=L"H")
        {if(h->Substring(0,2)==L"0X") off=2;}
    else
        {off=1;}

    if(!off) throw;

    char dx=0;
    for(int i=l;i>off;i--)
        {
            if((dx=k->IndexOf(h->Substring(i-1,1)))>=0)
                {v+=dx<<((l-i)<<2);}
            else
                {throw;}
        }
    return v;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top