J'ai une chaîne de caractère qui ressemble à celle-ci :
Il y a donc bien plusieurs espaces au début, des caractères regroupés hexa (bien qu'ils ne sont pas considérés en tant que tel) deux par deux, et leur interprétation ensuite : .../.... ......
Et il faudrait que je puisse obtenir ceci :
Comme vous l'avez remarqué, c'est le contenu d'un paquet SMPP (son PDU donc).
Je voudrais donc récupérer les caractères qui sont par deux par deux (chiffres et lettres majuscules) précédés d'un espace, dans un premier temps. J'ai donc pensé à la regex suivante :
" \\[[:alnum:][:alnum:]]{1}"
Le problème étant que, je ne suis pas même sûr de celle-ci et j'ai vraiment des doutes sur comment m'en servir...
Salut, tiens c'est bizarre, peut-être parce que je suis l'auteur du topic mais je les vois bien. Il y a deux images. Je viens de vérifier avec un autre compte sur openclassroom, c'est bon aussi
Quel moteur de Regex est-ce que tu utilises ? Je n'ai jamais vu de chose comme [:alnum:] :/
Je te propose celle-ci sinon : /([\d|A-F]{2} )/g pour avoir chaque couple de nombre. Tu peux la tester ici. Après il faut encore trouver un moyen d'appliquer cette expression dans le langage que tu veux et en obtenir le résultat pour le stocker dans ton tableau.
Edit : Explications rapide de la regex.
/..../g délimite la regex et spécifie qu'elle s'appliquera à l'ensemble du texte qui lui sera soumis.
/(.....)/g spécifie que tout se qui correspondra à la regex dans les parenthèses sera "selctionner", on aura un résultat différé pour chaque occurence/sélection.
/([...|...])/g demande de trouver ou bien l'élément de droite, ou bien celui de gauche
/([...|...]{2})/g demande de trouver 2 fois ce patterne (puisqu'on a 2 nombre qui se suivent)
/([\d|...]{2})/g "\d" correspond à "n'importe quel chiffre"
/([\d|A-F]{2})/g cherche les lettre de A à F (majuscule seulement)
Tu n'as jamais vu un truc pareil, pour une raison très très simple, le tuto que j'ai suivi pour écrire cela date de .... 2005, je viens tout juste de m'en rendre compte, j'aurais du checker avant. Je ne savais même pas qu'il existait des moteurs de regex, je le saurais à l'avenir !
D'ailleurs, tu parles de l'appliquer à ma chaîne, justement, je voudrais le faire en C. Mais il semble que les tuto pour le faire en C ne sont pas légions. Tu aurais une explication à ce "phénomène" ?
Les expressions regulières ne sont pas gérées par le C ANSI. Mais il existe la bibliothèque PCRE qui utilise la meme syntaxe que ce que t'as donné @Indolore.
Bonjour, je reviens ici pour poster un début de solution et donner suite au thread.
Après avoir regardé la bibliothèque PCRE et les regex classiques et après beaucoup beaucoup de manipulations, je suis arrivé à ce code (en regex classique) :
//pdu_connection est une chaîne vide qui va récupérer le résultat
//pdu contient une chaine comme ça :
/* 00 00 00 2F 00 00 00 09 00 00 00 00 00 00 00 01 .../.... ........
73 6D 70 70 63 6C 69 65 6E 74 31 00 70 61 73 73 smppclie nt1.pass
77 6F 72 64 00 27 56 4D 41 27 00 34 00 00 00 word.'VM A'.4...*/
void pdu_to_hex(char *pdu_connection, char *pdu){
int err;
regex_t preg;
const char *str_request = pdu;
const char *str_regex = "([0-9|A-F]{2} )";
char *result = malloc(100 * sizeof(char));
memset(result, '\0', sizeof(result));
int j=0;
while(strcmp(&str_request[j], "\0")){
char current[4];
memset(¤t, '\0', sizeof(current));
current[0] = str_request[j];
current[1] = str_request[j+1];
current[2] = str_request[j+2];
printf("La chaine courante est :%s;\n",current);
printf("j = %d\n",j);
j++;
err = regcomp (&preg, str_regex, REG_EXTENDED);
if (err == 0)
{
int match;
size_t nmatch = 0;
regmatch_t *pmatch = NULL;
nmatch = preg.re_nsub;
pmatch = malloc (sizeof (*pmatch) * nmatch);
if (pmatch)
{
match = regexec (&preg, current, nmatch, pmatch, 0);
regfree (&preg);
if (match == 0)
{
char *hex = NULL;
int start = pmatch[0].rm_so;
int end = pmatch[0].rm_eo;
size_t size = end - start;
hex = malloc (sizeof (*hex) * (size + 1));
if (hex)
{
strncpy (hex, ¤t[start], size);
hex[size] = '\0';
printf ("%s matched\n", hex);
strcat(pdu_connection, "\\x");
strncat(pdu_connection, hex, 2);
printf("Le resultat concatene est :%s\n\n",pdu_connection);
free (hex);
}
}
else if (match == REG_NOMATCH)
{
printf ("%s ne correspond a deux caracteres hex + un espace\n\n", current);
}
else
{
char *text;
size_t size;
size = regerror (err, &preg, NULL, 0);
text = malloc (sizeof (*text) * size);
if (text)
{
regerror (err, &preg, text, size);
fprintf (stderr, "%s\n", text);
free (text);
}
else
{
fprintf (stderr, "Memoire insuffisante\n");
exit (EXIT_FAILURE);
}
}
}
else
{
fprintf (stderr, "Memoire insuffisante\n");
exit (EXIT_FAILURE);
}
}
}
}
J'arrive donc bien à récupérer ma chaîne (c'est juste l'affichage dans un terminal) :
Le seul souci c'est quand je l'envoie, voilà ce que ma trame contient réellement :
En gros j'ai l'impression que la chaine que j'envoie est interprété comme de l'ascii et non comme de l'héxa. Alors que quand j'envoie cette chaîne précisément déclaré comme tel en C :
Je n'ai pas bien saisi quel est le nouveau problème. Tu nous montres ce que la trame contient au moment de l'envoi, mais qu'est-ce qui est faux dedans ? à quoi tu t'attends par rapport à ce qu'elle contient ?
Les \x sont également formatés comme caractères et ne servent donc pas indiquer que les deux caractères qui suivent sont en hexa.
Au lieu de les interpréter comme '\x', ils sont interprétés comme "\x".
Le contenu de la trame n'est pas faux et c'est donc bien tous les caractères que je veux, ils ne sont juste pas au bon format. Et je suis quasiment sûr que ça vient d'ici :
strcat(pdu_connection, "\\x");
Mais je vois vraiment pas comment je pourrais faire autrement pour lui indiquer héxa et non char.
Le souci est que, quand cette chaine passe dans une socket TCP, elle est pour le réseau composée des caractères suivants :
\ puis x puis 0 puis 0 etc... C'est de l'ASCII pour le réseau, comme le montre la première capture Wireshark plus haut.
La pile réseau prend chacun des caractères et le programme qui le reçoit en bout de chaîne reçoit donc l'équivalent hexadécimale de chacun des caractères : \ x 0 0
Merci Insonore pour que ce que tu as fait. Evidemment à thetui aussi mais il semblerait que tu puisses aller plus loin
J'y ai pensé, et j'ai essayé, mais du coup, ça me rajouterait une étape inutile non ?
Si je te suis, ça voudrait dire que je peux prendre chaque couple de caractères, et chercher leur représentation asci ? Parce qu'il faut que je parte d'un caractère hexa pour avoir son ascii correspondant.
je vais peut etre dire un co***rie, mais tu n'as pas vraiment besoin de rajouter le \x
> \ puis x puis 0 puis 0 etc... C'est de l'ASCII pour le réseau, comme le montre la première capture Wireshark plus haut.
car en fait ce que tu vois sur le Wireshark c'est à gauche la trame lue en hexa et à droite son interprétation (au mieux), donc toi tout ce que tu à besoin, c'est d'envoyer la donnée brute du buffer genre :
Il faudrait passer le tableau en unsigned char pour gerer les caracteres non représentables, et l'appel à strtol() il faut rajouter NULL ce qui donne strtol(hex, NULL, 16); .
Edit :
A force de recherches, je pense avoir trouve qqch qui pourrait t'intéresser.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
la connaissance est une chose qui ne nous appauvrit pas quand on la partage.
Mon GitHub