Convertion entier vers chaine ?? [Linux-C] - C++ - Programmation
Marsh Posté le 21-01-2003 à 12:05:23
Code :
|
Marsh Posté le 21-01-2003 à 14:34:13
western a écrit :
|
j'aurai meme rajouté un isdigit afin de verifier qu'on a bien un nombre et en cas d'erreur un return NULL au lieu du exit().....
Marsh Posté le 21-01-2003 à 16:43:36
western a écrit : Depuis que je l'utilise, pas un exit n'est arrivé ;-) |
normal, tu échoues que si y'a erreur d'allocation
Marsh Posté le 21-01-2003 à 22:28:09
western a écrit :
|
euuuuuuuh et int2chaine(111111111) t'as déjà essayé ???
Marsh Posté le 22-01-2003 à 05:15:40
Citation : char* tmp = (char*) calloc(sizeof(int), sizeof(char)); |
Hum...
sizeof(int) donne le nombre d'octets pour stocker un int en représentation binaire.
En représentation chaîne décimale, il faut plus.
Il est parfaitement possible que ça n'aie jamais planté, vu que les allocations se font souvent par multiple d'un minimum (16 par exemple).
Et puis calloc... au cas ou on oublie d'écrire le nombre ça évites un bogue ?
Empiriquement:
Code :
|
Personnellement, les fonctions qui font des allocations, ou quittent le programme, bof...
Code :
|
Marsh Posté le 22-01-2003 à 08:15:08
Musaran> t'es sur de ton 2.5? moi j'aurais plutot vu le plus petit entier N tel que N >= CHAR_BITS*ln(2)/ln(10) ce qui doit faire sur nos machines 32 bits N=10
[edit] marne, c'est vrai que 8*0.3... ça fait 2.5 . au moins 'jai donné une explication du nombre magique et ma solution est plus portable [/edit]
plus simplement
donc j'allouerais sizeof(int)*CHAR_BITS*ceil(ln(2.)/ln(10.))+1
en tout cas tu ferais peut etre aussi bien faire attention avec les flottants dans des endroits dangereux comme ça, peut etre il serait plus simple de rester dans un calcul entier en faisant des arrondis par exces: on allouera peut etre un peu trop, mais bon, on est pas quelques octets prets apparemment
Marsh Posté le 22-01-2003 à 09:22:42
oui j'ai essayé 111111111 et ça marche ...
je ne vois pas (mais vraiment pas) l'intérêt d'allouer
Code :
|
(<- original, un float pour l'allocation)
Marsh Posté le 22-01-2003 à 11:48:00
western a écrit : oui j'ai essayé 111111111 et ça marche ...
(<- original, un float pour l'allocation) |
ben t'as de la chance alors, cf l'explication de musaran plus haut. parce que la chaine pour representer 111111111 elle a besoin de 9+1 characteres et que tu n'en as alloué que 4
Marsh Posté le 22-01-2003 à 12:09:54
ReplyMarsh Posté le 22-01-2003 à 12:14:51
Juste pour rigoler ...
Code :
|
J'ai attent les limites des INT et ... ça marche toujours ... finalement, ce code (que j'ai copié dans un truc qui parlait de Bjarne Stroustrup) est correcte ...
Marsh Posté le 22-01-2003 à 13:03:10
western a écrit : Juste pour rigoler ...
|
bon, je reprends: ton calloc reserve QUATRE octets. Ta chaine en fait une bonne dizaine. Donc, ton sprintf écrit en dehors de la zone réservée par ton calloc. Chez toi ça passe parce que ton calloc a réservé 16 octets ou qqch comme ça [ça c'est un coup de bol], mais sur une autre machine ça ne sera peut etre pas le cas.
Lance ton code avec purify/valgrind ou n'importe quel malloc-debuggeur tu vas voir comme il t'insulte
Marsh Posté le 22-01-2003 à 13:30:27
chez lui ca passe parce qu'aucune donnée important n'est ecrit apres le 4eme car, mais ca peut planter!!!!
Marsh Posté le 22-01-2003 à 14:33:12
ok! valgrid m'insulte ... alors j'ai essaié vos trucs (2.5*..., etc.) il m'insulte toujours ;-) donc ma question (outre qu'aucun d'entre vous n'a toujours pas proposé de solutions valables) s'adresse au Captain: combien faut-il allouer?
PS. sprintf écrit 10 octets et si je mets 10 + 1 en dure, je suis toujours insulté ...
Marsh Posté le 22-01-2003 à 15:36:58
j'ai trouvé "tout seul"
version finale et SANS BUGS!
Code :
|
Pourquoi?
Dans /usr/include/limits.h , on trouve :
Code :
|
Ce qui donne bien 10 chiffres (donc char) + le signe + le '\0' final.
Avec des entiers sur 64 bits c'est juste 2 fois plus long (pour autres plate-formes ;-).
Donc, la taille minimale est pour un entier i à convertir en notation décimale :
Code :
|
Je pense que ceux-ci close le débat (à moins de s'exciter sur free())!!!
Finalement, je dois remercier les personnes qui ont "trollé" sur le sujet ainsi quelqu'unes autres qui ne sont pas là ...
Marsh Posté le 22-01-2003 à 16:47:29
western a écrit : j'ai trouvé "tout seul" |
Pour en remettre une couche, un truc plus général c'est d'utiliser la valeur de retour de snprintf(NULL,0,"%d",i) qui renvoie le nb de caractère necessaires
Marsh Posté le 22-01-2003 à 17:13:35
pourquoi pas mais il faut peut-être tester sur une plate-forme 64 bits ...
Marsh Posté le 22-01-2003 à 17:47:09
western a écrit : pourquoi pas mais il faut peut-être tester sur une plate-forme 64 bits ... |
ça doit marcher, à moins de tomber sur un vieille version de sprintf qui renvoie pas la longueur. Sinon, pour conclure une bonne fois pour toutes ce que j'aurais fait si j'avais du faire ce genre de fonction c'est tmp=malloc(256), snprintf(tmp, 256, '%d', tmp=realloc(tmp,strlen(tmp)+1), c'est quand même moins tordu que d'aller tapper dans des log(i).. par contre ça marchera pas sur une architecture avec des entiers en 1024bits
Marsh Posté le 22-01-2003 à 23:46:31
J'avais vaguement pensé à cette approche par logarithme, sans avoir le courage de le faire.
À mon avis, on peut tout aussi bien toujours allouer la taille maximum, l'économie théorique de place n'en valant pas la peine.
Pour que le calcul soit une constante de compilation sans coût d'exécution, je ferais comme ça:
Code :
|
Le problème est que INT_MAX peut être défini autrement qu'en nombre simple.
C'est pour ça que je n'utilises pas INT_MIN directement: '(-2147483647 - 1)' sur mon système.
Allocation en C == prise de tête .
Marsh Posté le 21-01-2003 à 12:03:59
Salut, je pose la question pour un ami
Comment faire une convertion d'entier vers uen chaine en C sous Linux qd itoa marche pas ?
Merci d'avance