Un algo pas si simple...

Un algo pas si simple... - Algo - Programmation

Marsh Posté le 23-01-2003 à 10:37:26    

Le contexte est le suivant :
J'ai une appli qui rempli une table de log.
On veut permettre à l'utilisateur de consulter cette table depuis l'interface de mon appli.
Mais cette table est généralement énorme, donc afficher tous les les enregistrements prendrait un temps énorme.
un des champ de ma table de log est MSGID. ce champ identifie le type de message d'un enregistrment.
J'ai donc opté pour la solution suivante :
offrir la possibilité de définir un filtre sur ce MSGID, sachant que :
| veut dire que la valeur suivante est également visualisable.
- représente un interval de valeurs visualisables.
par exemple le filtre "5000-5999|6001" autorise la visualisation des messages dont le MSGID est compris entre 5000 et 5999, plus ceux dont le MSGID est 6001.
Je pensait que l'algo serait assez simple, mais je suis en train de rajouter tout un tas de cas particuliers, je m'en sort pas.  
Pour l'instant, mon algo en est là (c'est codé en C) :
Je commence par séparer les 2 types d'éléments : opérateurs '-' et '|', et chiffres. Je stocke tous les opérateurs dans un tableau, et tous les chiffres dans un autre.
ensuite, mon algo en est là :

Code :
  1. char szPartToAdd[32];                // Partie de clause where à ajouter
  2.                     char curentOp    = '\0';             // Opérateur courant
  3.                     char nextOp      = '\0';             // Opérateur précédant
  4.                     long lPrevMSGID  = '\0';             // MSGID précédant l'opérateur courant
  5.                     long lNextMSGID  = '\0';             // MSGID suivant l'opérateur courant
  6.                     BOOL bFirstCondition = TRUE;
  7.                     BOOL bColNameWrited  = FALSE;
  8.                     if (lNbOp == 0)
  9.                     {
  10.                         memset (szPartToAdd, 0, sizeof (szPartToAdd));
  11.                         sprintf (szPartToAdd, "MSGID = %ld", lplAllMSGID[0]);
  12.                         strcat (szWhereClause, szPartToAdd);
  13.                     }
  14.                     else
  15.                     {
  16.                         for (lCpt = 0; lCpt <= lNbOp; lCpt++)
  17.                         {
  18.                             memset (szPartToAdd, 0, sizeof (szPartToAdd));
  19.                             if (!bColNameWrited)
  20.                             {
  21.                                 if (bFirstCondition)
  22.                                 {
  23.                                     strcat (szWhereClause, "MSGID " );
  24.                                     bFirstCondition = FALSE;
  25.                                 }
  26.                                 else
  27.                                    strcat (szWhereClause, "OR MSGID " );
  28.                                 bColNameWrited = TRUE;
  29.                             }
  30.                             curentOp   = szAllOp[lCpt];
  31.                             nextOp     = szAllOp[lCpt+1];
  32.                             lPrevMSGID = lplAllMSGID[lCpt];
  33.                             lNextMSGID = lplAllMSGID[lCpt+1];
  34.                             if (curentOp == '-')
  35.                             {
  36.                                 sprintf (szPartToAdd, "BETWEEN %ld AND %ld ", lPrevMSGID, lNextMSGID);
  37.                                 bColNameWrited = FALSE;
  38.                             }
  39.                             else if (curentOp == '|')
  40.                             {
  41.                                 if (lCpt == 0)
  42.                                 {
  43.                                     sprintf (szPartToAdd, "= %ld ", lPrevMSGID);
  44.                                     bColNameWrited = FALSE;
  45.                                 }
  46.                                 else if ((lCpt == lNbOp) || (nextOp == '|'))
  47.                                 {
  48.                                     sprintf (szPartToAdd, "= %ld ", lNextMSGID);
  49.                                     bColNameWrited = FALSE;
  50.                                 }
  51.                                 else
  52.                                 {
  53.                                     continue;
  54.                                 }
  55.                             }
  56.                             strcat (szWhereClause, szPartToAdd);
  57.                         }
  58.                     }


 
Bref, un 'ti coup de main serait le bienvenu !

Reply

Marsh Posté le 23-01-2003 à 10:37:26   

Reply

Marsh Posté le 23-01-2003 à 11:40:50    

Réécris ton code pour en faire un automate. En voici le pseudo-code :
 
variables
  Liste : tableau de couples d'entiers   -- pour désigner des intervalles de valeurs
  nombre : entier    -- pour construire un entier caractère par caractère
  intervalle : booléen
 
intervalle = FAUX
nombre        = 0
 
Pour chaque caractère car
    selon car
        '0'-'9':
            nombre = nombre * 10 + chiffre-correspondant
 
        '-':
            nombre     = 0
            intervalle = VRAI
            ajouter le couple (nombre, 0) à liste
 
        '|':
            si intervalle
                alors modifier le 2ème terme du dernier couple de liste avec nombre
                sinon ajouter le couple (nombre, nombre) à liste
            nombre     = 0
            intervalle = FAUX
    fin de sélection
fin de boucle
 
Voilà l'idée générale. Après, tu brodes.

Reply

Marsh Posté le 23-01-2003 à 11:51:05    

L'idée me plait assez.
Ms là je suis en train de partir sur autre chose.
Au lieu d'isoler tous les opérateurs, je constitue un tableau isolant tous les "OR" sql (caractère '|' dans mon codage).
Ainsi, si on a ça "5001|5002-6001|7002|6005-6007", je stocke 5001, 5002-6001, 7002, 6005-6007. Ensuite, pour chaque élément de ce nouveau tableau, je fait soit une égalité, soit un interval, en ajoutant des OR pour chacun.
ça me parait + simple comme ça...

Reply

Marsh Posté le 23-01-2003 à 12:25:33    

Effectivement, cela peut sembler plus simple à première vue de se baser sur un tokenizer.
 
Mais à mon avis, le code final sera plus complexe, plus long en nombre de ligne de code source, tout en étant moins évolutif, et qui plus est plus lent et plus gourmand en mémoire (oui, oui, tout ça ! :D ) qu'un bête automate à états finis.
 
Mais tu es libre de découvrir cela par toi-même ! ;)

Reply

Marsh Posté le 01-02-2003 à 05:50:00    

Reconnaître, stocker et analyser des sous-séquences intermédiaires... C++ n'est pas fait pour ça, il ne facilite pas les choses.
 
J'ai déjà plusieurs fois fait une analyse de ce genre, et j'ai toujours fini par aboutir à l'exemple de BifaceMcLeOD.
 
Je m'étais dit "tiens, ça ressemble à la description d'un automate" :) .


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 01-02-2003 à 09:10:54    

:ange:  :jap:

Reply

Sujets relatifs:

Leave a Replay

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