OVH Cloud OVH Cloud

Analyse syntaxique

31 réponses
Avatar
Dominique MICOLLET
Bonjour,

Je cherche à isoler dans la chaîne suivante :
%%%{1,[2,0,0,0,0,2]%%%}+%%%{1,[1,0,0,1,0,2]%%%}
les différents nombres qui y apparaissent, en conservant leur sémantique (le
premier 1 est un coefficient, le premier 2 est un degré).

En utilisant astucieusement les méthodes de recherche de caractères ou
sous-chaînes et d'extraction de ces dernières, je devrais m'en sortir.

Mais j'imagine que d'autres ont déjà eu ce souci et qu'il existe une
solution toute prête.

Auriez des suggestions de pistes à suivre ?

--
Cordialement

Dominique MICOLLET Email : enlever deux fr
Universite de Bourgogne
9, Avenue Alain SAVARY BP 47870 Tel : +33/(0)3-80-39-59-27
21078 DIJON CEDEX FRANCE Tfx : +33/(0)3-80-39-68-69

10 réponses

1 2 3 4
Avatar
Sylvain
Marc Boyer wrote on 28/02/2007 10:46:

Parce qu'il est extrèmement fragile en ce qui concerne les
paramètres, exigeant des pointeurs à des types bien précis ?


M'enfin bon, les compilos en 2007 font la vérification de
type il me semble, non ?


non, même en 2007, le compilo ne vérifie pas qu'au premier "%lf"
correspond bien un pointeur sur double.
(il a été indiqué qu'un oubli du modifier "l" est possible...)

pour autant, je partage l'avis que les ?scanf restent utilisables si le
cadre est entièrement maitrisé (génération des output et des scans);
mais également que l'écriture from-rien-du-tout d'une classe stream
implémentant un extracteur d'entiers et/ou flotttants est un très bon
exercice qui pourra être mené en temps assez court.

Sylvain.


Avatar
James Kanze
On Feb 28, 10:49 pm, Sylvain wrote:
Marc Boyer wrote on 28/02/2007 10:46:

Parce qu'il est extrèmement fragile en ce qui concerne les
paramètres, exigeant des pointeurs à des types bien précis ?


M'enfin bon, les compilos en 2007 font la vérification de
type il me semble, non ?


non, même en 2007, le compilo ne vérifie pas qu'au premier "%lf"
correspond bien un pointeur sur double.
(il a été indiqué qu'un oubli du modifier "l" est possible...)


Certains le font, d'autres non. En revanche, si on
« construit » la chaîne, au moyen des operator+ sur un
std::string, et c_str() ensuite, je n'en connais aucun qui le
fait.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
James Kanze
On Feb 28, 10:48 am, Marc Boyer
wrote:

On Feb 26, 6:11 pm, Michel Decima wrote:

On Mon, 26 Feb 2007 15:28:12 +0000 (UTC), Marc Boyer
:

string s= "%%%{1,[2,0,0,0,0,2]%%%}+%%%{1,[1,0,0,1,0,2]%%%}";
int res= scanf("%%%%%%{%d,[%d,%d,%d,%d,%d,%d]%%%%%%}+"
"%%%%%%{%d,[%d,%d,%d,%d,%d,%d]%%%%%%}",
&coef,&degre,
/// A continuer avec la sémantique de tes vars
C'est lourd, impossible à maintenir, et tout se casse la gueule si

jamais l'expression n'est pas fixe.


Sérieux ?
Et tu envisages quoi qui serait moins lourd, plus maintenable ?



Prèsque n'importe quoi. Côté maintenabilité : d'après la
sémantique qu'il a suggéré, ça ne m'étonnerait pas que certai nes
des valeurs, voire toutes, soient des flottants. Alors,
attention entre les %f et les %lf.


Le compilo émet des avertissements il me semble.


La plupart non. Et évidemment, ça serait plus maintenable de
construire la chaîne à partir des composants -- une chaîne separ
qui contient "%%%", par exemple -- au moyen des additions sur
des chaînes ; dans ce cas-là, je ne connais aucun compilateur
qui émet un avertissement.

Sans parler des histoires de
localisation : s'il travaille avec une locale français (fort
probable vue la langue dans laquelle il a posté), les virgules
vont poser des problèmes s'il veut des flottants.


Ca, c'est un vrai problème. Mais une fois identifié, il
se résoud assez vite (remplacer les , par des :, les %
par des # tant qu'on y est, et les . par des ,).


Ou en forçant la locale global à "C", et en le restituant par la
suite.

Ce n'est pas que ce n'est pas faisable, mais c'est bien une
lourdeur de plus, et un problème supplémentaire de maintenance.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34






Avatar
Marc Boyer
Le 28-02-2007, Sylvain a écrit :
Marc Boyer wrote on 28/02/2007 10:46:
Parce qu'il est extrèmement fragile en ce qui concerne les
paramètres, exigeant des pointeurs à des types bien précis ?


M'enfin bon, les compilos en 2007 font la vérification de
type il me semble, non ?


non, même en 2007, le compilo ne vérifie pas qu'au premier "%lf"
correspond bien un pointeur sur double.
(il a été indiqué qu'un oubli du modifier "l" est possible...)


#include <stdio.h>

int main(){
float f;
double d;
scanf("%f", &f);
scanf("%lf", &f);
scanf("%f", &d);
scanf("%lf", &d);
return 0;
}


zeus|news> g++ fclc.c -W -Wall -pedantic
fclc.c: In function `int main()':
fclc.c:7: attention : format double, arg float (arg 2)
fclc.c:8: attention : format float, arg double (arg 2)

Alors apres, oui, on peut utiliser le langage sans demander
de Warning au compilo. C'est AMHA un usage aussi mauvais que
l'usage de gets ou l'usage de char* en lieu et place de
std::string.
Le C a une vieille histoire avec quelques scories, le C++
en herite de quelques unes.

mais également que l'écriture from-rien-du-tout d'une classe stream
implémentant un extracteur d'entiers et/ou flotttants est un très bon
exercice qui pourra être mené en temps assez court.


A ce rythme la, autant prendre boost::regex. Ce sera le meme
cout de developpement, mais je pense qu'a la maintenance, on prefere
l'usage de solutions standard que de solutions ad-hoc.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)



Avatar
Marc Boyer
Le 01-03-2007, James Kanze a écrit :
On Feb 28, 10:48 am, Marc Boyer
On Feb 26, 6:11 pm, Michel Decima wrote:
On Mon, 26 Feb 2007 15:28:12 +0000 (UTC), Marc Boyer
:

string s= "%%%{1,[2,0,0,0,0,2]%%%}+%%%{1,[1,0,0,1,0,2]%%%}";
int res= scanf("%%%%%%{%d,[%d,%d,%d,%d,%d,%d]%%%%%%}+"
"%%%%%%{%d,[%d,%d,%d,%d,%d,%d]%%%%%%}",
&coef,&degre,
/// A continuer avec la sémantique de tes vars
C'est lourd, impossible à maintenir, et tout se casse la gueule si

jamais l'expression n'est pas fixe.


Sérieux ?
Et tu envisages quoi qui serait moins lourd, plus maintenable ?



Prèsque n'importe quoi. Côté maintenabilité : d'après la
sémantique qu'il a suggéré, ça ne m'étonnerait pas que certaines
des valeurs, voire toutes, soient des flottants. Alors,
attention entre les %f et les %lf.


Le compilo émet des avertissements il me semble.


La plupart non.


Sérieux ?

Et évidemment, ça serait plus maintenable de
construire la chaîne à partir des composants -- une chaîne separ
qui contient "%%%", par exemple -- au moyen des additions sur
des chaînes ; dans ce cas-là, je ne connais aucun compilateur
qui émet un avertissement.


Doucement. On parle là de lire un format qui ne demande quand même
pas de une construction complexe.

Sans parler des histoires de
localisation : s'il travaille avec une locale français (fort
probable vue la langue dans laquelle il a posté), les virgules
vont poser des problèmes s'il veut des flottants.


Ca, c'est un vrai problème. Mais une fois identifié, il
se résoud assez vite (remplacer les , par des :, les %
par des # tant qu'on y est, et les . par des ,).


Ou en forçant la locale global à "C", et en le restituant par la
suite.

Ce n'est pas que ce n'est pas faisable, mais c'est bien une
lourdeur de plus, et un problème supplémentaire de maintenance.


A comparer avec la maintenance des autres solutions.
Dans , j'ai fait
la solution à base de regex. Si je ne me trompe pas, ça donne

const std::string num= " *[-+]?[0-9]+.?[0-9]* *";
const std::string match_num= "("+num+")";
const std::string six_num= match_num + "," + match_num + ","
+ match_num + "," + match_num
+ match_num + "," + match_num;
const boost::regex e("%%%{"+match_num+"["+six_num+"]%%%}+%%%{"
+match_num+"["+six_num+"]%%%}";

Je laisse chacun juger de la simplicité relative de chaque
version.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)







Avatar
Jean-Marc Desperrier
James Kanze wrote:
Ou en forçant la locale global à "C", et en le restituant par la
suite.


Ce n'est pas thread safe, on peut générer des anomalies de comportement
très difficiles à comprendre avec ce genre de chose.

Avatar
Sylvain
Marc Boyer wrote on 01/03/2007 09:27:

int main(){
float f;
double d;
scanf("%f", &f);
scanf("%lf", &f);
scanf("%f", &d);
scanf("%lf", &d);
return 0;
}

zeus|news> g++ fclc.c -W -Wall -pedantic
fclc.c: In function `int main()':
fclc.c:7: attention : format double, arg float (arg 2)
fclc.c:8: attention : format float, arg double (arg 2)


?!? jamais vu de tels messages - et je ne les attendais pas !
le mix français/anglais traduit le fait que c'est un plug-in (g++ très
spécifique) expérimental ?

ça marche aussi sur une construction aussi basique que:

struct floats {
float f1, f2;
double d;
};

int foo(floats& out, const char* in, const char* format)
{
return (in) ? sscanf(in, format, &out.f1, &out.f2, &out.d) : 0;
}

?

Alors apres, oui, on peut utiliser le langage sans demander
de Warning au compilo. C'est AMHA un usage aussi mauvais que
l'usage de gets ou l'usage de char* en lieu et place de
std::string.


personne n'a suggéré cela.

Le C a une vieille histoire avec quelques scories, le C++
en herite de quelques unes.


s'il cherche à renier cet héritage par du traitement de texte sur
quelque fonctions du CRT, cela ne me parait pas pertinent.

mais je pense qu'a la maintenance, on prefere
l'usage de solutions standard que de solutions ad-hoc.


hmm, "ad hoc" (ou idoine) signifie "convenant spécifiquement à la
situation", on y préfererait des solutions "standards" donc
généralistes, donc incluant plein de détails, options, subtilités,
inutiles et donc potentiellement confusants pour le problème traité ??
je ne suis pas sur de partager ce point de vue.

Sylvain.

Avatar
Marc Boyer
Le 01-03-2007, Sylvain a écrit :
Marc Boyer wrote on 01/03/2007 09:27:

int main(){
float f;
double d;
scanf("%f", &f);
scanf("%lf", &f);
scanf("%f", &d);
scanf("%lf", &d);
return 0;
}

zeus|news> g++ fclc.c -W -Wall -pedantic
fclc.c: In function `int main()':
fclc.c:7: attention : format double, arg float (arg 2)
fclc.c:8: attention : format float, arg double (arg 2)


?!? jamais vu de tels messages - et je ne les attendais pas !
le mix français/anglais traduit le fait que c'est un plug-in (g++ très
spécifique) expérimental ?


% g++ --version
g++ (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

En général avec g++, je passe la locale à "C", mais là, j'ai
fait ça vite.

ça marche aussi sur une construction aussi basique que:

struct floats {
float f1, f2;
double d;
};

int foo(floats& out, const char* in, const char* format)
{
return (in) ? sscanf(in, format, &out.f1, &out.f2, &out.d) : 0;
}


Sauf que là, il devrait dire quoi ? Il a pas le format...

Alors apres, oui, on peut utiliser le langage sans demander
de Warning au compilo. C'est AMHA un usage aussi mauvais que
l'usage de gets ou l'usage de char* en lieu et place de
std::string.


personne n'a suggéré cela.


OK

mais je pense qu'a la maintenance, on prefere
l'usage de solutions standard que de solutions ad-hoc.


hmm, "ad hoc" (ou idoine) signifie "convenant spécifiquement à la
situation", on y préfererait des solutions "standards" donc
généralistes, donc incluant plein de détails, options, subtilités,
inutiles et donc potentiellement confusants pour le problème traité ??
je ne suis pas sur de partager ce point de vue.


Ben, toujours question d'équilibre.
Là, pour parser une chaine du style
%%%{1,[2,0,0,0,0]%%%}+%%%{1,[2,0,0,0,0]%%%}
tu proposais d'écrire une classe istream spécifique, c'est bien ça ?

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)


Avatar
Sylvain
Marc Boyer wrote on 01/03/2007 16:59:

Ben, toujours question d'équilibre.


oui, appliquuons *la* règle ... au cas par cas ;)

Là, pour parser une chaine du style
%%%{1,[2,0,0,0,0]%%%}+%%%{1,[2,0,0,0,0]%%%}
tu proposais d'écrire une classe istream spécifique, c'est bien ça ?


oui - le PO nous parle de coefficient et de degré (ce qu'il a appelé la
sémantique des valeurs extraites).

ce point me laisse penser que l'on ne cherchera ici à extraire les
valeurs en leur donnant un sens basé sur la position et/ou la syntaxe
(dans un {} pour le rang du coeff, dans un [] pour les exposants d'un
polynome (?)).
un istream qui soit capable de générer des vecteurs de int (les
'degrés') indexés sur les 'coefficient', tout en jetant tout le reste me
parait aussi compliqué que 2 tests (inBracket, inSqrBracket).

Sylvain.

Avatar
Marc Boyer
Le 01-03-2007, Sylvain a écrit :
Marc Boyer wrote on 01/03/2007 16:59:

Ben, toujours question d'équilibre.


oui, appliquuons *la* règle ... au cas par cas ;)

Là, pour parser une chaine du style
%%%{1,[2,0,0,0,0]%%%}+%%%{1,[2,0,0,0,0]%%%}
tu proposais d'écrire une classe istream spécifique, c'est bien ça ?


oui - le PO nous parle de coefficient et de degré (ce qu'il a appelé la
sémantique des valeurs extraites).

ce point me laisse penser que l'on ne cherchera ici à extraire les
valeurs en leur donnant un sens basé sur la position et/ou la syntaxe
(dans un {} pour le rang du coeff, dans un [] pour les exposants d'un
polynome (?)).


C'est à dire pas toujours le même nombre d'entiers entre les [] ?
Oui, dans ce cas là, sscanf me semble très inadapté.

Comme quoi, avant de coder, bien préciser le cahier des charges.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)


1 2 3 4