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

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
Antoine Leca
En cmnpeq$6ue$, Charlie Gordon va escriure:
"Antoine Leca" wrote in message
news:cmnngg$tdh$
En cmgg25$srs$, Charlie Gordon va escriure:


Evidemment, mais qui parle de malloc ?


Moi, quand je disais qu'une solution packagée (comme j'avais compris que
c'était ce que l'on voulait) serait lourde.

Évidemment, si c'est un simple remplaçant de snprintf("%ld", sz, n) avec la
base en plus, cela n'est plus un problème, mais ce n'est pas non plus aussi
intéressant, ÀMHA.


Que se passe-t-il si n est piégé?



Mea culpa, ce n'est pas un problème puisque n est passé par valeur.

Mais pour ltostr, je suppose que ce que tu appelles un
valeur piégée de n est LONG_MIN...


Non, je pensais aux "trap représentations".

veux-tu dire que snprintf ne sait pas faire ?


C'est clair que dans des cas moins tordus, genre passer un int quand on
attend un unsigned (%o), sprintf a un comportement indéfini alors que l'on
pourrait en définir un sans souci majeur.


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 ;-)


;-), même si je ne suis pas persuadé qu'une fonction supplètive de sprintf
recoive le même degré d'attention que cette dernière, au moins dans les
premières années de vie du standard (voir, par exemple, les « habiles »
différences sur le comportement de snprintf et de swprintf en cas de
débordements).


C'est lamentable.


Désolé, je suis trop loin pour te prêter un mouchoir.

standardiser sans mise en garde, c'est encourager l'usage.


Peut être. En l'occurence, le bogue est tellement criant que ce n'est pas
évident. L'argument peut tenir pour strtok par exemple, mais là il y a bien
mise en garde.


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.


<NAÏF faux="oui">
Heu, si la base est bien souvent constante, pourrait-on gagner des cycles en
éliminant le paramètre ?
</NAÏF>


La version proposée de itoa() dans K&R est d'ailleurs beuguée
pour le cas de INT_MIN :
Où est le 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.


Même en base 2, cela fait un nombre de 32768 bits pour n. Même à l'époque
(!), les processeurs ne manipulaient pas des quantités de cet ordre.


Antoine



Avatar
Antoine Leca
En , Gabriel Dos Reis va escriure:
"Charlie Gordon" writes:

fgets() date de la première libc,


Laquelle exactement ?


C'est dans le <stdio.h> de V6 (75), en tous cas.

Avant V6, c'est nettement plus flou, parce que la notion d'E/S standard
n'existait pas...


Antoine


Avatar
Charlie Gordon
"Antoine Leca" wrote in message
news:cmo08h$1h9$
En cmnpeq$6ue$, Charlie Gordon va escriure:

Evidemment, mais qui parle de malloc ?


Moi, quand je disais qu'une solution packagée (comme j'avais compris que
c'était ce que l'on voulait) serait lourde.


oui, et cela sortirait du cadre de la libc.
Dommage, parce que un langage qui aurait la syntaxe et la sémantique du C, mais
qui aurait des chaines dynamique, des tableaux multidimensionnels variables, une
gestion de la mémoire automatique, des types extensibles ou generiques, une
large bibliothèque de support, mais dont les pointeurs seraient contrôlés...
aurait beaucoup d'applications pour lesquelles C est trop lourd, et les
alternatives peu satisfaisantes.

Évidemment, si c'est un simple remplaçant de snprintf("%ld", sz, n) avec la
base en plus, cela n'est plus un problème, mais ce n'est pas non plus aussi
intéressant, ÀMHA.


pourquoi avoir ajouté strtol() alors que sscanf() fait très bien l'affaire ?
pourquoi utiliser fputs() alors que fprintf() suffit.
Pourquoi même utiliser putc(), fprintf() est tellement plus pratique.

En fait, je suis juste frustré que la cohérence n'ait pas été respectée lors du
rajout de strtol qui ne faisait pas partie de la libc.
C'est bien trop tard, le mal est fait.

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 ;-)


;-), même si je ne suis pas persuadé qu'une fonction supplètive de sprintf
recoive le même degré d'attention que cette dernière, au moins dans les
premières années de vie du standard (voir, par exemple, les « habiles »
différences sur le comportement de snprintf et de swprintf en cas de
débordements).


snprintf() a eu une vie avant la norme ;-)
Les implémentations étaient incompatibles quant à la valeur de retour en cas de
troncature.
Il a bien fallu trancher.Il y a ainsi des différences entre versions successives
de la glibc par exemple.

Il y avait 3 possibilités :
1. renvoyer le nombre de caractères effectivement écrits avant le ''.
avantage: facile à implémenter.
inconvénient: il faut une autre méthode pour détecter la troncature.
2. renvoyer le nombre de caractères qui auraient été écrits si la destination
avait été suffisamment grande.
avantage: on peut tester la troncature, et on sait combien il faudrait
allouer
inconvénient: l'implémentation est plus complexe et potentiellement plus
lente.
3. renvoyer une valeur négative pour signifier l'erreur.
avantage: facile à implémenter, facile de tester qu'il n'y a pas troncature.
inconvénient: on ne sait pas combien il faudrait allouer, on n'est même pas
sûr que le formatage partiel soit fait dans le cas de troncature, d'ailleurs on
ne sait pas quelle erreur s'est produite.

la norme dit maintenant que snprintf() fait le 2eme cas.
après tergiversations, il semble que swprintf fait finalement le 3eme cas.

C'est très regrettable de n'avoir pas unifié le comportement... J'imagine que
le souci de compatibilité avec l'existant a primé ?
Personnellement, j'ai une préférence pour le cas 2. Et l'avoir imposé pour
snprintf() fait que l'implémentation dans le cas swprintf() n'aurait pas dû être
un obstacle, puisque les algorithmes sont les mêmes... Gaby ou Antoine ont
peut-être l'explication.

standardiser sans mise en garde, c'est encourager l'usage.


Peut être. En l'occurence, le bogue est tellement criant que ce n'est pas
évident. L'argument peut tenir pour strtok par exemple, mais là il y a bien
mise en garde.


Il n'est malheureusement pas criant pour tout le monde. Surtout quand des
pontes insistent sur les cas tordus où l'utilisation de gets() est
potentiellement sûre.

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.


<NAÏF faux="oui">
Heu, si la base est bien souvent constante, pourrait-on gagner des cycles en
éliminant le paramètre ?
</NAÏF>


Eh bien oui ! dans le projet où la conversion doit être super rapide, j'utilise
une extension de gcc qui me permet de tester à la compilation si la base est
constante et égale à 10 pour générer un appel à une fonction encore plus
efficace. C'est dans un header, encadré, utilisé uniquement pour les
compilateurs qui supportent, et cela garde le code lisible et générique.

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.


Même en base 2, cela fait un nombre de 32768 bits pour n. Même à l'époque
(!), les processeurs ne manipulaient pas des quantités de cet ordre.


Oui, bien sûr. Mais dans K&R reverse() est présentée comme une fonction
générale pour les chaines de caractères, et ensuite utilisée pour
l'implémentation de itoa(). Tu as raison, ce n'est pas un problème pour itoa().

Chqrlie.



Avatar
Antoine Leca
En cmqgki$ne6$, Charlie Gordon va escriure:
snprintf() a eu une vie avant la norme ;-)


Oui, et aussi pendant la période d'incubation.

Les implémentations étaient incompatibles quant à la valeur de retour
en cas de troncature.
Il a bien fallu trancher.Il y a ainsi des différences entre versions
successives de la glibc par exemple.


Oui.


Il y avait 3 possibilités :
1. renvoyer le nombre de caractères effectivement écrits avant le
''. avantage: facile à implémenter.
inconvénient: il faut une autre méthode pour détecter la
troncature.


Pour mémoire, c'est ce que fait strftime.
Preuve que l'on peut trouver de tout au marché du C.

C'est très regrettable de n'avoir pas unifié le comportement...


Mmmmm.
Que veux-tu dire par là, sachant que strftime est « née » en 1986-7,
swprintf vers 1992 et snprintf (dans la version normalisée) en 1998?

J'imagine que le souci de compatibilité avec l'existant a primé ?


J'imagine aussi. Même si je donne un sens à existant qui n'est peut-être pas
celui auquel on penserait.

Personnellement, j'ai une préférence pour le cas 2. Et l'avoir
imposé pour snprintf() fait que l'implémentation dans le cas
swprintf() n'aurait pas dû être un obstacle, puisque les algorithmes
sont les mêmes... Gaby ou Antoine ont peut-être l'explication.


Bin oui, le calendrier: snprintf est la puînée.


<NAÏF faux="oui">
Heu, si la base est bien souvent constante, pourrait-on gagner des
cycles en éliminant le paramètre ?
</NAÏF>


Eh bien oui !


Pardon, ce n'était pas clair: si tu veux une base constante, il y a déjà
sprintf...


dans le projet où la conversion doit être super rapide,
j'utilise une extension de gcc [...]
cela garde le code lisible et générique.


Je suis le seul à trouver qu'il y a quelque chose qui cloche, là ?



Antoine


Avatar
Charlie Gordon
dans le projet où la conversion doit être super rapide,
j'utilise une extension de gcc [...]
cela garde le code lisible et générique.


Je suis le seul à trouver qu'il y a quelque chose qui cloche, là ?


Quelle mauvaise foi !
Tu vires mes explications : dans un header, je teste si telle ou telle
optimisation est possible dans l'environnement de compilation avec des #ifdef.
Et dans le code il n'y a que des ltostr.
Dans un autre module, il y a une implementation de ltostr, ltostr10 et je passe
sur les autres optimisations.

generique : utilise le meme fonction
lisible : simple a comprendre en lisant

Chqrlie.


Avatar
Antoine Leca
En cmtde2$buq$, Charlie Gordon va escriure:
dans le projet où la conversion doit être super rapide,
j'utilise une extension de gcc [...]
cela garde le code lisible et générique.


Je suis le seul à trouver qu'il y a quelque chose qui cloche, là ?


Quelle mauvaise foi !


Non, c'est toi qui n'a pas compris mon propos.
J'ai coupé tes explications, non pas pour te prendre en défaut (ce qui
serait effectivement de la mauvaise foi), mais parce que tu arrives à une
solution à ton problème (fort bien), mais ensuite tu présentes la dite
solution comme étant générique.
Sauf que, par définition ou presque, ce qui est générique n'est PAS une
solution au problème, qui (c'est toi qui le dis) est un problème de
rapidité.

Je ne conteste pas que ce soit une bonne manière de procéder (et si je n'ai
pas écrit « joli », c'est parce que c'est ainsi qu'est structuré mon propre
code, 8^) La seule différence, c'est que dans mon code j'utiliserais plus
souvent LTOSTR() pour faire ressortir qu'il y a derrière une macro, donc un
potentiel piège à cause de la géométrie variable.

« Lisible » est resté parce que je ne l'ai pas coupé, par flemme. Nous
sommes bien d'accord que ce genre d'utilisation des macros augmente la
lisibilité du code (pas comme not_eq).


Antoine



Avatar
James Kanze
Gabriel Dos Reis writes:

|> "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.

La réalité est un peu plus complexe que ça, et codifier la pratique
existante faisait bien partie du cahier de charge. Mais c'est vrai que
dans le langage même, ils ont introduit un certain nombre d'innovations
dans le sens de plus de rigueur et de vérifications de côté du
compilateur. Les prototypes de fonctions, par exemple. Ou ne permettre
les conversions de pointeur que dans le cas où un des pointeur était
void* (parce que la *pratique* existante à l'époque, quoiqu'on dise
certaines références, était de convertir implicitement entre tout type
de pointeur, voire même entre pointeur et int).

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

| Gabriel Dos Reis writes:
|
| |> "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.
|
| La réalité est un peu plus complexe que ça, et codifier la pratique
| existante faisait bien partie du cahier de charge. Mais c'est vrai que
| dans le langage même, ils ont introduit un certain nombre d'innovations
| dans le sens de plus de rigueur et de vérifications de côté du
| compilateur.

Comme la conversion void* -> T* ?
Ou comme l'introduction de « volatile » avec la sémantique qu'un objet
déclaré avec un type volatile pourrait voir sa valeur modifiée de
manière inconnue au compilateur ou pourrait avoir d'autres
« side effects » inconnus ? C'est vachement plus de vérification
et de rigeur ça.

« `Volatile', in particular, is a frill for esoteric applications,
and much better expressed by other means. Its chief virtue is that
nearly everyone can forget about it. »

[...]

« A related observation is that string literals are not of type
`array of const char.' Indeed, the Rationale (88-004 version) says,
`However, string literals do not have [this type], in order to avoid
the problems of pointer type checking, particularly with library
functions....' Should this bald statement be considered anything
other than an admission that X3J11's rules are screwy? It is
ludicrous that the committee introduces the `const' qualifier, and
also makes strings unwritable, yet is unable to connect the two
conceptions. »

[...]

« K&R C has one important internal contradiction (variadic functions
are forbidden, yet printf exists) and one important divergence
between rule and reality (common vs. ref/def external data
definitions). These contradictions have been an embarrassment to me
throughout the years, and resolving them was high on X3J11's
agenda. X3J11 did manage to come up with an adequate, if awkward,
solution to the first problem. Their solution to the second was the
same as mine (make a rule, then issue a blanket license to violate
it). »

-- Dennis M. Ritchie

http://www.lysator.liu.se/c/dmr-on-noalias.html

| Les prototypes de fonctions, par exemple. Ou ne permettre

Tu veux parler de « l'abomination » « f(void) » ?

| les conversions de pointeur que dans le cas où un des pointeur était
| void* (parce que la *pratique* existante à l'époque, quoiqu'on dise
| certaines références, était de convertir implicitement entre tout type

certaines références étant K+R-1.

| de pointeur, voire même entre pointeur et int).
|
| --
| James Kanze
| Conseils en informatique orientée objet/
| Beratung in objektorientierter Datenverarbeitung
| 9 place Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

--
Gabriel Dos Reis

Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
Avatar
cedric
Gabriel Dos Reis wrote:

Ou comme l'introduction de « volatile » avec la sémantique qu'un objet
déclaré avec un type volatile pourrait voir sa valeur modifiée de
manière inconnue au compilateur ou pourrait avoir d'autres
« side effects » inconnus ? C'est vachement plus de vérification
et de rigeur ça.


Qu'est ce que vous auriez vu de mieux à la place ?

Avatar
Emmanuel Delahaye
Gabriel Dos Reis wrote on 11/11/04 :
James Kanze writes:

Gabriel Dos Reis writes:

"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.



La réalité est un peu plus complexe que ça, et codifier la pratique
existante faisait bien partie du cahier de charge. Mais c'est vrai que
dans le langage même, ils ont introduit un certain nombre d'innovations
dans le sens de plus de rigueur et de vérifications de côté du
compilateur.


Comme la conversion void* -> T* ?
Ou comme l'introduction de « volatile » avec la sémantique qu'un objet
déclaré avec un type volatile pourrait voir sa valeur modifiée de
manière inconnue au compilateur ou pourrait avoir d'autres
« side effects » inconnus ? C'est vachement plus de vérification
et de rigeur ça.


Si j'ai bien compris, le but de 'volatile' n'est pas d'introduire de la
rigueur, mais plutôt d'interdire quelques optimisations aggressives
genre

{
int x = 100;

while (x)
{
x--;
}
}

Ce code ne fait rien à part perdre du temps (pas de 'side-effect'),
donc, je (compilateur) le vire...

Je ne dis pas que c'est la meilleure façon de faire une tempo, mais
c'est parfois la seule possible dans les phases d'init d'une
application embarquée (avant que le système ne soit lancé complètement)
...

{
int volatile x = 100;

while (x)
{
x--;
}
}

ne sera pas optimisé.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"




1 2 3 4 5