Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2424 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [Linux-C] Convertion entier vers chaine ??

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Linux-C] Convertion entier vers chaine ??

n°290677
juki
PSN ID : Jukiller
Posté le 21-01-2003 à 12:03:59  profilanswer
 

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

mood
Publicité
Posté le 21-01-2003 à 12:03:59  profilanswer
 

n°290679
western
AJMM
Posté le 21-01-2003 à 12:05:23  profilanswer
 

Code :
  1. char* int2chaine(int i)
  2. {
  3.   char* tmp = (char*) calloc(sizeof(int), sizeof(char));
  4.   if(tmp != NULL)
  5.     sprintf(tmp, "%d", i);
  6.   else
  7.     {
  8.       perror("impossible de convertir un int en char*" );
  9.       exit(1);
  10.     }
  11.   return tmp;
  12. }

n°290840
tilateur
Posté le 21-01-2003 à 14:34:13  profilanswer
 

western a écrit :

Code :
  1. char* int2chaine(int i)
  2. {
  3.   char* tmp = (char*) calloc(sizeof(int), sizeof(char));
  4.   if(tmp != NULL)
  5.     sprintf(tmp, "%d", i);
  6.   else
  7.     {
  8.       perror("impossible de convertir un int en char*" );
  9.       exit(1);
  10.     }
  11.   return tmp;
  12. }

 


:jap:
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().....

n°290846
western
AJMM
Posté le 21-01-2003 à 14:38:14  profilanswer
 

Depuis que je l'utilise, pas un exit n'est arrivé ;-)

n°291034
lorill
Posté le 21-01-2003 à 16:43:36  profilanswer
 

western a écrit :

Depuis que je l'utilise, pas un exit n'est arrivé ;-)

normal, tu échoues que si y'a erreur d'allocation

n°291083
western
AJMM
Posté le 21-01-2003 à 17:37:13  profilanswer
 

c'est pour cela qu'un exit est plus intéressant que ...

n°291332
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 21-01-2003 à 22:28:09  profilanswer
 

western a écrit :

Code :
  1. char* int2chaine(int i)
  2. {
  3.   char* tmp = (char*) calloc(sizeof(int), sizeof(char));
  4.   if(tmp != NULL)
  5.     sprintf(tmp, "%d", i);
  6.   else
  7.     {
  8.       perror("impossible de convertir un int en char*" );
  9.       exit(1);
  10.     }
  11.   return tmp;
  12. }

 


 
 
euuuuuuuh et int2chaine(111111111) t'as déjà essayé ??? :heink:

n°291514
Musaran
Cerveaulté
Posté le 22-01-2003 à 05:15:40  profilanswer
 

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 :
  1. char* tmp = (char*)malloc(sizeof(int)*2.5 + 1 +1 +1); //+1 pour le signe, +1 pour '\0', +1 par sécurité


Personnellement, les fonctions qui font des allocations, ou quittent le programme, bof...

Code :
  1. int int2str(char* str, int i){
  2. return sprintf(str, "%d", i); //renvoie le nombre de caractères
  3. }


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°291528
Taz
bisounours-codeur
Posté le 22-01-2003 à 08:15:08  profilanswer
 

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 :D. au moins 'jai donné une explication du nombre magique et ma solution est plus portable :p :sol:[/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


Message édité par Taz le 22-01-2003 à 08:25:31
n°291567
western
AJMM
Posté le 22-01-2003 à 09:22:42  profilanswer
 

oui j'ai essayé 111111111 et ça marche ...
je ne vois pas (mais vraiment pas) l'intérêt d'allouer

Code :
  1. sizeof(int)*2.5*...+...+...+...

(<- original, un float pour l'allocation)

mood
Publicité
Posté le 22-01-2003 à 09:22:42  profilanswer
 

n°291716
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 22-01-2003 à 11:48:00  profilanswer
 

western a écrit :

oui j'ai essayé 111111111 et ça marche ...
je ne vois pas (mais vraiment pas) l'intérêt d'allouer

Code :
  1. sizeof(int)*2.5*...+...+...+...

(<- 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

n°291720
western
AJMM
Posté le 22-01-2003 à 11:57:23  profilanswer
 

avant de parler de chances, fait le test!

n°291727
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 22-01-2003 à 12:09:54  profilanswer
 

western a écrit :

avant de parler de chances, fait le test!


[:tapai]

n°291734
western
AJMM
Posté le 22-01-2003 à 12:14:51  profilanswer
 

Juste pour rigoler ...

Code :
  1. int t = -1111111, tt = 1111111;
  2.   for(int i = 0; ; i++)
  3.     {
  4.       t-=10; //- et 10 peuvent être remplacé: * ou 10000
  5.       tt+=10;//+ et 10 peuvent être remplacé: * ou 10000
  6.       printf("%d\n%s\n",t, int2chaine(t));
  7.       printf("%d\n%s\n",tt, int2chaine(tt));
  8.     }


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

n°291787
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 22-01-2003 à 13:03:10  profilanswer
 

western a écrit :

Juste pour rigoler ...

Code :
  1. int t = -1111111, tt = 1111111;
  2.   for(int i = 0; ; i++)
  3.     {
  4.       t-=10; //- et 10 peuvent être remplacé: * ou 10000
  5.       tt+=10;//+ et 10 peuvent être remplacé: * ou 10000
  6.       printf("%d\n%s\n",t, int2chaine(t));
  7.       printf("%d\n%s\n",tt, int2chaine(tt));
  8.     }


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


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

n°291806
harrysauce
Miaaaooou!
Posté le 22-01-2003 à 13:30:27  profilanswer
 

chez lui ca passe parce qu'aucune donnée important n'est ecrit apres le 4eme car, mais ca peut planter!!!!

n°291854
western
AJMM
Posté le 22-01-2003 à 14:33:12  profilanswer
 

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

n°291900
western
AJMM
Posté le 22-01-2003 à 15:36:58  profilanswer
 

j'ai trouvé "tout seul"
version finale et SANS BUGS!

Code :
  1. char* int2chaine(int i)
  2. {
  3.   char* tmp = (char*) calloc((unsigned int)(log(abs(i)) + 1 + (i<0 ? 1 : 0)) , sizeof(char));
  4.   if(tmp != NULL)
  5.     printf("%d caracteres ecrits\n", sprintf(tmp, "%d", i));
  6.   else
  7.     {
  8.       perror("impossible de convertir un int en char*" );
  9.       exit(1);
  10.     }
  11.   return tmp;
  12. }


Pourquoi?
Dans /usr/include/limits.h , on trouve :

Code :
  1. #  define INT_MAX 2147483647
  2. #  define UINT_MAX 4294967295U
  3. #   define LONG_MAX 9223372036854775807L
  4. #   define ULONG_MAX 18446744073709551615UL


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 :
  1. log(abs(i)) + 1 + (i<0 ? 1 : 0)


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


Message édité par western le 22-01-2003 à 15:40:20
n°291972
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 22-01-2003 à 16:47:29  profilanswer
 

western a écrit :

j'ai trouvé "tout seul"
version finale et SANS BUGS!


 
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

n°291997
western
AJMM
Posté le 22-01-2003 à 17:13:35  profilanswer
 

pourquoi pas mais il faut peut-être tester sur une plate-forme 64 bits ...

n°292023
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 22-01-2003 à 17:47:09  profilanswer
 

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

n°292043
western
AJMM
Posté le 22-01-2003 à 18:01:57  profilanswer
 

:pt1cable:

n°292264
Musaran
Cerveaulté
Posté le 22-01-2003 à 23:46:31  profilanswer
 

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 :
  1. //transforme du texte brut en chaine littérale
  2. #define stringer(t) #t
  3. //idem, en évaluant les macros d'abord
  4. #define stringereval(t) stringer(t)
  5. ...malloc( sizeof stringereval(INT_MAX) / sizeof(char) + 1); //+1 pour le signe


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 [:iznogoud_23].


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [Linux-C] Convertion entier vers chaine ??

 

Sujets relatifs
lire une chaine de caractere ?[ PHP ] les 3 derniers carracteres d une chaine...
envoi d'un fichier local vers vers un serveur ftpEnvoi variable php vers Flash
BO: comment exporter des états vers Excel ?[Algo/C] Grande chaine de caractères pour test d'un algorithme
Aligner verticalement un texte vers le bas (css inside)Recuperer une chaine de caractere d'une iframe
Génération d'une chaîne de caractèrerecuperer une page WEB en chaine de caracteres
Plus de sujets relatifs à : [Linux-C] Convertion entier vers chaine ??


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR