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 :

Besoin d'aide pour un parseur HTML


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Par défaut Besoin d'aide pour un parseur HTML
    Bonjour,

    Voila je débute en langage C, et je viens de faire une petit programme qui analyse le contenu d'un fichier .html et voir si les balises sont corrects ou non.

    Le code n'est pas au top, mais c'est dèjà un bon début je trouve

    Rapide explication:

    Tout d'abord, mon analyse se fait à l'aide d'automate, c'est à dire qu'a chaque caractère lu, je passe d'un état à l'autre:

    "<": Etat un qui signifie début balise
    "/": Etat deux qui signifie qu'on est dans balise fermante.
    "a-z,A-Z": Etat trois qui nom de la balise fermante.
    "[espace ou tabulation]": Etat cinq => Attribut de la balise...
    etc...

    Le programme ouvre un fichier donné, rapporte le 1er caractère, après il le teste, et au fur et a mesure qu'il lit le fichier, il transite d'un etat à un autre, sauf erreur syntaxique, il le signale et s'arrete.

    Pour l'instant j'ai fait en sorte qu'il s'arrête dés qu'il trouve le ">", fin de balise, mais je trouve que mon code est mal organisé, j'aimerais l'optimiser mais je ne trouve pas comment.

    Voici le code:
    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #include <stdio.h>
    #include <stdlib.h>
    typedef enum {
        zero, un, deux, trois, quatre, cinq, six, sept, huit, neuf
    } etats;
     
    int main(int argc, char const *argv[])
    {
    	FILE *fichier;
    	etats courrant = zero;
        if(fichier = fopen("test.html", "r"))
        {
            char c = fgetc(fichier);
            while (c!=EOF)
            {
                switch(courrant)
                {
                    case zero:
                        if (c == '<') { courrant = un; c = fgetc(fichier); break; }
                        else c = fgetc(fichier);
     
                    case un:
                        if ((c >= 'a') && (c <= 'z')) { printf("Etat quatre\n"); courrant = quatre; c = fgetc(fichier); break; }
                        if (c == '/') { printf("etat deux\n"); courrant = deux; c = fgetc(fichier); break; }
                        else { printf("Syntax Error\n"); return 1; }
     
                    case deux:
                        if ((c >= 'a') && (c <= 'z')) { printf("Etat trois\n"); courrant = trois; c = fgetc(fichier); break; }
                        else { printf("Syntax Error\n"); return 1; }
     
                    case trois:
                        if (c == '>') { printf("fin de la balise"); return 1;}
                        if (c == ' ') {printf("Syntax error\n"); return 1;}
                        else { printf("Etat trois\n"); courrant = trois; c = fgetc(fichier); break; }
                    case quatre:
                        if (c == ' ') { printf("Etat cinq\n"); courrant = cinq; c = fgetc(fichier); break; }
                        if (c == '>') { printf("fin de la balise"); return 1;}
                        else { printf("Etat quatre\n"); courrant = quatre; c = fgetc(fichier); break; }
     
                    case cinq:
                        if (c == ' ') { printf("Etat cinq\n"); courrant = cinq; c = fgetc(fichier); break;}
                        if ( c == '>'|| c == '<'|| c == '=') { printf("Syntax Error\n"); return 1;}
                        else { printf("Etat six\n"); courrant = six; c = fgetc(fichier); break; }
     
                    case six:
                        if (c == '=') { printf("Etat sept\n"); courrant = sept; c = fgetc(fichier); break;}
                        else { printf("Etat six\n"); courrant = six; c = fgetc(fichier); break; }
     
                    case sept:
                        if (c == '"'|| c =='\'') { printf("Etat huit\n"); courrant = huit; c = fgetc(fichier); break;}
                        else { printf("Etat quatre\n"); courrant = quatre; c = fgetc(fichier); break; }
     
                    case huit:
                        if (c == '"'|| c =='\'') { printf("Etat neuf\n"); courrant = neuf; c = fgetc(fichier); break;}
                        else { printf("Etat huit\n"); courrant = huit; c = fgetc(fichier); break; }
     
                    case neuf:
                        if (c == ' ') { printf("Etat cinq\n"); courrant = cinq; c = fgetc(fichier); break;}
                        if (c == '>') { printf("fin de la balise"); return 1;}
                        else { printf("Syntax Error\n"); return 1; }
                }
            }
        }
        else printf("Couldn't open the file.\n");
        printf("Operation terminated");
        fclose(fichier);
    	return 0;
    }
    Voila j'espère qu'il n'est pas trop pénible à lire ou à comprendre

    Je remercie d'avance ceux qui ont pris le temps de le lire et d'y répondre !

    Cordialement.
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Bonjour,

    Pour ta machine à état, je te suggère les trois propositions suivantes:

    Avoir un type d'énumération pour les états.typedef enum {st_start, st_begin, st_close, st_end...} state_t;Avoir une étape intermédiaire pour diviser ton code en blocs, en utilisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef enum{TOKEN, UNTOKEN, VALUE} content_kind_t;
    typedef struct {
    content_kind_t type;
    const char* content;
    } token_t;
     
    typedef struct {
    token_t token;
    chain_t* next;
    } chain_t;
    l'idée, c'est de représenter
    <html><body><p>petit texte</p><p>autre texte</p></body></html>
    par la liste chainée:
    {TOKEN, "html"}
    {TOKEN, "body"}
    {TOKEN, "p"}
    {VALUE, "petit texte"}
    {UNTOKEN, "p"}
    {TOKEN, "p"}
    {VALUE, "petit texte"}
    {UNTOKEN, "p"}
    {UNTOKEN, "body"}
    {UNTOKEN, "html"}
    
    L'avantage, c'est que tu n'auras plus besoin d'une machine à état sur les caractères, mais sur ces blocs.
    Enfin, nous avons une balise pour le code (le bouton #)



    Il y a eu il y a peu une discussion similaire, avec la aussi une machine à état. Tu devrais jeter un œil sur ce qu'il y fut conseillé, cela pourrait t'éviter des soucis.

  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Le code est difficilement lisible parce qu'il mélange le code utile à celui utilisé pour le test (les printf) et introduit dans chaque case la lecture du fichier. D'ailleurs, je ne pense pas qu'il soit correct sur le case zero à cause de l'absence de break. Si le fichier commence par " <", avec un blanc (ou un \n) avant '<' alors on se retrouve sur case un avec '<' et on sort en erreur de syntaxe. Le cas des " et ' est également à vérifier.

    Pour le rendre plus lisible, j'ai réorganisé ton code en sortant les fgetc() du switch, et en masquant les printf() de test dans des macro. Un fois au point, il suffira de modifier les macros en éliminant les printf() pour que le code soit opérationnel.
    (J'espère ne pas avoir introduit d'autres erreurs, alors c'est à relire et à tester attentivement)
    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    /*--------------------------------------------------------*/
    #define RepeatState()  printf(" %d", courrant)
    #define SetState(v) printf("\nEtat %d", courrant=v)
    #define SyntaxError printf("\nSyntax Error\n"),0
    #define FinBalise   printf("\nfin de la balise\n"),1
    int Analyse( FILE * fichier)
    {
       etats courrant = zero;
       char c = fgetc(fichier);
       while (c!=EOF)
       {
          switch(courrant)
          {
             case zero:  if (c == '<') SetState(un);
                         break;
     
             case un:    if ((c >= 'a') && (c <= 'z')) SetState(quatre);
                         else if (c == '/') SetState(deux);
                              else return SyntaxError;
                         break;
     
             case deux:  if ((c >= 'a') && (c <= 'z')) SetState(trois);
                         else return SyntaxError;
                         break;
     
             case trois: if (c == '>') return FinBalise;
                         else if (c == ' ') return SyntaxError;
                              else RepeatState();//SetState(trois);
                         break;
     
             case quatre:if (c == ' ') SetState(cinq);
                         else if (c == '>') return FinBalise;
                              else RepeatState() ;// SetState(quatre);
                         break;
     
             case cinq:  if (c == ' ') RepeatState(); //SetState(cinq);
                         else if ( c == '>'|| c == '<'|| c == '=') return SyntaxError;
                              else SetState(six);
                         break;
     
             case six:   if (c == '=') SetState(sept);
                         else RepeatState();// SetState(six);
                         break;
     
             case sept:  if (c == '"'|| c =='\'') SetState(huit);
                         else SetState(quatre);
                         break;
     
             case huit:  if (c == '"'|| c =='\'') SetState(neuf);
                         else RepeatState(); //SetState(huit);
                         break;
     
             case neuf:  if (c == ' ') SetState(cinq);
                         else if (c == '>') return FinBalise;
                              else return SyntaxError;
                         break;
          }
          c = fgetc(fichier);
       }
       return 0;
    }
    /*--------------------------------------------------------*/
    int main(void)
    {
        FILE *fichier;
        if((fichier = fopen("test.html", "r"))!=NULL)
        {
            Analyse(fichier);
            fclose(fichier);
        }
        else printf("Couldn't open the file.\n");
        printf("Operation terminated");
        return 0;
    }

  4. #4
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Par défaut
    Re-Bonsoir,

    Je vous remercie vous deux pour vos réponses, elles me sont très utile, pas vraiment coté solution, mais surtout coté optimisation du code, en effet, le but de ce sujet pour moi c'était au faite de voir comment écrire un code "propre", mes codes sont toujours désordonnés ^^', si il y'a des conseils que vous pourriez me donner j'ai les oreilles grand ouvertes.

    Merci encore !

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Et bien, si tu veux des conseils, redonne nous ton code quand tu estimeras avoir fini, et nous te dirons ce que nous en pensons.

    C'est toujours un plaisir d'aider sur ce sujet!

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Par défaut
    Me revoilà !

    Maintenant je m'attaque à l'analyse d'un fichier balisé complet, en effet mon ancien programme s'arretait dés qu'il trouvait le ">".

    l'idée c'est de créer une pile ou je vais stocker les balises repérés dans le fichier, dés que je trouve "<" je sauvegarde le nom de la balise, et quand je trouve le ">" je prends le nom et j'empile.

    Dés que je trouve le "/", je sauvegarde le nom, je dépile le derniere élement de la pile et je compare les deux noms pour m'assurer que le chevauchement est correct.

    Ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <H1>
        <H2>
        </H2>
    </H1>
    Et non:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <H1>
       <H2>
    </H1>
       </H2>
    Mon problème: vu que je lis caractère par caractère mon fichier, je ne trouve pas comment prendre tous les chars qui constituent le nom, pour pouvoir l'empiler.

    Voici le code:
    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    /*--------------------------------------------------------*/
    #include <stdio.h>
    #include <stdlib.h>
    #include "tp1.h"
    #define RepeatState()  printf(" %d", courrant)
    #define SetState(v) printf("\nEtat %d", courrant=v)
    #define SyntaxError printf("\nSyntax Error\n"),0
    #define FinBalise   printf("\nfin de la balise\n"),1
     
    /*---------------------------------------------------------*/
    stack_s *stack_new (void)
    {
       return (NULL);
    }
     
    void stack_push (stack_s ** pp_stack, const char * data)
    {
       if (pp_stack != NULL)
       {
    /* (2) */
          stack_s *p_p = *pp_stack;
          stack_s *p_l = NULL;
     
    /* (3) */
          p_l = malloc (sizeof (*p_l));
          if (p_l != NULL)
          {
             p_l->data = data;
    /* (4) */
             p_l->next = NULL;
             p_l->prev = p_p;
             if (p_p != NULL)
                p_p->next = p_l;
    /* (5) */
             *pp_stack = p_l;
             printf("Nickel");
          }
          else
          {
             fprintf (stderr, "Memoire insuffisante\n");
             exit (EXIT_FAILURE);
          }
       }
       return;
    }
     
    /*--------------------------------------------------------*/
     
    char *stack_pop (stack_s ** pp_stack)
    {
       char *ret = NULL;
     
       if (pp_stack != NULL && *pp_stack != NULL)
       {
    /* (2) */
          stack_s *p_l = *pp_stack;
    /* (3) */
          stack_s *p_p = p_l->prev;
     
          if (p_p != NULL)
             p_p->next = NULL;
          ret = p_l->data;
    /* (4) */
          free (p_l);
          p_l = NULL;
    /* (5) */
          *pp_stack = p_p;
       }
       return (ret);
    }
     
    /*-------------------------------------------------------*/
     
    void stack_delete (stack_s ** pp_stack)
    {
       if (pp_stack != NULL && *pp_stack != NULL)
       {
          while (*pp_stack != NULL)
             stack_pop (pp_stack);
       }
       return;
    }
     /*------------------------------------------------------*/
     
    int Analyse( FILE * fichier)
    {
       etats courrant = zero;
       char c = fgetc(fichier);
       while (c!=EOF)
       {
          switch(courrant)
          {
             case zero:  if (c == '<') SetState(un);
                         break;
     
             case un:    if ((c >= 'a') && (c <= 'z')) SetState(quatre);
                         else if (c == '/') SetState(deux);
                              else return SyntaxError;
                         break;
     
             case deux:  if ((c >= 'a') && (c <= 'z')) SetState(trois);
                         else return SyntaxError;
                         break;
     
             case trois: if (c == '>') return FinBalise;
                         else if (c == ' ') return SyntaxError;
                              else RepeatState();//SetState(trois);
                         break;
     
             case quatre:if (c == ' ') SetState(cinq);
                         else if (c == '>') return FinBalise;
                              else RepeatState() ;// SetState(quatre);
                         break;
     
             case cinq:  if (c == ' ') RepeatState(); //SetState(cinq);
                         else if ( c == '>'|| c == '<'|| c == '=') return SyntaxError;
                              else SetState(six);
                         break;
     
             case six:   if (c == '=') SetState(sept);
                         else RepeatState();// SetState(six);
                         break;
     
             case sept:  if (c == '"'|| c =='\'') SetState(huit);
                         else SetState(quatre);
                         break;
     
             case huit:  if (c == '"'|| c =='\'') SetState(neuf);
                         else RepeatState(); //SetState(huit);
                         break;
     
             case neuf:  if (c == ' ') SetState(cinq);
                         else if (c == '>') return FinBalise;
                              else return SyntaxError;
                         break;
          }
          c = fgetc(fichier);
       }
       return 0;
    }
    /*--------------------------------------------------------*/
    int main(void)
    {
        FILE *fichier;
        //-------Test pour voir si mes fonctions de pile marchent.--------//
        /*
        const char *i = "Salah";
        stack_s *pile = stack_new();
        stack_push(&pile, i);
        const char *s = stack_pop(&pile);
        printf(s);
        */
        if((fichier = fopen("test.html", "r"))!= NULL )
        {
            Analyse(fichier);
            fclose(fichier);
        }
        else printf("Couldn't open the file.\n");
        printf("Operation terminated");
        return 0;
    }
    Need Help ! Merci

Discussions similaires

  1. [RegEx] Besoin d'aide pour une regex (html)
    Par benjamin122 dans le forum Langage
    Réponses: 10
    Dernier message: 07/09/2012, 23h33
  2. Besoin d'aide pour modifier un fichier html
    Par killahpriest dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 22/08/2010, 15h35
  3. [HTML 4.0] Besoin d'aide pour la programmation d'un menu en html
    Par JaMJaMs dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 03/12/2009, 20h02
  4. Besoin d'aide pour quelques bugs sur page html
    Par Xplosive dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 19/10/2008, 19h38
  5. [Tableaux] Besoin d'aide pour parser du HTML
    Par vallica dans le forum Langage
    Réponses: 2
    Dernier message: 08/10/2006, 22h12

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