OVH Cloud OVH Cloud

conversion int vers string

47 réponses
Avatar
sebosac
salut,

je cherche a convertir un int en string:


<stdlib.h>

char string[255];


itoa(1664,&string,10);



mais le compilateur me dit qu'il ne peut linker car le symbole _itoa n'existe pas.


il y aurais t'il une autre solution ?

merci

10 réponses

1 2 3 4 5
Avatar
Charlie Gordon
"Antoine Leca" wrote in message
news:cmd284$rde$
En cmctic$7ft$, Charlie Gordon va escriure:
A ce propos, je me souviens avoir optimisé en 1991 à Cambridge le
driver Postscript de Lotus 1-2-3.


Jolie anecdote.

plus de 90% du temps passé était concentré dans une seule routine qui
convertissait en chaines de caractères en base 10 des nombres entiers


Tu ramènes de l'eau à mon moulin, là: par rapport à itoa qui est censé gérer
toutes les bases, sprintf est «prévenu» de la base à utiliser, donc peut
optimiser à part la base 10 (ou 16).
;-)

Après, c'est un problème de qualité d'implémentation: c'est évident que si
tu as un problème de perf' et que la routine de conversion numérique vers
texte intégrée dans xprintf() fait la division « à la main » (et si en plus
elle doit gérer les objets sur 64 ou 128 bits avec le même chemin... sans
commentaire)

pour la plupart constants.


Tu as des chiffres sur l'impact de traiter à part les constantes (courantes)
? Je suppose que ce doit être important, mais les faits sont meilleurs que
les suppositions...


Ils avaient effectivement mis toutes les chances de leur côté pour que ce soit
lent : 10 était bien un paramètre. Le driver était truffé d'appels du style :

outnum(1000, 10);
outchar(' ');
outnum(1000, 10);
outstr(" moveto");

Le passage à :

outstr("1000 1000 moveto");

gagnait sur tous les plans.
faire les autres conversions en base 10 uniquement et avec des divisions
permettait encore de un facteur entier tellement l'implementation originale
était lente ;-)

Chqrlie.

PS: L'équipe n'était pas particulièrement douée, il m'a fallu expliquer
longuement pourquoi des lignes comme celles-ci étaient ridicules, bien qu'elles
ne causassent en général pas de problème :

if (*arg == '/' && strncmp(&arg[1], "n", sizeof("n")) == 0) {
/* process /n command line option */
}
...
buf[strlen(buf)] = ''; /* prevent buffer overflow */


Avatar
Charlie Gordon
"Antoine Leca" wrote in message
news:cm8h2i$u3q$
avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.




Si tu passes tous les paramètres équivalents à ceux de strtol à _ltostr,
plus ceux pour gérer la chaîne et son allocation, tu va finir avec une
syntaxe plutôt lourde, tu ne crois pas ?


int ltostr(long n, char *buf, int size, int base);

qui retournerait si le resultat de la conversion tient dans le buffer. est-ce
si lourd ?

Par exemple putc(c,fp) me semble plus efficace que fprintf(fp, "%c", c);


Oui. Et je me demande ce qu'il en est pour puts("ma chaine:", fp),
puts(chaine, fp), putc('n', fp); par rapport au fprintf équivalent.
Mais cela n'a pas grand chose à voir avec le sujet.


Tu veux certainement parler de fputs() ?

Ce qui est regrettable dans itoa, c'est que la taille du tableau
résultat n'est pas spécifiée dans l'appel, avec les problèmes de
débordement de tableaux que cela peut poser si le programmeur est peu
méfiant ou que la taille des types entiers change au delà de ses
attentes.


Ça, c'est l'argument massue pour ne PAS normaliser itoa(). gets()a réussi à
rester parce qu'il y avait à côté un moyen simple d'éviter les débordements.
En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
calcul de la longueur de la chaîne en fonction des propriétés des types
entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
anecdotique, sans parler de la lourdeur.


Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à l'époque
une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
aurait dû conduire à exclure gets() de la norme ANSI.
contrairement à gets(), il est relativement simple d'éviter les débordements
avec itoa() en allouant un buffer destination suffisamment grand (tant pis pour
les architectures ou les entiers font plus de 64 bits ;-)


Et je ne vois pas en quoi itoa() peut-être plus efficace vu que les
opérations utilisées seront les mêmes que snprintf() à part
l'allocation mémoire initiale de itoa().


parce que snprintf finira par appeler la fonction que je me propose
d'appeler directement.


Chez moi, cette fonction est snprintf elle-même (en fait, vfprintf avec un
FILE spécial).


Chez moi aussi, d'ailleurs sprintf et snprintf ont exactement le même surcoût,
et sont quand même considérablement plus lourdes que itoa :

snprintf() fait dans l'ordre:

construction d'un FILE spécial
appel de vfprintf avec une va_list
vfprintf parse la chaine de format en y cherchant % avec une méthode efficace
pour de longues chaines, mais lourde quand c'est le premier caractère.
ensuite il faut parser la syntaxe générale des formats de printf, avec tous les
flags et champs de controle
puis dispatcher sur le handler correspondant à 'd', pas très efficace tout cela.
Puis on commence à formater avec en l'occurrence une routine bien plus
compliquée que itoa, puisqu'elle doit potentiellement tenir compte de toutes les
options sus-nommées.
Et enfin on recopie la chaine résultante en tenant compte des options de cadrage
et en verifiant l'overflow potentiel (snprintf)
Il reste encore a essayer de continuer la chaine de format (ouf elle est finie)
On revient, on revient...
Et enfin on a fini.

N'importe quel programmeur expérimenté verra que c'est plus lourd que
l'implémentation de itoa, sauf peut-être dans des librairies particulièrement
simplistes et qu'il vaudrait mieux éviter, ou réécrire partiellement.

[...]
d'un autre côté tu vas trouver des implémentations de
itoa() qui appelent sprintf() ;-) (de la même manière qu'aujourd'hui, c'est
en général vain d'essayer de gagner du temps en utilisant atoi())
Si tu es vraiment juste sur les perfs de cette partie, tu ne vas pas couper
de réécrire cela toi-même.


Oui, voir ci-dessus.

Enfin, par expérience les programmes qui génèrent des chaînes de caractères
ne le font pas pour faire joli, ils finissent par ranger ces chaînes quelque
part, dans un fichier ou dans un socket, donc ils finissent par être limités
par le débit des entrées-sorties (OK, cela fait un bail que je n'ai pas
programmé sur un processeur plus lent que son contrôleur d'E/S, même si je
sais que cela existe encore, surtout en C).


C'est un a priori pas toujours justifié !
Avec des considérations comme cela, tu justifies tous les abus.
On peut aussi invoquer la loi de Moore : de toute façon, ça sert plus à rien
d'écrire du code efficace, les processeurs sont tellement rapides ! A quoi bon
faire des free() : aujourd'hui la mémoire est si abondante et bon marché...

Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les bécanes
Unix (plus précisement, sur V7).


En fait, c'est plus subtil que cela : la fonction itoa est un exemple de boucle
do/while dans le Kernighan et Ritchie de 1978, contemporain de V7. La version
proposée est d'ailleurs beuguée pour le cas de INT_MIN :

void itoa(int n, char s[])

int i, sign;

if ((sign = n) < 0) /* record sign */
n = -1; /* make n positive */

i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while (n /= 10); /* delete it */
if (sign < 0)
s[i++] = '-';

s[i] = '';
reverse(s);
}

void reverse(char s[]) {
int c, i, j;
for ( i = 0, j = strlen(s)-1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

Heureusement que i et j sont des int et non des size_t comme strlen() !

Chqrlie.

PS: show me a do/while loop, I'll show you a bug.




Avatar
Gabriel Dos Reis
"Charlie Gordon" writes:

[...]

| > En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
| > équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
| > calcul de la longueur de la chaîne en fonction des propriétés des types
| > entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
| > anecdotique, sans parler de la lourdeur.
|
| Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à l'époque
| une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
| aurait dû conduire à exclure gets() de la norme ANSI.

Je crois que tu fais l'erreur colossale de croire que la norme était
écrite pour ne contenir que des choses « non bugguées ».
Certains aiment à dire que la charte du comité ANSI était de codifier
la partique existante, alors ... -- mais, en réalité c'est pas vrai,
le comité a fait mal d'inventions, y compris l'infame void* -> T*
et volatile.

-- Gaby
Avatar
Charlie Gordon
"Gabriel Dos Reis" wrote in message
news:
"Charlie Gordon" writes:

[...]

| > En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
| > équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
| > calcul de la longueur de la chaîne en fonction des propriétés des types
| > entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
| > anecdotique, sans parler de la lourdeur.
|
| Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à
l'époque

| une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
| aurait dû conduire à exclure gets() de la norme ANSI.

Je crois que tu fais l'erreur colossale de croire que la norme était
écrite pour ne contenir que des choses « non bugguées ».
Certains aiment à dire que la charte du comité ANSI était de codifier
la partique existante, alors ... -- mais, en réalité c'est pas vrai,
le comité a fait mal d'inventions, y compris l'infame void* -> T*
et volatile.


Erreur colossale ???
Ils ont fait des ajouts remarquables comme le prototypage des fonctions.
C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
certaines saletés qui polluent encore la libc.

Chqrlie.

Avatar
Gabriel Dos Reis
"Charlie Gordon" writes:

| "Gabriel Dos Reis" wrote in message
| news:
| > "Charlie Gordon" writes:
| >
| > [...]
| >
| > | > En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
| > | > équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
| > | > calcul de la longueur de la chaîne en fonction des propriétés des types
| > | > entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
| > | > anecdotique, sans parler de la lourdeur.
| > |
| > | Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à
| l'époque
| > | une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
| > | aurait dû conduire à exclure gets() de la norme ANSI.
| >
| > Je crois que tu fais l'erreur colossale de croire que la norme était
| > écrite pour ne contenir que des choses « non bugguées ».
| > Certains aiment à dire que la charte du comité ANSI était de codifier
| > la partique existante, alors ... -- mais, en réalité c'est pas vrai,
| > le comité a fait mal d'inventions, y compris l'infame void* -> T*
| > et volatile.
|
| Erreur colossale ???
| Ils ont fait des ajouts remarquables comme le prototypage des fonctions.

Qu'ils ont piqué à C with Classes, mais évidemment comme à chaque fois,
avec des variations douteuses.

| C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
| certaines saletés qui polluent encore la libc.

Du genre ?

-- Gaby
Avatar
Charlie Gordon
"Gabriel Dos Reis" wrote in message
news:
| C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
| certaines saletés qui polluent encore la libc.

Du genre ?


Ce ping pong tient de l'élevage de trolls ;-)

gets, strtok, strncpy, strncat...

Chqrlie.

Avatar
Gabriel Dos Reis
"Charlie Gordon" writes:

| "Gabriel Dos Reis" wrote in message
| news:
| > | C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
| > | certaines saletés qui polluent encore la libc.
| >
| > Du genre ?
|
| Ce ping pong tient de l'élevage de trolls ;-)

Tes performances en ce domaine sont plutôt remarquables ; as-tu des
subventions de l'U.E. ?

| gets, strtok, strncpy, strncat...

Ah bon.

-- Gaby
Avatar
Antoine Leca
En cmgg25$srs$, Charlie Gordon va escriure:
"Antoine Leca" wrote in message
news:cm8h2i$u3q$
avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.




Si tu passes tous les paramètres équivalents à ceux de strtol à
_ltostr, plus ceux pour gérer la chaîne et son allocation, tu va
finir avec une syntaxe plutôt lourde, tu ne crois pas ?


int ltostr(long n, char *buf, int size, int base);

qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?


Ta solution impose d'avoir alloué la chaîne avant l'appel. Donc, cela
revient exactement à snprintf, il n'y a pas réellement d'avantage si ce
n'est la possible rapidité (pas garantie) et le fait de traiter les bases
exotiques (et tu sais ce que j'en penses).
Si tu veux un équivalent de itoa() utilisable partout, il va falloir
rajouter un malloc() avant, et prévoir le free() quelque part; et là je dis
que cela devient lourd.

De plus, il manque quelques précisions:
Utilise-t-on des appels récursifs (plus rapide mais nécessite plus de pile)
ou deux passes (calcul de la longueur nécessaire puis génération des
chiffres en partant de la fin) ou un tampon intermédiaire "suffisament long"
(là encore, consome de la pile)?
Que se passe-t-il si cela ne tient pas? Rien, ou indéfini? Qu'est ce que
cela retourne? Comment recommencer?
Que se passe-t-il si n est piégé? Rien, ou indéfini? Veux-tu répéter le
problème de strtol() où il est impossible ou très difficile de savoir ce que
signifie LONG_MAX?
Quelle casse emploie-t-on? Quel jeu de chiffres quand plusieurs sont
possibles (arabe, écritures indiennes)?
Où met-on le signe? Et l'absence de signe?

Et pour finir, si tu choisis la solution simple dans tous ces cas-là, quel
est l'avantage par rapport à la version évidente programmée soi-même?


Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.


Quand?
En 1986: c'était trop tôt, fgets n'était pas encore assez connu.
http://www.lysator.liu.se/c/rat/d9.html#4-9-7-2
En 1998: peut-être que oui. Je ne sais pas si cela a été discuté.
Voir aussi
http://groups.google.com/groups?hl=xx-hacker&selm`kjle%24u9%40dfw-ixnews10
.ix.netcom.com (Doug est dans le comité)


contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)


Comment fais-tu dans le cas général si tu ne veux pas ramener la
bibliothèque mathématique au passage? Tu alloue sizeof(int) * CHAR_BIT + 2 ?


ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle


Euh? Le code est là, d'accord, mais il n'est pas utilisé: c'est un switch,
et par définition cette construction est plus efficace qu'une cascade de
if() else dans un cas comme celui-là.

Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.


C'est bien là où se passe le problème.
Si cette routine n'est pas assez efficace sur ton implémentation, tu es en
présence d'un cas classique où l'optimisation d'une fonction de bibliothèque
est nécessaire. Sommes-nous d'accord que cela peut arriver pour bien d'autre
cas? Par exemple, il est des tonnes de programmes qui se suffisent de ctime
ou strftime, mais il m'est arrivé d'écrire un programme qui avait à traiter
de grandes quantités de formattage de dates, cela n'allait pas assez vite,
alors j'ai ré-écrit ma propre version dans mon cas particulier (qui testait
mes cas particuliers de fuseaux horaires et années bissextiles, pas les
autres). Idem pour mbrtowc: si tu en as besoin au c½ur de ton programme, la
version standard de la bibliothèque va plus que probablement pas être
satisfaisante...

Et enfin on recopie la chaine résultante en tenant compte des options
de cadrage et en verifiant l'overflow potentiel (snprintf)


1) je vois mal où est le gain dans ton ltostr ci-dessus
2) dans l'implémentation classique de sprintf (récursive), la recopie est
gratuite; ce sont les options qui font changer ce qui est écrit (d'abord les
' ', puis le signe, puis les '0', puis les chiffres eux mêmes)

Évidemment, quand on rajoute les modificateurs $ ou ' de Posix, le panorama
change du tout au tout. Et certaines implémentations choisissent de traiter
ces cas particuliers au milieu des cas normaux, d'où plus de fonctionnalités
(pour qui?) au détriment d'une perte de performances pour le plus grand
nombre; ce qui est ÀMHA l'histoire de l'évolution de la bibliothèque C
depuis pas mal d'années. Mais j'ai divergé.


Enfin, par expérience les programmes qui génèrent des chaînes de
caractères ne le font pas pour faire joli, ils finissent par ranger
ces chaînes quelque part, dans un fichier ou dans un socket, donc
ils finissent par être limités par le débit des entrées-sorties


C'est un a priori pas toujours justifié !


Je le justifie par mon expérience qui me dit que C n'est pas le langage
idéal pour manipuler des chaînes de caractères, donc la motivation pour
créer de mouvelles fonctions de bibliothèque à cette fin est faible.


Avec des considérations comme cela, tu justifies tous les abus.


Oui; le pragmatisme permet toujours de justifier les abus si on en extrapole
l'argumentation.

On peut aussi invoquer la loi de Moore : de toute façon, ça sert plus
à rien d'écrire du code efficace, les processeurs sont tellement
rapides !


1) on m'a effectivement déjà servi cet argument; et effectivement parfois
comme excuse pour ne pas faire ce que je demandais;
2) c'est exactement l'excuse que l'on me sert pour justifier l'absence
d'optimisation à l'intérieur de sprintf, et au contraire le fait de rajouter
les options genre $ ou ' dans la même fonction de traitement; donc avec le
même argument tu justifies la nécessité d'incorporer itoa() ou un
équivalent, du fait de la déchéance des performances de sprintf...


A quoi bon faire des free() : aujourd'hui la mémoire est
si abondante et bon marché...


Je suis sensé dire quoi ? que cela reflète la sensation que l'on a en lisant
le code des systèmes d'exploitation modernes, pourtant poussé au panégyrique
?



Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les
bécanes Unix (plus précisement, sur V7).


En fait, c'est plus subtil que cela : la fonction itoa est un exemple
de boucle do/while dans le Kernighan et Ritchie de 1978, contemporain
de V7.


Démonstration directe du fait qu'elle n'était pas présente dans la
bibliothèque standard, ce qui nécessitait sa programmation à part.

La version proposée est d'ailleurs beuguée pour le cas de INT_MIN :


Où est le bogue?
Parles-tu du bogue pédagogique (cf. l'exercice qui suit), destiné à attirer
l'attention sur les cas particuliers quand on écrit des fonctions « de
bibliothèque » à usage supposément non restreint?


Heureusement que i et j sont des int et non des size_t comme strlen()


?
Avec size_t, tu n'as plus de bogue?

PS: show me a do/while loop, I'll show you a bug.


Quel est le rapport ?
Ou plus exactement, comme cet exemple est justement dans le paragraphe sur
do/while, que veux-tu démontrer là?


Antoine





Avatar
Charlie Gordon
"Antoine Leca" wrote in message
news:cmnngg$tdh$
En cmgg25$srs$, Charlie Gordon va escriure:

int ltostr(long n, char *buf, int size, int base);

qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?


Ta solution impose d'avoir alloué la chaîne avant l'appel. Donc, cela
revient exactement à snprintf, il n'y a pas réellement d'avantage si ce
n'est la possible rapidité (pas garantie) et le fait de traiter les bases
exotiques (et tu sais ce que j'en penses).


Ben oui, comme partout dans ce language ou l'allocation est à la charge du
programmeur !

Si tu veux un équivalent de itoa() utilisable partout, il va falloir
rajouter un malloc() avant, et prévoir le free() quelque part; et là je dis
que cela devient lourd.


Evidemment, mais qui parle de malloc ?

De plus, il manque quelques précisions:
Utilise-t-on des appels récursifs (plus rapide mais nécessite plus de pile)
ou deux passes (calcul de la longueur nécessaire puis génération des
chiffres en partant de la fin) ou un tampon intermédiaire "suffisament long"
(là encore, consome de la pile)?


Choix d'implémentation, ce peut d'ailleurs dépendre de l'architecture.

Que se passe-t-il si cela ne tient pas? Rien, ou indéfini? Qu'est ce que
cela retourne? Comment recommencer?


too bad, ou éventuellement ltostr peut retourner la place nécessaire (comme
snprintf)

Que se passe-t-il si n est piégé? Rien, ou indéfini? Veux-tu répéter le
problème de strtol() où il est impossible ou très difficile de savoir ce que
signifie LONG_MAX?


Le comportement de strtol sur overflow est immonde, on est d'accord là dessus.
Mais pour ltostr, je suppose que ce que tu appelles un valeur piégée de n est
LONG_MIN...
L'implémentation ne devrait se vautrer lamentablement comme l'exemple de K&R,
c'est quand même pas sorcier. veux-tu dire que snprintf ne sait pas faire ?

Quelle casse emploie-t-on? Quel jeu de chiffres quand plusieurs sont
possibles (arabe, écritures indiennes)?
Où met-on le signe? Et l'absence de signe?


Il suffit de le définir.

Et pour finir, si tu choisis la solution simple dans tous ces cas-là, quel
est l'avantage par rapport à la version évidente programmée soi-même?


Sans doute moins de bugs ;-)

Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.


Quand?
En 1986: c'était trop tôt, fgets n'était pas encore assez connu.
http://www.lysator.liu.se/c/rat/d9.html#4-9-7-2
En 1998: peut-être que oui. Je ne sais pas si cela a été discuté.
Voir aussi
http://groups.google.com/groups?hl=xx-hacker&selm`kjle%24u9%40dfw-ixnews10
.ix.netcom.com (Doug est dans le comité)


C'est lamentable. standardiser sans mise en garde, c'est encourager l'usage.
fgets() date de la première libc, gets() a été gardé pour deux raisons : il ne
prend pas de paramètre, donc plus court et plus rapide (à l'époque en tout cas)
et il supprime le 'n' que puts() ajoute. Comme fgets() n'a pas cette
sémantique, c'était déjà très confus à l'époque.

contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)


Comment fais-tu dans le cas général si tu ne veux pas ramener la
bibliothèque mathématique au passage? Tu alloue sizeof(int) * CHAR_BIT + 2 ?


Pas nécessairement, cela dépend de la base, qui est bien souvent constante.
snprintf a le même problème.

ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle


Euh? Le code est là, d'accord, mais il n'est pas utilisé: c'est un switch,
et par définition cette construction est plus efficace qu'une cascade de
if() else dans un cas comme celui-là.


Cela dépend de l'implémentation de snprintf() ...

Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.


C'est bien là où se passe le problème.
Si cette routine n'est pas assez efficace sur ton implémentation, tu es en
présence d'un cas classique où l'optimisation d'une fonction de bibliothèque
est nécessaire. Sommes-nous d'accord que cela peut arriver pour bien d'autre
cas? Par exemple, il est des tonnes de programmes qui se suffisent de ctime
ou strftime, mais il m'est arrivé d'écrire un programme qui avait à traiter
de grandes quantités de formattage de dates, cela n'allait pas assez vite,
alors j'ai ré-écrit ma propre version dans mon cas particulier (qui testait
mes cas particuliers de fuseaux horaires et années bissextiles, pas les
autres). Idem pour mbrtowc: si tu en as besoin au c½ur de ton programme, la
version standard de la bibliothèque va plus que probablement pas être
satisfaisante...


Nous sommes bien d'accord la dessus.

...

La version proposée de itoa() dans K&R est d'ailleurs beuguée
pour le cas de INT_MIN :


Où est le bogue?
Parles-tu du bogue pédagogique (cf. l'exercice qui suit), destiné à attirer
l'attention sur les cas particuliers quand on écrit des fonctions « de
bibliothèque » à usage supposément non restreint?
Heureusement que i et j sont des int et non des size_t comme strlen()
?

Avec size_t, tu n'as plus de bogue?


Oui bien sûr, celui-là est connu.
Mais il y en a un autre plus subtil dans reverse : cette fonction ne marche pas
pour des chaines de plus de INT_MAX caractères. Or à l'époque, en mode 16 bits,
c'était pas du tout impossible. Et si on corrige ce problème en changeant le
type de i et j en size_t (qui n'existait pas à l'époque), c'est sur la chaine
vide que reverse() se vautrerait.

PS: show me a do/while loop, I'll show you a bug.


Quel est le rapport ?
Ou plus exactement, comme cet exemple est justement dans le paragraphe sur
do/while, que veux-tu démontrer là?


Tu connais ma position sur les do/while... penses-tu que ce soit par hasard
qu'on ait laissé sciemment un bug auprès d'une telle boucle dans K&R ? Je pense
que cette construction est mal née, et ça se voit même dans K&R ;-)

Chqrlie.


Avatar
Gabriel Dos Reis
"Charlie Gordon" writes:

| fgets() date de la première libc,

Laquelle exactement ?

-- Gaby
1 2 3 4 5