Convertir une chaine en hex ?

Convertir une chaine en hex ? - C++ - Programmation

Marsh Posté le 03-08-2005 à 09:35:56    

Bonjour, je cherche un moyen pratique et rapide de convertir une chaine char* en chaine hex.
 
J'ai un buffer char* qui contient des octets qui proviennent d'un fichier avec read()
 
Est-ce qu'il y a moyen de convertir toute la chaine sans faire une boucle pour convertir toute la chaine octet par octet ?
 
Je cherches une méthode rapide pour la convertir d'un coup sans faire du boucle.
 
Merci. :)

Reply

Marsh Posté le 03-08-2005 à 09:35:56   

Reply

Marsh Posté le 03-08-2005 à 09:40:14    

Code :
  1. const char * chaine_c = "1337F00D";
  2. std::istringstream iss(chaine_c);
  3. unsigned int nb = 0;
  4. if(iss >> std::hex >> nb) {
  5.  std::cout << nb << std::endl;
  6. } else {
  7.  std::cout << ":heink: ?" << std::endl;
  8. }

Reply

Marsh Posté le 03-08-2005 à 09:53:35    

Merci :) mais je ne comprends pas très bien ce que fait le code, peux-tu commenter stp ? :)
 
Mais cela ne semble pas bien fonctionner, j'ai essayer avec la chaîne "A" et ça me retourne 10 au lieu de 41  [:chacal_one333]

Reply

Marsh Posté le 03-08-2005 à 10:01:41    

en hexa, A, ca vaut 10 ... après, que le caractère 'A' soit le 41ème sur ta table de caractères, c'est un autre problème.
 
Si tu veux juste les numéros des caractères, il n'y a pas de conversion à effectuer : tu peux faire des manipulations sur les char comme sur toutes les autres valeurs entières.

Reply

Marsh Posté le 03-08-2005 à 11:24:01    

Code :
  1. std::cout << std::hex << static_cast<int>( 'A' );


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 03-08-2005 à 11:25:34    

HelloWorld a écrit :

Code :
  1. std::cout << std::hex << static_cast<int>( 'A' );



ah, ouais ... J'avais vraiment pas compris ca :D
 
Edit : pour finir de répondre à sa question, dans ce cas, oui, il faut faire une boucle pour parcourir la chaine. Quelque chose du genre :

Code :
  1. std::ostringstream oss;
  2. const size_t SIZE = 512;
  3. char buffer[SIZE];
  4. for(size_t i=0; i<SIZE; ++i)
  5.   oss << std::hex << static_cast<int>(buffer[i]);


Message édité par theshockwave le 03-08-2005 à 11:35:09
Reply

Marsh Posté le 03-08-2005 à 16:56:56    

euh, je suis confus la  :pt1cable:  
 
Comment ça A == 10 en hex ?
 
A == 65 décimal non ? et 65 == 41 en hex non  :??:

Reply

Marsh Posté le 03-08-2005 à 17:03:34    

Il voulait dire 0xA = 10. Le A en question, c'est le A de la base hexa, le digit après 9.
Toi, tu parles du carcatères ASCII 'A'. Ce carcatère ASCII, il a pour valeur décimale 65, soit 0x41. Donc, il te faut obtenir la valeur d'un caractère ASCII donné (d'où le static_cast en int) puis la représenter en hexa (std::hex).


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 03-08-2005 à 17:08:37    

HelloWorld a écrit :

Donc, il te faut obtenir la valeur d'un caractère ASCII donné (d'où le static_cast en int)


je trouve ca un peu litigieux, comme explication [:dawa]

Reply

Marsh Posté le 03-08-2005 à 17:09:10    

Ok, mais il n'y a pas d'autres façon que de faire cela que dans une boucle ?
 
Mais pour faire cela dans une boucle je suis confus aussi. Étant donné que chaque caractère de ma chaine va prendre 2 octets au lieu d'un seul, ce qui veut dire que ma chaine de destination doit etre 2 fois plus grande, mais comment est-ce que je précise à chaque itération que je veux placer le résultat 2 octets plus loin que le dernier ? Vu que je places 2 octets à la fois ..


Message édité par NullDragon le 03-08-2005 à 17:09:39
Reply

Marsh Posté le 03-08-2005 à 17:09:10   

Reply

Marsh Posté le 03-08-2005 à 17:12:01    

il faut que tu t'habitues à l'utilisation de la STL, dans mon exemple, le genre de problème que tu soulèves est géré. Il  ne manque qu'un seul détail : pour récupérer la chaine construite par l'intermédiaire du std::ostringstream, il faut faire oss.str(); (je dis ca de mémoire, donc à vérifier)

Reply

Marsh Posté le 03-08-2005 à 17:16:07    

Ok, mais le problème c'est que si j'ai une grosse chaîne de 1mb à convertir la boucle est longue :/
 
Et j'ai besoin de cette chaîne pour initialiser un nombre dans la lib gmp, car cette lib accepte seulement une base de 2 à 36.

Reply

Marsh Posté le 03-08-2005 à 17:20:53    

la boucle est longue ? Tu as ressorti un vieux 286 pour programmer ou quoi ? :o
 
sinon, pour cette histoire d'initialisation, j'ai rien compris :p

Reply

Marsh Posté le 03-08-2005 à 17:28:27    

Non j'ai un amd 64  ;)  
 
La boucle est longue oui, car c'est une boucle pour 1mb donc de 1048576 fois.
 
À moins que j'ai mal fait ma boucle, j'aurais besoin d'un exemple pour voir, car je n'arrives pas à convertir comme il faut je crois, puisque je dois sauter 2 octets dans ma boucle de destination.
 
voici ce que j'ai fait: j'ai prit un exemple simple pour ma châine.
 

Code :
  1. unsigned char*buffer = new unsigned char[4];
  2. unsigned char*bufferhex = new unsigned char[8];
  3. unsigned long x;
  4. ostringstream
  5. buffer = "ABCD";
  6. std::ostringstream oss;
  7. for (x=0;x<5;x++)
  8. {
  9.   oss << std::hex << static_cast<int>(buffer[x]);
  10.   //comment je le remet dans bufferhex a partir de la ?
  11. }

 
 

Reply

Marsh Posté le 03-08-2005 à 17:33:25    

si tu manipules des chaines, utilise std::string :o (parce que là, en fait, tu ne le vois pas, mais tu fais déjà des fuites mémoire dans tous les sens ...)
 
regarde ce que ca donnerait :
 

Code :
  1. std::string buffer = "ABCD";
  2. std::ostringstream oss;
  3. for (std::string::const_iterator i = buffer.begin(); i != buffer.end(); ++i)
  4. {
  5.   oss << std::hex << static_cast<int>(*i);
  6. }
  7. buffer = oss.str(); //buffer contient maintenant la version "hexadécimale" de ta chaine


 
Edit : petite correction au code (double déclaration de oss)


Message édité par theshockwave le 03-08-2005 à 17:34:00
Reply

Marsh Posté le 03-08-2005 à 17:33:52    

Et pour la lib gmp, c'est une lib qui gère les gros int. Mais pour initialiser un nombre avec son type, dans ce cas-ci le type mpz_t, il y a une fonction pour cela, la fonction mpz_init_str() qui accepte 3 parametre: valeur, char* et base
 
valeur est le nombre de la variable de type mpz_t dans lequel va se trouver le nombre, char* est le nom du buffer dans lequel on prend le nombre qui est très gros, et base est le int de la base de notre chaine, soit de 2 à 36. Dommage qu'il y ait pas la base 256, j'aurais pu lui passer ma chaine d'octet directement.

Reply

Marsh Posté le 03-08-2005 à 17:38:06    

theshockwave a écrit :

si tu manipules des chaines, utilise std::string :o (parce que là, en fait, tu ne le vois pas, mais tu fais déjà des fuites mémoire dans tous les sens ...)
 
regarde ce que ca donnerait :
 

Code :
  1. std::string buffer = "ABCD";
  2. std::ostringstream oss;
  3. for (std::string::const_iterator i = buffer.begin(); i != buffer.end(); ++i)
  4. {
  5.   oss << std::hex << static_cast<int>(*i);
  6. }
  7. buffer = oss.str(); //buffer contient maintenant la version "hexadécimale" de ta chaine


 
Edit : petite correction au code (double déclaration de oss)


 
Ok je vais essayer cela :)
 
Mais que veux-tu dire par le fait que j'avais des fuites mémoire ? j'aime comprendre, alors si tu pourrais expliquer en quoi mon programme fait des fuites :)
 
Ah oui et je suis confus aussi parce que mon buffer jusqu'ici se remplissait avec read() comme ceci:  
 
myFile.read ((char*)bbytes, n);
 
Je vois mal comment l'adapter au code que tu as eu la gentillesse de me montrer  :jap:


Message édité par NullDragon le 03-08-2005 à 17:40:41
Reply

Marsh Posté le 03-08-2005 à 17:45:37    

Soit tu fais du C++, soit tu fais du C, mais là, tu as plutôt l'air parti sur du C, on dirait ...
 
les fichiers s'utilisent par le système de flux, en C++ (std::fstream) et non pas par les FILE * issus du C ... Donc soit tu postes dans la catégorie C, soit tu écris ton code en C++. :)
 
 
Pour ta fuite mémoire, c'est simple :

NullDragon a écrit :

Code :
  1. unsigned char*buffer = new unsigned char[4];
  2. buffer = "ABCD";



quand tu fais ca, tu fais pointer buffer sur une chaine constante, tu ne recopies en aucun cas la valeur de la chaine ("ABCD" ) dans ton buffer alloué juste au-dessus

Reply

Marsh Posté le 03-08-2005 à 17:48:50    

Je le fais en C++ mais j'ai encore de la misère à faire la différence entre des fonctions qui viennent de C ou de C++ :)
 
Mais read() ça vient de ifstream, c'est du C ?
 
Je croyais que c'était du C++
 
Parce que mon fichier je ne l'ouvre pas avec *FILE mais comme ceci:
 
ifstream myFile ("D:\\test.bin", ios::in | ios::binary);


Message édité par NullDragon le 03-08-2005 à 17:50:07
Reply

Marsh Posté le 03-08-2005 à 17:51:01    

dans ce cas, si myFile est du type istream, tu es bien en C++, mais read est dépréciée ... Tu as quoi, dans ton fichier ? une valeur binaire que tu veux obtenir sous forme de chaine hexadécimale ?

Reply

Marsh Posté le 03-08-2005 à 17:53:24    

C'est un fichier quelconque, je fais un programme d'encryption, alors les octets lu peuvent être de 0 à 255.
 
donc ma ligne myFile.read() est correct pour lire dans mon fichier ?
 
Mais comment je remplace std::string buffer de ton code par mon buffer ?  :pt1cable:
 
EDIT: oui je veux transformer chaque octet en hex, mais si read est déprécié que puis-je utiliser d'autre pour aller lire un nombre d'octets n dans mon fichier ?


Message édité par NullDragon le 03-08-2005 à 17:55:42
Reply

Marsh Posté le 03-08-2005 à 18:28:10    

Voilà, j'ai essayé avec ton code, mais on dirait qu'il fait une boucle infini, peux-tu vérifier ce qui ne va pas stp ? :)
 
http://www.rafb.net/paste/results/fHKFdC10.html

Reply

Marsh Posté le 03-08-2005 à 18:31:35    

Citation :

myFile.read ((char*)buffer.c_str(), n);


 
Je ne veux pas voir ca !
 
Edit : passe par des .get() ou .getline()
le close sur le fichier ne sert à rien (fait par le destructeur la ligne d'après)


Message édité par theshockwave le 03-08-2005 à 18:34:44
Reply

Marsh Posté le 03-08-2005 à 18:34:03    

Ok, je vais l'enlever, mais je ne connais pas d'autres façon ..

Reply

Marsh Posté le 03-08-2005 à 18:36:10    

mmmh, j'aimerais bien que quelqu'un qui est plus habitué à la manipulation de fichiers en C++ vienne :whistle: parce que j'évite ce genre de sujet allègrement (et je n'ai pas trop le temps de rechercher la solution en ce moment)

Reply

Marsh Posté le 03-08-2005 à 18:38:40    

Ok, j'ai essayé:
 
myFile.getline((char*)buffer.c_str(), n);
 
mais ça me renvoit une erreur: memory cannot be read.

Reply

Marsh Posté le 03-08-2005 à 18:43:47    

Arrête tout de suite de tenter d'écrire dans un std::string::c_str() ... Ca va forcément t'exploser dans les dents !
 
Edit : j'ai bien peur que tu sois à nouveau forcé de passer par un système de buffers, comme je t'ai dit, je n'ai pas le temps de vérifier, mais tu dois bien pouvoir trouver de la lecture à ce sujet (Thinking in C++ ou je ne sais quel autre ouvrage disponible sur le net)


Message édité par theshockwave le 03-08-2005 à 18:44:54
Reply

Marsh Posté le 03-08-2005 à 18:47:38    

ok merci :)

Reply

Marsh Posté le 04-08-2005 à 10:35:45    

c'est bien getline qu'il faut utiliser, mais un autre.
http://c.developpez.com/faq/cpp/?p [...] _par_ligne


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 04-08-2005 à 10:46:14    

par contre, pour un fichier binaire, c'est un peu ridicule d'avoir un délimiteur (que ce soit \n par défaut ou un autre à spécifier) :/

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed