int variant_init(variant * v, const char * s)
{
memset(v, ' ', sizeof *v) ;
v->size = strlen(s) ;
Problème potentiel lorsque strlen() retourne une valeur supérieure à
UNIT_MAX (en supposant par exemple que size_t est un type plus grand
que unsigned.)
Je suppose que tu voulais dire UINT_MAX.
Mais est-ce que je suppose mal de considérer size_t comme un
unsigned int ?
Où size_t est à la discretion de l'implémentation est n'est pas
inscrit dans le marbre normatif ?
*(next+pos) = step & 1 << pos ? toupper(first->str[pos]) :
Bzzz. str est un char*, str[pos] est éventuellement signé ;
toupper() attend un int avec soit la valeur EOF, soit une valeur
représentable comme unsigned char. Bisbille.
Le mieux est d'utiliser des unsigned char partout dans ton programme
(et d'expliquer pourquoi).
Effectivement, c'est ce que dit le man. Je n'avais même pas fait
attention à ce qu'il attende un entier. C'est d'ailleurs bizarre.
Pourquoi attend-il un entier alors que les chaînes ASCII sont stockées
dans des tableaux de char ?
int variant_init(variant * v, const char * s)
{
memset(v, ' ', sizeof *v) ;
v->size = strlen(s) ;
Problème potentiel lorsque strlen() retourne une valeur supérieure à
UNIT_MAX (en supposant par exemple que size_t est un type plus grand
que unsigned.)
Je suppose que tu voulais dire UINT_MAX.
Mais est-ce que je suppose mal de considérer size_t comme un
unsigned int ?
Où size_t est à la discretion de l'implémentation est n'est pas
inscrit dans le marbre normatif ?
*(next+pos) = step & 1 << pos ? toupper(first->str[pos]) :
Bzzz. str est un char*, str[pos] est éventuellement signé ;
toupper() attend un int avec soit la valeur EOF, soit une valeur
représentable comme unsigned char. Bisbille.
Le mieux est d'utiliser des unsigned char partout dans ton programme
(et d'expliquer pourquoi).
Effectivement, c'est ce que dit le man. Je n'avais même pas fait
attention à ce qu'il attende un entier. C'est d'ailleurs bizarre.
Pourquoi attend-il un entier alors que les chaînes ASCII sont stockées
dans des tableaux de char ?
int variant_init(variant * v, const char * s)
{
memset(v, ' ', sizeof *v) ;
v->size = strlen(s) ;
Problème potentiel lorsque strlen() retourne une valeur supérieure à
UNIT_MAX (en supposant par exemple que size_t est un type plus grand
que unsigned.)
Je suppose que tu voulais dire UINT_MAX.
Mais est-ce que je suppose mal de considérer size_t comme un
unsigned int ?
Où size_t est à la discretion de l'implémentation est n'est pas
inscrit dans le marbre normatif ?
*(next+pos) = step & 1 << pos ? toupper(first->str[pos]) :
Bzzz. str est un char*, str[pos] est éventuellement signé ;
toupper() attend un int avec soit la valeur EOF, soit une valeur
représentable comme unsigned char. Bisbille.
Le mieux est d'utiliser des unsigned char partout dans ton programme
(et d'expliquer pourquoi).
Effectivement, c'est ce que dit le man. Je n'avais même pas fait
attention à ce qu'il attende un entier. C'est d'ailleurs bizarre.
Pourquoi attend-il un entier alors que les chaînes ASCII sont stockées
dans des tableaux de char ?
En news:473b1123$0$27287$, Mickaël Wolff va
escriure:
[Utiliser des unsigned char * quand on fait appel à <ctype.h>]
Effectivement, c'est ce que dit le man. Je n'avais même pas fait
attention à ce qu'il attende un entier. C'est d'ailleurs bizarre.
Pourquoi attend-il un entier alors que les chaînes ASCII sont
stockées dans des tableaux de char ?
Parce que les Américains ne voient pas la différence de toute façon,
parce que les char signés cela ne concernait au départ que les PDP-11
des Américains (les machines IBM avaient des chars non signés du fait
de l'EBCDIC), et parce que comme c'est *nix qui a les préférences des
gens chargés à la fois de la normalisation et du compilateur de
référence (GCC pour le moment), par défaut char est souvent signé.
Au résultat, patatras.
En news:473b1123$0$27287$426a74cc@news.free.fr, Mickaël Wolff va
escriure:
[Utiliser des unsigned char * quand on fait appel à <ctype.h>]
Effectivement, c'est ce que dit le man. Je n'avais même pas fait
attention à ce qu'il attende un entier. C'est d'ailleurs bizarre.
Pourquoi attend-il un entier alors que les chaînes ASCII sont
stockées dans des tableaux de char ?
Parce que les Américains ne voient pas la différence de toute façon,
parce que les char signés cela ne concernait au départ que les PDP-11
des Américains (les machines IBM avaient des chars non signés du fait
de l'EBCDIC), et parce que comme c'est *nix qui a les préférences des
gens chargés à la fois de la normalisation et du compilateur de
référence (GCC pour le moment), par défaut char est souvent signé.
Au résultat, patatras.
En news:473b1123$0$27287$, Mickaël Wolff va
escriure:
[Utiliser des unsigned char * quand on fait appel à <ctype.h>]
Effectivement, c'est ce que dit le man. Je n'avais même pas fait
attention à ce qu'il attende un entier. C'est d'ailleurs bizarre.
Pourquoi attend-il un entier alors que les chaînes ASCII sont
stockées dans des tableaux de char ?
Parce que les Américains ne voient pas la différence de toute façon,
parce que les char signés cela ne concernait au départ que les PDP-11
des Américains (les machines IBM avaient des chars non signés du fait
de l'EBCDIC), et parce que comme c'est *nix qui a les préférences des
gens chargés à la fois de la normalisation et du compilateur de
référence (GCC pour le moment), par défaut char est souvent signé.
Au résultat, patatras.
En news:473ad468$0$25918$, Vincent Guichard va
escriure:void PrintSolutionN(char * mot, int len, long index)
Pourquoi un long pour index ?
sol[i] = toupper(mot[i]);
:-( (cf. autres messages)
int N = strlen(mot);
:-(
long total = 1<<N;
Pourquoi un long ici ?
int index;
... et un int ici (alors même que le prototype de PrintSolutionsN attend
un
long pour index).
printf("Analyse pour %s: %ld solutions.n", mot, total);
for(index=0; index < total; index++)
Avec un mot de 15 lettres, total peut valoir INT_MIN (surprise) et cela va
faire une boucle infinie.
Avec un mot de 16 lettres ou plus, total peut valoir 0, donc l'algorithme
va
faire les 32768 premières possibilités (jusque là OK), index va passer de
INT_MAX à INT_MIN (ou bien erreur de débordement) et donc s'arrêter là.
Si tu as des int de 32 bits, les limites sont plus loin mais les
comportements sont les mêmes avec des mots de 31 ou 32+ lettres.
En news:473ad468$0$25918$ba4acef3@news.orange.fr, Vincent Guichard va
escriure:
void PrintSolutionN(char * mot, int len, long index)
Pourquoi un long pour index ?
sol[i] = toupper(mot[i]);
:-( (cf. autres messages)
int N = strlen(mot);
:-(
long total = 1<<N;
Pourquoi un long ici ?
int index;
... et un int ici (alors même que le prototype de PrintSolutionsN attend
un
long pour index).
printf("Analyse pour %s: %ld solutions.n", mot, total);
for(index=0; index < total; index++)
Avec un mot de 15 lettres, total peut valoir INT_MIN (surprise) et cela va
faire une boucle infinie.
Avec un mot de 16 lettres ou plus, total peut valoir 0, donc l'algorithme
va
faire les 32768 premières possibilités (jusque là OK), index va passer de
INT_MAX à INT_MIN (ou bien erreur de débordement) et donc s'arrêter là.
Si tu as des int de 32 bits, les limites sont plus loin mais les
comportements sont les mêmes avec des mots de 31 ou 32+ lettres.
En news:473ad468$0$25918$, Vincent Guichard va
escriure:void PrintSolutionN(char * mot, int len, long index)
Pourquoi un long pour index ?
sol[i] = toupper(mot[i]);
:-( (cf. autres messages)
int N = strlen(mot);
:-(
long total = 1<<N;
Pourquoi un long ici ?
int index;
... et un int ici (alors même que le prototype de PrintSolutionsN attend
un
long pour index).
printf("Analyse pour %s: %ld solutions.n", mot, total);
for(index=0; index < total; index++)
Avec un mot de 15 lettres, total peut valoir INT_MIN (surprise) et cela va
faire une boucle infinie.
Avec un mot de 16 lettres ou plus, total peut valoir 0, donc l'algorithme
va
faire les 32768 premières possibilités (jusque là OK), index va passer de
INT_MAX à INT_MIN (ou bien erreur de débordement) et donc s'arrêter là.
Si tu as des int de 32 bits, les limites sont plus loin mais les
comportements sont les mêmes avec des mots de 31 ou 32+ lettres.
Bonjour,
si la récursion n'est pas le thème du devoir, tu peux aussi compter de 0 à
2^N-1 et mettre une majuscule à l'emplacement i du mot lorsque le bit i de
l'index est à 1 et une minuscule lorsqu'il est à 0.
Bonjour,
si la récursion n'est pas le thème du devoir, tu peux aussi compter de 0 à
2^N-1 et mettre une majuscule à l'emplacement i du mot lorsque le bit i de
l'index est à 1 et une minuscule lorsqu'il est à 0.
Bonjour,
si la récursion n'est pas le thème du devoir, tu peux aussi compter de 0 à
2^N-1 et mettre une majuscule à l'emplacement i du mot lorsque le bit i de
l'index est à 1 et une minuscule lorsqu'il est à 0.
void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]
free(sol);
}
void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]
free(sol);
}
void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]
free(sol);
}
In article <473c97d8$0$12488$,
Charlie Gordon wrote:void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
In article <473c97d8$0$12488$426a74cc@news.free.fr>,
Charlie Gordon <news@chqrlie.org> wrote:
void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]
free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
In article <473c97d8$0$12488$,
Charlie Gordon wrote:void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
"Marc Espie" a écrit dans le message de news:
fhi805$2goe$In article <473c97d8$0$12488$,
Charlie Gordon wrote:void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
strdup n'est pas standard mais elle est portable : c'est une fonction Posix
qu'il est trivial de reimplementer sur les plateformes ou elle n'est pas
disponible:
char *strdup(const char *str) {
size_t size;
char *p;
if (!str)
return NULL;
size = strlen(str) + 1;
p = malloc(size);
if (!p)
return NULL;
return memcpy(p, str, size);
}
C'est un tel scandale que l'ANSI, puis l'ISO n'aient pas inclus cette
fonction dans la libc que je refuse de cesser de l'utiliser alors que
pratiquement toutes les plateformes la supportent. Bien sur M$ l'affuble
d'un underscore initial aussi stupide que laid, mais c'est bien coherent
avec le reste de leur environnmement.
"Marc Espie" <espie@lain.home> a écrit dans le message de news:
fhi805$2goe$1@biggoron.nerim.net...
In article <473c97d8$0$12488$426a74cc@news.free.fr>,
Charlie Gordon <news@chqrlie.org> wrote:
void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]
free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
strdup n'est pas standard mais elle est portable : c'est une fonction Posix
qu'il est trivial de reimplementer sur les plateformes ou elle n'est pas
disponible:
char *strdup(const char *str) {
size_t size;
char *p;
if (!str)
return NULL;
size = strlen(str) + 1;
p = malloc(size);
if (!p)
return NULL;
return memcpy(p, str, size);
}
C'est un tel scandale que l'ANSI, puis l'ISO n'aient pas inclus cette
fonction dans la libc que je refuse de cesser de l'utiliser alors que
pratiquement toutes les plateformes la supportent. Bien sur M$ l'affuble
d'un underscore initial aussi stupide que laid, mais c'est bien coherent
avec le reste de leur environnmement.
"Marc Espie" a écrit dans le message de news:
fhi805$2goe$In article <473c97d8$0$12488$,
Charlie Gordon wrote:void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
strdup n'est pas standard mais elle est portable : c'est une fonction Posix
qu'il est trivial de reimplementer sur les plateformes ou elle n'est pas
disponible:
char *strdup(const char *str) {
size_t size;
char *p;
if (!str)
return NULL;
size = strlen(str) + 1;
p = malloc(size);
if (!p)
return NULL;
return memcpy(p, str, size);
}
C'est un tel scandale que l'ANSI, puis l'ISO n'aient pas inclus cette
fonction dans la libc que je refuse de cesser de l'utiliser alors que
pratiquement toutes les plateformes la supportent. Bien sur M$ l'affuble
d'un underscore initial aussi stupide que laid, mais c'est bien coherent
avec le reste de leur environnmement.
In article <473cadc3$0$26500$,
Charlie Gordon wrote:"Marc Espie" a écrit dans le message de news:
fhi805$2goe$In article <473c97d8$0$12488$,
Charlie Gordon wrote:void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
strdup n'est pas standard mais elle est portable : c'est une fonction
Posix
qu'il est trivial de reimplementer sur les plateformes ou elle n'est pas
disponible:
char *strdup(const char *str) {
size_t size;
char *p;
if (!str)
return NULL;
YUCK
Grosse connerie: un pointeur nul n'est PAS une chaine valide.
Toutes les implementations qui `verifient' les pointeurs et essaient
de faire un truc sense avec en presence d'un pointeur nul ont le gros
defaut de permettre l'ecriture de code non portable (j'ai deja corrige
du code linux qui segfaultait ailleurs grace a un strcmp(NULL,
"qqchose") )
size = strlen(str) + 1;
p = malloc(size);
if (!p)
return NULL;
return memcpy(p, str, size);
}
C'est un tel scandale que l'ANSI, puis l'ISO n'aient pas inclus cette
fonction dans la libc que je refuse de cesser de l'utiliser alors que
pratiquement toutes les plateformes la supportent. Bien sur M$ l'affuble
d'un underscore initial aussi stupide que laid, mais c'est bien coherent
avec le reste de leur environnmement.
Je ne suis pas d'accord avec toi. strdup pose de reels petits problemes
de portabilite. C'est une des rares fonctions qui melange allocation
memoire et manipulation de chaines... elle a aussi le gros defaut
d'avoir un flou artistique sur la fonction d'allocation memoire utilisee.
En particulier, je connais des implementations qui utilisent malloc()
en C et new en C++...D'ou big probleme avec le free() resultant.
Pour pouvoir l'inclure dansla norme, il aurait fallu que cette fonction
soit non-ambigue.
Ce qui n'est pas trop comprehensible, c'est qu'on n'ait pas dans la
norme une fonction de nom similaire et possedant une semantique bien
definie... apres tout, ils ne se sont pas genes pour index -> strchr.
Enfin si, je vois une semie- bonne raison: les fonctions de string.h sont
(globalement) valables pour les implementations `freestanding', tandis
que malloc(), non...
In article <473cadc3$0$26500$426a74cc@news.free.fr>,
Charlie Gordon <news@chqrlie.org> wrote:
"Marc Espie" <espie@lain.home> a écrit dans le message de news:
fhi805$2goe$1@biggoron.nerim.net...
In article <473c97d8$0$12488$426a74cc@news.free.fr>,
Charlie Gordon <news@chqrlie.org> wrote:
void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]
free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
strdup n'est pas standard mais elle est portable : c'est une fonction
Posix
qu'il est trivial de reimplementer sur les plateformes ou elle n'est pas
disponible:
char *strdup(const char *str) {
size_t size;
char *p;
if (!str)
return NULL;
YUCK
Grosse connerie: un pointeur nul n'est PAS une chaine valide.
Toutes les implementations qui `verifient' les pointeurs et essaient
de faire un truc sense avec en presence d'un pointeur nul ont le gros
defaut de permettre l'ecriture de code non portable (j'ai deja corrige
du code linux qui segfaultait ailleurs grace a un strcmp(NULL,
"qqchose") )
size = strlen(str) + 1;
p = malloc(size);
if (!p)
return NULL;
return memcpy(p, str, size);
}
C'est un tel scandale que l'ANSI, puis l'ISO n'aient pas inclus cette
fonction dans la libc que je refuse de cesser de l'utiliser alors que
pratiquement toutes les plateformes la supportent. Bien sur M$ l'affuble
d'un underscore initial aussi stupide que laid, mais c'est bien coherent
avec le reste de leur environnmement.
Je ne suis pas d'accord avec toi. strdup pose de reels petits problemes
de portabilite. C'est une des rares fonctions qui melange allocation
memoire et manipulation de chaines... elle a aussi le gros defaut
d'avoir un flou artistique sur la fonction d'allocation memoire utilisee.
En particulier, je connais des implementations qui utilisent malloc()
en C et new en C++...D'ou big probleme avec le free() resultant.
Pour pouvoir l'inclure dansla norme, il aurait fallu que cette fonction
soit non-ambigue.
Ce qui n'est pas trop comprehensible, c'est qu'on n'ait pas dans la
norme une fonction de nom similaire et possedant une semantique bien
definie... apres tout, ils ne se sont pas genes pour index -> strchr.
Enfin si, je vois une semie- bonne raison: les fonctions de string.h sont
(globalement) valables pour les implementations `freestanding', tandis
que malloc(), non...
In article <473cadc3$0$26500$,
Charlie Gordon wrote:"Marc Espie" a écrit dans le message de news:
fhi805$2goe$In article <473c97d8$0$12488$,
Charlie Gordon wrote:void print_word_case(const char *mot, unsigned long mask)
{
char *sol = strdup(mot);
[...]free(sol);
}
Je suis surpris, d'habitude tu utilises des fonctions portables, ce
que strdup n'est pas...
strdup n'est pas standard mais elle est portable : c'est une fonction
Posix
qu'il est trivial de reimplementer sur les plateformes ou elle n'est pas
disponible:
char *strdup(const char *str) {
size_t size;
char *p;
if (!str)
return NULL;
YUCK
Grosse connerie: un pointeur nul n'est PAS une chaine valide.
Toutes les implementations qui `verifient' les pointeurs et essaient
de faire un truc sense avec en presence d'un pointeur nul ont le gros
defaut de permettre l'ecriture de code non portable (j'ai deja corrige
du code linux qui segfaultait ailleurs grace a un strcmp(NULL,
"qqchose") )
size = strlen(str) + 1;
p = malloc(size);
if (!p)
return NULL;
return memcpy(p, str, size);
}
C'est un tel scandale que l'ANSI, puis l'ISO n'aient pas inclus cette
fonction dans la libc que je refuse de cesser de l'utiliser alors que
pratiquement toutes les plateformes la supportent. Bien sur M$ l'affuble
d'un underscore initial aussi stupide que laid, mais c'est bien coherent
avec le reste de leur environnmement.
Je ne suis pas d'accord avec toi. strdup pose de reels petits problemes
de portabilite. C'est une des rares fonctions qui melange allocation
memoire et manipulation de chaines... elle a aussi le gros defaut
d'avoir un flou artistique sur la fonction d'allocation memoire utilisee.
En particulier, je connais des implementations qui utilisent malloc()
en C et new en C++...D'ou big probleme avec le free() resultant.
Pour pouvoir l'inclure dansla norme, il aurait fallu que cette fonction
soit non-ambigue.
Ce qui n'est pas trop comprehensible, c'est qu'on n'ait pas dans la
norme une fonction de nom similaire et possedant une semantique bien
definie... apres tout, ils ne se sont pas genes pour index -> strchr.
Enfin si, je vois une semie- bonne raison: les fonctions de string.h sont
(globalement) valables pour les implementations `freestanding', tandis
que malloc(), non...
Complément à la réponse d'hier soir que j'ai écrit en courant.
Le résultat global n'est pas très cohérent, et c'est bien la conclusion à
laquelle Mickaël était arrivé.
Complément à la réponse d'hier soir que j'ai écrit en courant.
Le résultat global n'est pas très cohérent, et c'est bien la conclusion à
laquelle Mickaël était arrivé.
Complément à la réponse d'hier soir que j'ai écrit en courant.
Le résultat global n'est pas très cohérent, et c'est bien la conclusion à
laquelle Mickaël était arrivé.