Implementation correcte de strchr ?
Le
candide
Quel est votre avis sur cette implémentation de strchr ?
Le code :
/* Source à encoder en ISO-8859-1. */
#include <stdio.h>
#include <string.h>
char *mystrchr(const char *s, int c)
{
while ((unsigned char)*s != (unsigned char)c) {
if (*s == '\0')
return NULL;
++s;
}
return (char*)s;
}
int main(void)
{
const int e = getchar();
printf("%d %d", e, (unsigned char)e);
printf("%d %d", 'é', (unsigned char)'é');
printf("1 %s", strchr("abcdéf", 'é'));
printf("2 %s", strchr("abcdéf", e));
printf("3 %s", mystrchr("abcdéf", 'é'));
printf("4 %s", mystrchr("abcdéf", e));
return 0;
}
Le code :
/* Source à encoder en ISO-8859-1. */
#include <stdio.h>
#include <string.h>
char *mystrchr(const char *s, int c)
{
while ((unsigned char)*s != (unsigned char)c) {
if (*s == '\0')
return NULL;
++s;
}
return (char*)s;
}
int main(void)
{
const int e = getchar();
printf("%d %d", e, (unsigned char)e);
printf("%d %d", 'é', (unsigned char)'é');
printf("1 %s", strchr("abcdéf", 'é'));
printf("2 %s", strchr("abcdéf", e));
printf("3 %s", mystrchr("abcdéf", 'é'));
printf("4 %s", mystrchr("abcdéf", e));
return 0;
}

Poser une question


^^^
Pourquoi int? "char" irait, non? Ca serait cohérent avec la déclaration
de "s".
C'est pas parce que strchr veut un int qu'on est obligé de faire pareil,
surtout que le manpage dit d'ailleurs que le c est converti en char en
interne (sans précision sur le signe de char).
Si quelqu'un connait la raison sur le choix du int pour c, je suis
intéressé. J'ai rien trouvé dans les manpages là dessus.
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
A quoi servent les deux cast en unsigned? On peut pas faire avec un cast
à (char) sur c directement? (pour que *s et (char)c aient tous les deux
le même type).
sam.
EOF
Heu? Mais encore? Si j'osais (arthur :-) ) je dirais que c'est du grand
n'importe quoi. EOF c'est pour les flux, et là on est dans le monde des
chaines. Il n'y a aucun rapport entre les deux.
Il doit y avoir une autre raison. Sans compter que si on passe EOF dans
c, on se retrouve à faire (char)EOF ou (unsigned char)EOF, ce qui est
d'une bêtise sans nom.
sam (EOT)
Je suppose que dans la mesure où getc() renvoi un int (pour permettre de
renvoyer des codes d'erreurs), putc() prend également un int.
Cela peut potentiellement permettre de faire en sorte que
putchar(getc()) renvoi une erreur si getc() a lui même renvoyé une erreur.
Par extension, tout ce qui manipule des char utilisent des int (je vois
aussi memset(), dans le même genre) - enfin c'est une explication
possible ; ie. strchr(str, getchar()) ne nécessite pas de cast.
Oui.. que les fonction d'i/o utilisent EOF je n'ai pas de soucis, mais
c'est voir la présence de EOF dans une routine de manip de chaine qui
laisse perplexe.
Oui.. mais c'est une curieuse façon de coder. D'une part on se demande
l'intérêt d'éviter un cast à cet endroit là et de le repousser dans la
librairie. Et d'autre part la fin de fichier est silencieusement ignorée
et là c'est carrément moche. Il faut espérer que l'utilisateur fasse
appel à feof() avant de travailler avec ce que retourne strchr().
J'imagine assez qu'il y a des raisons historiques finalement là dessous.
Peut être datant de l'époque où l'on aimait pas le code machine produit
par les compilos quand il fallait convertir un int en char et qu'on
préférait gérer cela à sa sauce efficacement en asm dans les
bibliothèques standard.
sam.