Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Combinaison min/MAJ

43 réponses
Avatar
spongebof
Bonjour,

Je cherche un algorithme à implémenter en C qui soit capable à partir
d'un mot de X caractères de trouver toutes les écritures possibles pour
0 à X majuscule(s) présente(s) dans ce mot.

Exemple pour le mot 'test':

test
tesT
teSt
teST
tEst
tEsT
tESt
tEST
Test
TesT
TeSt
TeST
TEst
TEsT
TESt
TEST

Merci

10 réponses

1 2 3 4 5
Avatar
espie
In article <47406762$0$29541$,
Aris wrote:
In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);


Euh, le cast en question, c'est la bibliotheque C qui est censee le
faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...
de manière générale, jamais faire de cast explicite là où le cast

implicite fonctionne. C'est la porte ouverte à des conversions invalides
qui peuvent prendre des heures à débugger


Merci de l'enfoncage de portes ouvertes... ;-)
Je crois que le probleme ici est un peu plus subtil, et j'attendrai la
reponse de Charlie...



Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);


Euh, le cast en question, c'est la bibliotheque C qui est censee le
faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...


"In all cases the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of the macro
EOF."

Si on a un char signé, le passer à tolower etc sans faire un cast en
unsigned char est du comportement indéfini quand la valeur est négative et
différente de EOF (et on a potentiellement un mauvais résultat si la valeur
est celle d'EOF, ce qui est le cas par exemple dans une locale latin-9 pour
y tréma passé à toupper).

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Charlie Gordon
"Marc Espie" a écrit dans le message de news:
fhmfph$2e90$
In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);


Euh, le cast en question, c'est la bibliotheque C qui est censee le
faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...


Oui et non, tu as raison, le cast n'est nécessaire que pour islower() et ses
amis.
Mais le texte de la norme n'est pas assez précis:

C99 7.4.2.1p3: "If the argument is a character for which isupper is true and
there are one or more
corresponding characters, as specified by the current locale, for which
islower is true,
the tolower function returns one of the corresponding characters (always the
same one
for any given locale); otherwise, the argument is returned unchanged."

C'est fallacieux de parler de "character for which isupper is true" alors
que isupper n'est pas définie pour les 'characters' négatifs, mais seulement
pour les unsigned char et la valeur EOF. Il me semble que cette définition
est ambiguë quand les char sont signés (les char devraient être non signés
pas défaut, une bonne fois pour toutes).

--
Chqrlie.


Avatar
Charlie Gordon
"Aris" a écrit dans le message de news:
47406762$0$29541$
In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);


Euh, le cast en question, c'est la bibliotheque C qui est censee le
faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...
de manière générale, jamais faire de cast explicite là où le cast

implicite fonctionne. C'est la porte ouverte à des conversions invalides
qui peuvent prendre des heures à débugger


Tout à fait d'accord!

Mais dans le cas de islower() et ses amis, le cast en (unsigned char) est
nécessaire si le type 'char' est signé par défaut. islower() n'est défini
que pour toutes les valeurs du type unsigned char et la valeur EOF. Lui
passer un char signé négatif viole cette contrainte, et comme cette fonction
est souvent implémentée comme une macro qui ne valide pas son argument, le
comportement indéfini peut être méchant.

Il est très instructif de regarder l'implémentation de <ctype.h> de la
Glibc. Ils utilisent une astuce DDLF pour contourner cette incohérence du
langage (char signé par défaut) et donnent ainsi un comportement défini pour
tout argument signed char *et* unsigned char en plus de EOF (qui vaut -1).
Ceci dit ils ne peuvent pas résoudre le cas de 'ÿ' qui dans l'encodage
iso-latin1 vaut 255, soit -1 en tant que char signé, et est donc
indiscernable de la valeur de EOF. Donc islower('ÿ') == 0, comme
islower(EOF), ce qui est un peu surprenant.

Moralité: avec gcc, j'utilise toujours l'option -funsigned-char

--
Chqrlie.



Avatar
Charlie Gordon
"Jean-Marc Bourguet" a écrit dans le message de news:

(Marc Espie) writes:

In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);


Euh, le cast en question, c'est la bibliotheque C qui est censee le
faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...


"In all cases the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of the macro
EOF."

Si on a un char signé, le passer à tolower etc sans faire un cast en
unsigned char est du comportement indéfini quand la valeur est négative et
différente de EOF (et on a potentiellement un mauvais résultat si la
valeur
est celle d'EOF, ce qui est le cas par exemple dans une locale latin-9
pour
y tréma passé à toupper).


Merci Jean-Marc, comme d'habitude je me suis fait avoir par cette sale
habitude du comité ISO de mettre en facteur des contraintes en debut de
section. Donc j'avais bon, mais c'est vraiment un piège merdique au
possible.

A+


Je dirais même A++ ;-)

--
Chqrlie.



Avatar
Aris
"Aris" a écrit dans le message de news:
47406762$0$29541$
In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);
Euh, le cast en question, c'est la bibliotheque C qui est censee le

faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...
de manière générale, jamais faire de cast explicite là où le cast

implicite fonctionne. C'est la porte ouverte à des conversions invalides
qui peuvent prendre des heures à débugger


Tout à fait d'accord!

Mais dans le cas de islower() et ses amis, le cast en (unsigned char) est
nécessaire si le type 'char' est signé par défaut. islower() n'est défini
que pour toutes les valeurs du type unsigned char et la valeur EOF. Lui
passer un char signé négatif viole cette contrainte, et comme cette fonction
est souvent implémentée comme une macro qui ne valide pas son argument, le
comportement indéfini peut être méchant.

Il est très instructif de regarder l'implémentation de <ctype.h> de la
Glibc. Ils utilisent une astuce DDLF pour contourner cette incohérence du
langage (char signé par défaut) et donnent ainsi un comportement défini pour
tout argument signed char *et* unsigned char en plus de EOF (qui vaut -1).
Ceci dit ils ne peuvent pas résoudre le cas de 'ÿ' qui dans l'encodage
iso-latin1 vaut 255, soit -1 en tant que char signé, et est donc
indiscernable de la valeur de EOF. Donc islower('ÿ') == 0, comme
islower(EOF), ce qui est un peu surprenant.

Moralité: avec gcc, j'utilise toujours l'option -funsigned-char

hmm ok.

mais dans ce cas, le cast n'est pas la bonne solution au problème. c'est
à la déclaration du char[] qu'il faut déclarer un unsigned char[], si
les fonctions de manipulation de texte s'attendent à de l'unsigned.

Aussi de toutes facons les caractères > 127 sont tous dépendants du
charset et ne devraient tout simplement jamais se retrouver dans un
tolower... je pense qu'unix a mis trop de temps à sortir des problèmes
d'encodage et qu'il vaut mieux éduquer directement à l'utilisation de
routines utf8/unicode si on doit traiter des chaines internationales.

évidement, c'est hors sujet pour un "bête" programme de TP :)




Avatar
Charlie Gordon
"Aris" a écrit dans le message de news:
4740b9db$0$29544$
"Aris" a écrit dans le message de news:
47406762$0$29541$
In article <473e0559$0$14273$,
Charlie Gordon wrote:
m[i] = tolower((unsigned char)m[i]);
Euh, le cast en question, c'est la bibliotheque C qui est censee le

faire en interne... du point de vue utilisateur, tolower() prend
specifiquement un int pour qu'il n'y ait pas de probleme de coercion
du caractere mal venue...
de manière générale, jamais faire de cast explicite là où le cast

implicite fonctionne. C'est la porte ouverte à des conversions invalides
qui peuvent prendre des heures à débugger


Tout à fait d'accord!

Mais dans le cas de islower() et ses amis, le cast en (unsigned char) est
nécessaire si le type 'char' est signé par défaut. islower() n'est
défini que pour toutes les valeurs du type unsigned char et la valeur
EOF. Lui passer un char signé négatif viole cette contrainte, et comme
cette fonction est souvent implémentée comme une macro qui ne valide pas
son argument, le comportement indéfini peut être méchant.

Il est très instructif de regarder l'implémentation de <ctype.h> de la
Glibc. Ils utilisent une astuce DDLF pour contourner cette incohérence
du langage (char signé par défaut) et donnent ainsi un comportement
défini pour tout argument signed char *et* unsigned char en plus de EOF
(qui vaut -1). Ceci dit ils ne peuvent pas résoudre le cas de 'ÿ' qui
dans l'encodage iso-latin1 vaut 255, soit -1 en tant que char signé, et
est donc indiscernable de la valeur de EOF. Donc islower('ÿ') == 0,
comme islower(EOF), ce qui est un peu surprenant.

Moralité: avec gcc, j'utilise toujours l'option -funsigned-char

hmm ok.

mais dans ce cas, le cast n'est pas la bonne solution au problème. c'est à
la déclaration du char[] qu'il faut déclarer un unsigned char[], si les
fonctions de manipulation de texte s'attendent à de l'unsigned.


Non, cette solution ne convient pas, parce ce que toutes les fonctions de
chaines de la lib C prennent des char * qui sont incompatibles avec unsigned
char *.

Aussi de toutes facons les caractères > 127 sont tous dépendants du
charset et ne devraient tout simplement jamais se retrouver dans un
tolower... je pense qu'unix a mis trop de temps à sortir des problèmes
d'encodage et qu'il vaut mieux éduquer directement à l'utilisation de
routines utf8/unicode si on doit traiter des chaines internationales.


Oui, et c'est pourquoi je suis outré que les fonctions (ou macros) de
<ctype.h> se mêlent de gérer la "Locale". Soit on veut une interface
efficace et bien définie sur le jeu de caractères de base (bien souvent
l'ASCII) et on pourrait utiliser ctype.h, soit il faut gérer l'encodage et
on se lance sur un terrain bien plus riche et compliqué que ce que le C
laisse imaginer avec sa gestion de la Locale simpliste et ses fonctions
multi-byte pourries. En plus la solution la plus séduisante du moment
(UTF-8) est incompatible avec ctype.h.

évidement, c'est hors sujet pour un "bête" programme de TP :)


Au contraire, le sujet peut etre developpé à loisir lors d'un TP.

--
Chqrlie.





Avatar
Antoine Leca
En news:4740b9db$0$29544$, Aris va escriure:
Aussi de toutes facons les caractères > 127 sont tous dépendants du
charset et ne devraient tout simplement jamais se retrouver dans un
tolower...


Pourquoi cela, ce n'est pas sensé fonctionner ? Ou bien tu préfères que l'on
parle tous Simple English ?

Sans compter que tu peux te retrouver avec des caractères >127 sans l'avoir
demandé au départ, il suffit d'essayer toupper('i') ou tolower('I') dans
certains cas particuliers pour générer des ribambelles de magnifiques
soucis.


je pense qu'unix a mis trop de temps à sortir des problèmes
d'encodage et qu'il vaut mieux éduquer directement à l'utilisation de
routines utf8/unicode si on doit traiter des chaines internationales.


Ahem. Tu fais comment, dans un programme supposé portable, pour utiliser les
« routines utf8/unicode » ?
Encore un supporteur de ISO 15435 ?
Ou tu veux forcer l'implémentation de ICU sur toutes les machines ?


Antoine

Avatar
Jean-Marc Bourguet
Aris writes:

mais dans ce cas, le cast n'est pas la bonne solution au problème. c'est à
la déclaration du char[] qu'il faut déclarer un unsigned char[],


On peut arguer que char devrait être non signé (Charlie a l'air de se
limiter aux impléméntations de ce type -- ce qui n'est pas totalement
absurde considérant que gcc permet de faire de qu'on veut), mais il faut
tenir compte de l'histoire. Mais proposer l'utilisation systématique de
unsigned char pour le traitement des caractères comme tu le fais pose
quelque problèmes pratiques... quels sont les fonctions qui traitent des
unsigned char?

si les fonctions de manipulation de texte s'attendent à de l'unsigned.


Non, uniquement celle prenant un seul caractère (et admettant en plus EOF
comme valeur possible).

Aussi de toutes facons les caractères > 127 sont tous dépendants du charset


EBCDIC n'est pourtant pas mort. (Tu aurais écrit <0, les choses auraient
été différentes)

et ne devraient tout simplement jamais se retrouver dans un tolower...


Je ne comprends pas pourquoi, même hors EBCDIC.

je pense qu'unix a mis trop de temps à sortir des problèmes d'encodage et
qu'il vaut mieux éduquer directement à l'utilisation de routines
utf8/unicode si on doit traiter des chaines internationales.


Tu peux m'indiquer avec quelle API standard?

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Antoine Leca
En news:, Jean-Marc Bourguet va escriure:
Aussi de toutes facons les caractères > 127 sont tous dépendants du
charset


EBCDIC n'est pourtant pas mort.


Faux problème : avec EBCDIC tu es obligé d'avoir char non signé, et le
problème disparait complètement.

Mais bon, si c'est pour dire que si isascii() ne fait pas partie de la norme
C, c'est qu'il doit y avoir une raison, je suis tout-à-fait d'accord avec
toi :-)


Antoine


1 2 3 4 5