IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Parser une requête HTTP/GET en c ! regex ?


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut Parser une requête HTTP/GET en c ! regex ?
    Bonjour,

    J'ai dans une chaîne de caractère ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    request?foo=bar&bar=foo
    Et je souhaite obtenir un résultat sous forme de tableau:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    res[0][0] = "foo"
    res[0][1] = "bar"
    res[1][0] = "bar"
    res[1][1] = "foo"
    Intuitivement il faudrait utiliser les regex non ?

    genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "[a-z]*\?([a-z]*)=([a-z]*)?(&([a-z]*)=([a-z]*))*"
    mais à l'évidence cela ne fonctionne pas puique je n'arrive pas à avoir de parenthèses capturantes répétivives avec les regex.

    Avez-vous une idée à me proposer ?

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Parser une requête HTTP/GET en c ! regex ?
    Citation Envoyé par canard75
    Intuitivement il faudrait utiliser les regex non ?
    Bof, Je commencerais par un truc simple et standard genre strtok()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    #include <stdio.h>
    #include <string.h>
     
    #define N(a) (sizeof(a)/sizeof*(a))
     
    int main (void)
    {
        char s[] = "request?foo=bar&bar=foo";
        char *pp[6] =
            {
                0
            };
        size_t i = 0;
        size_t const n = N(pp) - 1;
        char *p = s;
     
        printf ("n = %u\n", (unsigned) n);
     
        while ((pp[i] = strtok(p, "?=&")) != NULL
                && i < n)
        {
            printf ("i = %u\n", (unsigned) i);
            if (i == 0)
            {
                p = NULL;
            }
            i++;
        }
        pp[i] = NULL;
     
        {
            size_t i = 0;
            while (pp[i] != NULL)
            {
                printf ("pp[%u] = %s\n", (unsigned) i, pp[i]);
                i++;
            }
        }
        return 0;
    }
    Pas de Wi-Fi à la maison : CPL

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Huhu !

    Bon ca fonctionne parfaitement mais il va me falloir un moment pour comprendre tout ca

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par canard75
    Bon ca fonctionne parfaitement mais il va me falloir un moment pour comprendre tout ca
    Ben oui. Ca fait partie du métier... Commence par lire la doc de strok(). Ensuite, pose des questions précises si tu ne comprends pas.
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    ce qu'il y a d'interessant c'est que ca compile avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    test2.c: In function `main':
    test2.c:14: warning: implicit declaration of function `strtok'
    test2.c:14: warning: assignment makes pointer from integer without a cast
    et ca fonctionne quand même...

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par canard75
    ce qu'il y a d'interessant c'est que ca compile avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    test2.c: In function `main':
    test2.c:14: warning: implicit declaration of function `strtok'
    test2.c:14: warning: assignment makes pointer from integer without a cast
    et ca fonctionne quand même...
    Par hasard, uniquement !

    Petit oubli de ma part :
    Corrigé.
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Merci pour le code. J'ai eu un peu de peine à suivre votre logique et j'en ai retiré ce qui suit.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
    #include <string.h> 
     
    #define N(a) (sizeof(a)/sizeof*(a))
    #define NB_PARAM 100 
    #define STRING "request?vara=resa&varb=resb&varc=resc"
    int main() {
    	char s[] = STRING;
    	char *pp[NB_PARAM];
    	size_t i = 1;
     
    	// Analyse
    	if((pp[0] = strtok(s, "?=&")))
    		for(i=1; (pp[i] = strtok(NULL, "?=&")) != NULL && i < (NB_PARAM); i++)
    		  printf("i = %d\n",i);	 
    	pp[i] = NULL;   
     
    	// Resultats
    	i = 0;
    	for(i=0; pp[i] != NULL; i++)
    		printf("pp[%d] = %s\n",i,pp[i]);
       return 0;
    }
    Pourquoi utilisez-vous %u et non %d et pourquoi passez-vous par un pointeur char *n ?

    Dans tous les cas je ne connaissais pas strtok, c'est excellent, merci

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Après une seconde optimisation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
    #include <string.h> 
     
    int ParseQuestion(char* question, char **pp) {
       int i = 1;	                                                 
    	if((pp[0] = strtok(question, "?=&"))) 
    		for(i=1; (pp[i] = strtok(NULL, "?=&")) != NULL; i++);
    	pp[i] = NULL;   
    	if(i==1) return -1; 
    	return 0; 
    }
     
    int main() {
    	int i=0;
    	char lala[] = "request?vara=resa&varb=resb&varc=resc";
    	char *res[100]; 
    	if(ParseQuestion(lala, res)) perror("Erreur"); 
    	for(i=0; res[i] != NULL; i++)
    		printf("res[%d] = %s\n",i,res[i]);   
       return 0;
    }

  9. #9
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Simple remarque, car Emmanuel n'a évidemment pas fait l'erreur :
    il faut effectivement déclarer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char s[] = "request?foo=bar&bar=foo";
    et non pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *s = "request?foo=bar&bar=foo";
    car dans le second cas s pointe vers une adresse mémoire non modifiable et le strtok plante, alors que s[] déclare un tableau tab, dans une zone mémoire modifiable initialisée avec la chaîne "request?foo=bar&bar=foo" et la le strtok peut travailler sans problème
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  10. #10
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par canard75
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
    #include <string.h> 
     
    #define N(a) (sizeof(a)/sizeof*(a))
    #define NB_PARAM 100 
    #define STRING "request?vara=resa&varb=resb&varc=resc"
    int main() {
    	char s[] = STRING;
    	char *pp[NB_PARAM];
    	size_t i = 1;
     
    	// Analyse
    	if((pp[0] = strtok(s, "?=&")))
    		for(i=1; (pp[i] = strtok(NULL, "?=&")) != NULL && i < (NB_PARAM); i++)
    		  printf("i = %d\n",i);	 
    	pp[i] = NULL;   
     
    	// Resultats
    	i = 0;
    	for(i=0; pp[i] != NULL; i++)
    		printf("pp[%d] = %s\n",i,pp[i]);
       return 0;
    }
    Pourquoi utilisez-vous %u et non %d et pourquoi passez-vous par un pointeur char *n ?
    J'utilise "%u" pour afficher i qui est de type size_t, c'est à dire entier non signé. J'avais ajouté le cast (unsigned) pour assurer la cohérence entre la variable et son formatteur. Il ne faut la le retirer comme ça...

    Quand à 'char *n' ? Je ne vois pas de quoi tu parles...
    Dans tous les cas je ne connaissais pas strtok, c'est excellent, i
    Pour une maquette, ça va, mais dans l'industrie, on utilise la fonction POSIX strtok_r() pour des questions de réentranc et d'appels imbriqués...

    Les fonctions POSIX, bien que non standards, sont très portables.

    J'utilise aussi ceci :

    http://emmanuel-delahaye.developpez.com/clib.htm
    Module TOK
    Pas de Wi-Fi à la maison : CPL

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Dans mon cas cela compile et s'execute normalement, Il y a quand même une erreur ?

  12. #12
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par canard75
    Dans mon cas cela compile et s'execute normalement, Il y a quand même une erreur ?
    Oui. Pour qu'un programme soit correct :
    • Il ne doit pas y avoir de comportement indéfini. Or cet erreur de cast en est un. Le problème d'un comportement indéfini est que son effet n'est pas forcément visible, ce qui le rend extrêment dangereux (en général il se manifeste le jour de la démo devant le client ou le grand patron... Loi de Murphy...)
    • Ensuite, il ne doit pas y avoir d'erreur de compilation ni de warnings (non expliqués).
    • Enfin, le comportement doit être conforme aux attentes.
    Pas de Wi-Fi à la maison : CPL

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Ok compris

  14. #14
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    J'attire votre attention sur les pages man de strtok:

    Never use these functions. If you do, note that:

    These functions modify their first argument.

    These functions cannot be used on constant strings.

    The identity of the delimiting character is lost.

    The strtok() function uses a static buffer while parsing, so it's not thread safe. Use
    strtok_r() if this matters to you.
    Jc

    PS: désolé je les ai en anglais seulement...

  15. #15
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par fearyourself
    PS: désolé je les ai en anglais seulement...
    évitez au maximum d'utiliser cette fonction. Sinon, prenez note des informations suivantes :

    Cette fonction modifie son premier argument.

    Les caractères de séparation sont surchargés, leur identité est donc perdue.

    Cette fonction ne doit pas être invoquée sur une chaîne constante.

    La fonction strtok() utilise un buffer statique et n'est donc pas sûre dans un contexte multithread. Dans ce cas il vaut mieux utiliser strtok_r().
    Du momment que t'es au courant ça ne gène pas.

Discussions similaires

  1. [PHP 5.3] Récupérer des données issues d'une requête http GET
    Par Pierrea4564 dans le forum Langage
    Réponses: 2
    Dernier message: 24/09/2013, 08h15
  2. [LINUX] Simuler une requête HTTP POST ou GET
    Par Anified dans le forum Linux
    Réponses: 1
    Dernier message: 05/02/2007, 16h11
  3. [Tableaux] Passer un tableau dans une requête HTTP ??
    Par haffouff dans le forum Langage
    Réponses: 2
    Dernier message: 09/05/2006, 17h17
  4. Réponses: 1
    Dernier message: 21/03/2006, 14h29
  5. [HTTP]Créer une requête http multipart/related
    Par jothi35 dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 05/04/2005, 15h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo