Convertir Chaine de caractères vers hexa - C++ - Programmation
Marsh Posté le 10-03-2006 à 09:18:55
Ca va dépendre de l'encodage des caractères.
Rien ne t'empeche de lire le fichier octet par octet.
Il n'y a pas de traduction ou de conversion à proprement parler, simplement une différence dans l'affichage des mêmes données.
L'hexa c'est pratique pour toi. L'ordi s'en fout il manipule des bits.
Au final, avec les printf tu peux faire du %X ou %x sur chaque caractère qui t affichera la valeur en hexa.
Marsh Posté le 10-03-2006 à 09:40:12
Taz => cela ne semble fonctionner que sur des entiers (unsigned est une valeur entière, a priori)
ce qui fait que mon flux étant un tableau de caractères, il y a incompatibilité des types de données (entier // char)
Y a-t-il un moyen de contourner cela?
Marsh Posté le 10-03-2006 à 10:10:18
plus simplement, existe t il une commande pour passer d'un caractere (genre A, ou è) vers sa valeur ASCII correspondante ?
Marsh Posté le 10-03-2006 à 11:21:34
Thordax a écrit : plus simplement, existe t il une commande pour passer d'un caractere (genre A, ou è) vers sa valeur ASCII correspondante ? |
pas besoin de commande pour faire ça : la valeur d'un char est justement le code du caractère dans l'encodage utilisé.
pour info, 'è' ne fait pas partie des 128 caractères de la table ascii. tu as besoin d'un encodage sur un octet complet (genre ISO-8859-1) pour ce type de caractères
PS: je ne vois pas le rapport avec la question initiale
Marsh Posté le 10-03-2006 à 11:31:19
ok je me suis mal exprimé, mea culpa
Je reprends donc du début.
J'ai au départ un fichier (exemple : toto.dat) dans lequel on a stocké des valeurs binaires.
Je dois analyser ces valeurs et par exemple reconnaître ce qu'on appelle des flags (même principe que des balises html).
Exemple :
-j'ouvre le fichier
-je récupère ces valeurs et les place dans un buffer
-ces valeurs sont des chaines de caractères, je ne peux donc pas directement rechercher "E1 4D"
-je convertis donc le contenu de mon buffer en des valeurs hexadécimales (et non ASCII si celui ci n'est que sur 128 valeurs, ce que je croyais etre 256)
-je balaye le buffer en recherchant la chaine E14D
-dès que je la trouve, je recopie la chaine suivant cette "balise"
-je recherche à nouveau une nouvelle balise
-etc ...
=> Mon problème principal est celui du passage en hexadécimal pour pouvoir ensuite rechercher le caractère qui nous intéresse dans le buffer.
Existe-t-il une fonction permettant de convertir simplement une chaîne de caractères en hexadécimal? dois je utiliser les fonctions associées a string ? le passage en integer ne semble pas fonctionner (i.e : int valeur_deci = int(chaine); ) car elle me renvoie une valeur décimale qui ne correspond pas a sa valeur correspondante
Merci pour vos réponses !
Marsh Posté le 10-03-2006 à 15:21:28
bon ben effectivement c'était de l'ascii dont j'avais besoin, j'ai trouvé la solution, voici le code pour ceux que ca intéresse :
Code :
|
Marsh Posté le 10-03-2006 à 15:32:38
Citation : je souhaite ouvrir un fichier, et traiter son contenu de manière hexadécimale |
dans quel but ?
Citation : code = donnees; // on passe en décimal |
non ! décimal n'a rien à voir avec ca (c'est une base de représentation de nombre)
Marsh Posté le 10-03-2006 à 15:55:07
je passe en décimal pour passer en hexa par la suite ...
et le ouvrir en hexa me permet d'effectuer un traitement de type : "recherche de la trame E1 4D" et non recherche du caractère ö ou un truc du style.
En fait, on connait la valeur des trames que l'on recherche dans le fichier, uniquement dans le standard hexadécimal, il faut donc le convertir a l'avance.
Maintenant j'ai un autre petit problème, comment fait on pour effectuer un balayage dans le fichier afin de trouver une chaine de caractère ? je suis en train de voir ca avec fgetc, mais y a t il une fonction plus pratique en c++ ?
Marsh Posté le 10-03-2006 à 16:21:43
Thordax a écrit : je passe en décimal pour passer en hexa par la suite ... |
Ce que skelter voulait dire, c'est que le cast de données du type char vers le type int n'a rien à voir avec un changement de base.
Essayons d'expliquer ça plus clairement :
Code :
|
ici, tu n'as pas changé de valeur (65 dans les deux cas); tout ce que tu as changé, c'est le sens qu'on donne à cette valeur
Après, c'est au moment d'injecter la valeur dans un flux de caractères (ici oss) que tu précises (grâce à std::hex) quelle base de représentation tu veux utiliser
Marsh Posté le 10-03-2006 à 16:25:26
ok d'ac
reste maintenant a savoir comment rechercher une chaine de caractère dans un flux et j'aurai pas mal avancé
Marsh Posté le 10-03-2006 à 16:29:25
un char est un type entier
#
while(!fichier_analyse.eof())
#
{
#
/
c'est tout pourri ça. ça marche pas. ça marche en pascal et nulle part ailleurs. merde enfin.
Marsh Posté le 10-03-2006 à 16:30:28
Thordax a écrit : ouvrir en hexa me permet d'effectuer un traitement de type : "recherche de la trame E1 4D" et non recherche du caractère ö ou un truc du style. |
Il serait plus simple et plus efficace de convertir ta trame hexa en succession de char (affichables ou non ; on s'en fout) plutôt que de convertir tout ton fichier.
Marsh Posté le 10-03-2006 à 16:34:13
+1
Citation : et le ouvrir en hexa me permet d'effectuer un traitement de type : "recherche de la trame E1 4D" et non recherche du caractère ö ou un truc du style. |
c'est plus simple et infiniment plus efficace de convertir en entier la chaine contenant la représentaion hexadécimal à rechercher
Marsh Posté le 10-03-2006 à 16:50:51
désolé le cahier des charges est ce qu'il est, je n'ai pas trop de marge de manoeuvre ...
Taz a écrit : un char est un type entier |
ca marche chez moi nickel, donc peut etre que dev c++ fonctionne en pascal, va savoir ...
Marsh Posté le 10-03-2006 à 17:10:42
mon oeil que ça marche ... t'aurais pas 2x le dernier char ?
et puis c'est overkill ton truc.
while (input.get(c)) { roulez ... }
# code = donnees; // on passe en décimal
tu passes nulle par là, tu mets juste un int dans un autre.
Marsh Posté le 10-03-2006 à 17:23:12
ben ca marche écoute, tente le tu verras, enfin bon j'imagine que t'as pas le temps ... mais comment te prouver que ca marche ?
Marsh Posté le 10-03-2006 à 17:35:48
Citation : ben ca marche écoute, tente le tu verras, enfin bon j'imagine que t'as pas le temps ... mais comment te prouver que ca marche ? |
peut-être que ça marche, mais ça devrait pas. Comme le dit Taz, le dernier caractère du fichier est probablement traité deux fois...
Marsh Posté le 10-03-2006 à 17:45:44
c'est même certain. mais mon autre question, c'est que 'cin >> c' tu ne lis pas tous les caractères de ton fichier, contrairement à cin.get(c);
Marsh Posté le 10-03-2006 à 17:54:47
je me souviens pas avoir utilisé de commande cin>>c
ceci dit tout ca ne regle pas mon probleme de recherche de fichier
je suis en pleine compréhension de find_first_of et de mise en boucle while ... have some tricks?
Marsh Posté le 10-03-2006 à 17:55:51
#
char donnees;
// on lit mot par mot
#
fichier_analyse>> donnees;
...
Marsh Posté le 10-03-2006 à 18:47:03
Heu... franchement, Thordax ne s y prends pas de la bonne manière.
Tout d abord, il existe un algoritme de recherche d une sous-chaîne dans une chaîne, il s appelle algo de <<BOYER et MOORE>>. C est plus efficace connu à ce jour. Tu trouvera surement de nombreuses implémentations sur le net.
Il est implémenté en C avec la fonction strstr(), mais ne fonctionne pas sur des fichiers binaires, aussi il faudrait réimplémenter l agorithme sur un fichier. Il permettrait de plus d économiser la mémoire en ne chargeant qu une partie du fichier d une longueure maximale égale à la longueur de la sous-chaîne recherchée.
Deuxièmement, au lieu de transformer le fichier binaire en chaîne hexadécimale, tu peut très bien faire le contraire: transformer la séquence recherchée en chaîne binaire. L avantage etant que du coup le temps de traitement est certainement plus rapide: 1°) la sous-chaîne recherchée est a priori plus courte que le fichier, 2°) le fichier transformé en chaîne hexadécimale prends 2 fois plus de place donc deux fois plus de temps à traiter.
Bref, je te souhaiterais bien: bon courage!
Marsh Posté le 13-03-2006 à 15:01:06
nargy => tout à fait d'accord avec toi, je vais simplement convertir la chaine recherchée en binaire.
Dans ce cas, comment faire une recherche de la chaine : "1110 0001 0100 1101" (E14D), ceci afin de récupérer la position pour analyser la trame ?
la commande find fonctionne-t-elle dans ce cas ? car dans le cas ou je fais une conversion hexa je n'ai qu'a placer les commandes :
Code :
|
(d'ailleurs j'ai un problème de vecteur vide au niveau du vecteur Positions, et je crois que la recherche s'effectue mal, seulement, je ne vois pas où est le problème dans mon code, si quelqu'un pouvait m'aider)
Marsh Posté le 13-03-2006 à 15:09:14
je t ai donné le nom de l algo le plus rapide pour ça, maintenant si tu veut un algo plus simple, tu peut utiliser la fonction standard <<memchr>> qui recherche 1 octet dans un buffer en mémoire.
Pour éviter de charger le fichier tout d un coup tu peut extraire le premier octet de la chaîne recherchée:
void* chaîne_recherchee=...;
char premier_octet=*((char*)chaîne_recherchee);
et le comparer à chaque caractère du fichier:
char c;
while(...)
if( (c=fgetc(file)) == premier_octet )
break;
...
if(pas_fin_de_fichier(file))
lire length(chaine_chercher-1) octets du fichier
comparer octets lus avec (chaine_recherchee+1) à l aide de <<memcmp(...)>>
si c est bon on a trouver une occurence
sinon reprendre la lecture du ficher
sinon plus d occurences trouvées
Marsh Posté le 13-03-2006 à 15:12:51
nargy a écrit : je t ai donné le nom de l algo le plus rapide pour ça, maintenant si tu veut un algo plus simple, tu peut utiliser la fonction standard <<memchr>> qui recherche 1 octet dans un buffer en mémoire. |
EDIT : autant pour moi j'avais mal lu ton code, oui ca peut tout à fait fonctionner de cette manière, je vais tester ca
Marsh Posté le 13-03-2006 à 15:20:53
heu, il te faut une fonction pour transformer la chaine hexa en chaîne binaire.
tu peut l ecrire toi même assez facilement avec quelques ifs, en gros:
vérifier que chaine_hexa a une longueur paire
chaine_bin=malloc(length(chaine_hexa)>>1)
pour chaque caractère de chaine_hexa
chaine_bin[] <- hex2bin(chaine_hexa[])
avec genre:
hex2bin(char c)
if(c>='0' && c<='9') return c-'0';
if(c>='A' && c<='F') return c-'A';
if(c>='a' && c<='f') return c-'a';
sinon erreure chaine hexa
Marsh Posté le 13-03-2006 à 15:28:39
mais je peux faire une recherche binaire simple en recherchant le premier octet, puis, lorsque je tombe sur le bon premier octet, en regardant si les octets suivants concordent (comparaison de chaine dans un deuxieme temps) n'est ce pas ?
Cela me permettrait d'éviter la conversion en hexa ?
de plus, quand tu fais une lecture des octets de la chaine, faut il utiliser une commande de type fread ou plutôt fgetc ?
Marsh Posté le 13-03-2006 à 16:02:02
> Cela me permettrait d'éviter la conversion en hexa ?
J ai pas tout suivi, si au départ tu n a que des chaines binaires t a aucune conversion à faire.
Si la chaîne de recherche est en hexa, tu la converti en binaire, pour comparer des chaînes binaires.
L algo que je t ai donné fait exactement ce que tu décris.
> fread / fgetc
Bof, c est du pareil au même. La différence étant que fread lit des octets et fgetc lit des caractères. Tu peut utiliser un type BYTE si t en a un à ta disposition, sinon pour tous les compilateurs sizeof(char)=1.
Marsh Posté le 13-03-2006 à 16:05:36
Note: c est la fonction <<memcmp()>> pour comparer des chaînes binaires. strcmp() compare des chaines de caractères terminées par un `\0`.
Marsh Posté le 13-03-2006 à 16:09:52
du coup on obtient un truc du style :
Code :
|
voici ou j'en suis, bizarrement, l'executable ne trouve aucune chaine correspondant a la chaine recherchée ... j'ai gaffé ou ?
EDIT : l'erreur semble venir du fgets, le nombre 1 est certainement faux, mais que dois je mettre ? 2 pour deux autres caractères ? (E14D compte 2 octets en tout, alors je suis un peu paumé la ..)
Marsh Posté le 13-03-2006 à 16:16:45
#
while(!feof(file))
#
{
#
if( (c=fgetc(file)) == premier_octet )
boom
while((c = fgetc(input)) != EOF) { travailleur sereinement }
#
fgets (chaine_trouvee , 1 , file);
#
#
n=memcmp ( chaine_recherchee, chaine_trouvee, len1>len2?len1:len2 );
t'as un problème. tantot tu consideres que ton entrée c'est du texte (ici des lignes) tantot que c'est du binaire ...
et len1 et len2 ne sont pas initialisées.
et puis à part le cout, c'est du C ta daube.
Marsh Posté le 13-03-2006 à 16:20:39
len1 et len2 ont été initialisés en début de code
je ne vois pas quelles entrées ne sont pas binaires, need eclaircissement la ...
et puis quant au C ce n'est rien après tout, je voulais utiliser les flux oss mais monsieur le patron ne veut pas, je crois ...
EDIT :
c=fgetc(file) me sort une valeur ASCII dans la boucle, et il ne trouvera jamais le caractère E correspondant au caractère recherché en début de boucle. Il y a donc un problème d'homogénéité des variables. Faut il changer E en décimal ?
Marsh Posté le 13-03-2006 à 16:32:33
nargy a écrit : |
sizeof retourne une taille en char, pas en octet, en C byte != octet
Marsh Posté le 13-03-2006 à 16:49:43
Citation : len1 et len2 ont été initialisés en début de code |
où ça ? je ne vois ni leur initialisation, ni leur modification au fur et à mesure que tu lis dans ton fichier
Citation : je ne vois pas quelles entrées ne sont pas binaires, need eclaircissement la ... |
en lisant le bout de code que tu donnes, j'ai l'impression que tu considères que tout est du texte (i.e. que tu as converti l'intégralité du fichier en caractères représentant les valeurs de tes octets en hexa)
Citation : c=fgetc(file) me sort une valeur ASCII dans la boucle, et il ne trouvera jamais le caractère E correspondant au caractère recherché en début de boucle. Il y a donc un problème d'homogénéité des variables. Faut il changer E en décimal ? |
Comme on a déjà essayé de te l'expliquer, un caractère EST un int. C'est équivalent. char c='E' est simplement un manière plus lisible (et portable) d'écrire char c=69
Marsh Posté le 13-03-2006 à 17:07:03
ok franceso, pigé
et mon erreur est trop simple : je faisais un break a la suite de la reconnaissance du premier caractere au lieu de tester la suite ...
Marsh Posté le 13-03-2006 à 17:16:53
Tu ne respecte pas l algo que je t ai donné.
Une fois que tu testes si le premier octet est correct, lis avec fread une quantité d octets prévue à l avance (de la longeure de la chaîne recherchée moins 1 octet) dans une zone mémoire temporaire créee à l avance avec malloc, puis tu compare avec memcmp() la zone temporaire avec les octets lus.
Si les 2 conditions sont remplies (premiers octets égaux + reste des octets égaux) tu a trouvé une occurence.
Marsh Posté le 13-03-2006 à 17:37:46
bon j'arrive a un truc pas mal mais c'est pas encore ce que je veux :
Code :
|
en effet, dans mon fichier de test, il n'y a pas les caractères E14D, mais bel et bien : áM soit leur correspondance ASCII. Comment faire le lien ? faire une recherche du premier caractère á puis faire un strcomp jusqu'à tomber sur M ?
Marsh Posté le 10-03-2006 à 09:05:34
Bonjour, mon problèlme est le suivant :
je souhaite ouvrir un fichier, et traiter son contenu de manière hexadécimale (genre : rechercher la chaine FF AD par balayage du fichier. Il faut donc ouvrir, stocker le contenu du fichier dans un buffer, et convertir celui-ci en hexadécimal. Existe-t-il une fonction simple qui "transcrive" ou qui "traduise" une chaine de caractere en hexa ?
ex :
Je m'appelle Thordax => 4D 1C 22 .... etc
merci pour vos réponses !