142 votes

C++ convertit une chaîne hexadécimale en entier signé

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

Ainsi, par exemple, j’ai la chaîne hexadécimale de « fffefffe ». La représentation binaire de c’est 11111111111111101111111111111110. La représentation de l’entier signé de c’est :-65538.

Comment faire cette conversion en C++ ? Il faut également travailler pour les nombres non négatifs. Par exemple, la chaîne hexadécimale 0000000 « a », qui est 00000000000000000000000000001010 en binaire et 10 en décimal.

247voto

Evan Teran Points 42370

utiliser std::stringstream

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

l'exemple suivant génère -65538 le résultat est:

#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;
}

EDIT: C++11 mise à jour. Dans la nouvelle norme, il y a un peu de nouveau les fonctions de l'utilitaire qui vous pouvez faire usage de! plus précisément, il existe une famille de "chaîne à nombre de" fonctions (http://en.cppreference.com/w/cpp/string/basic_string/stol et http://en.cppreference.com/w/cpp/string/basic_string/stoul). Ce sont essentiellement des wrappers minces autour de C de la chaîne de conversion des numéros de fonctions, mais de savoir comment traiter avec un std::string

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

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

REMARQUE: ci-Dessous est ma réponse originale à cette question, qui, comme l'éditer dit n'est pas une réponse complète. Pour une solution fonctionnelle. Coller le code ci-dessus de la ligne :-).


EDIT: Il semble que depuis lexical_cast<> est défini pour avoir de conversion de flux sémantique. Malheureusement, les ruisseaux ne comprends pas le "0x" notation. Donc, à la fois l' boost::lexical_cast et mon roulé à la main de l'un de ne pas traiter ainsi avec hex cordes. La solution ci-dessus qui définit manuellement le flux d'entrée à l'hex qu'il va la traiter correctement.

Boost a quelques trucs à faire aussi bien, qui a une belle erreur de vérification des capacités. 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 à l'aide de coup de pouce, voici une version légère de l'lexicale cast qui n'a pas de contrôle 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"); 

27voto

Mike Lundy Points 161

Andy Buchanan, dans la mesure du collant à C++ va, j’ai aimé vôtre, mais j’ai un peu de mods :

Utilisé comme

De cette façon vous n’avez pas besoin une impl par type int.

15voto

Kirill V. Lyadvinsky Points 47627

Exemple de travail avec strtoul sera:

#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 de long. Sur mon ordinateur numeric_limits<long>::max() donne 0x7fffffff. Évidemment qu' 0xfffefffe est plus grand que 0x7fffffff. Donc, strtol retours MAX_LONG , au lieu de la valeur requise. strtoul convertit string de unsigned long c'est pourquoi aucun débordement dans ce cas.

Ok, strtol envisage de la chaîne d'entrée pas comme entier signé 32 bits avant de convertation. Drôle de l'échantillon avec strtol:

#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 imprime -65538 dans la console.

9voto

AamodG Points 51

Voici une simple méthode de travail et j'ai trouvé d'ailleurs:

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

Veuillez noter que vous pourriez préférer utiliser unsigned long integer long integer, pour recevoir la valeur. Autre remarque, le c_str() fonction convertit les std::string const char* .

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

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 vous utilisez des types de données approprié selon votre besoin).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X