Partage
  • Partager sur Facebook
  • Partager sur Twitter

[zConvert] Exercice pour débutants

Bonne chance à vous :)

20 juillet 2010 à 22:32:48

bon voila une fonction qui marche sur les nombres à virgules(6 au max),
qu'on me fouette pas j'ai utiliser la lib math car en faisant les calculs manuellement j'avais des résidus qui faussait le résultat.
certes en forçant un peu sur des approximations ca aurait pu le faire mais vacances => !math =)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

void convertir_int(int n, char * chaine) 
{
  int cpt = 0;
  int i,temp,bool = 0;
  if(n<0)
  {
     chaine[cpt++]='-';
     n = -n;     
  }
  /*le int en 32bit va jusqu'a 2147483647*/
  for(i=1000000000;i>=10;i=i/10)
  {
     temp = n/i;
     if(bool || temp)
     {                           
        chaine[cpt++]= (temp + 48);
        bool = 1;
     }
     n = n%i;
     
  }
  chaine[cpt++] = (char) n + 48;
  chaine[cpt]=0;
  
}

void convertir_float(double x , char * chaine)
{
     char temp[50];
     double partie_ent;
     double partie_dec;
     partie_dec = modf(x,&partie_ent);
     convertir_int((int)partie_ent,chaine);
     strcat(chaine,",");
     partie_ent = 0.0;
     /*en float/double on peut faire de test == 0 donc on prend en espsilon assez petit pour compenser*/
     /*comme en fortran*/
     /*j'ai tester, dans mon cas cela degenere apres 6 chiffres apres la virgule*/
     while(partie_dec > 0.000001)
     {
        x = 10.0*(partie_ent + partie_dec);
        partie_dec = modf(x,&partie_ent);
     }
     convertir_int((int)partie_ent,temp);
     strcat(chaine,temp);
}
   
int main(int argc,char * argv[]) 
{
  int n1,menu;
  double n2;
  char chaine[50] = "";
  printf("1) int \n2) float\n");
  scanf("%d", &menu);
  if(menu == 1)
  {
     scanf("%d", &n1);
     convertir_int(n1, chaine);
  }
  else
  {
     scanf("%lf", &n2);
     convertir_float(n2, chaine);
  }   
  printf("%s\n", chaine);
  return EXIT_SUCCESS;
}

  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2010 à 10:03:16

Bonjour,

Je n'ai pas trop eu envie de participer car c'est un exercice trop classique.

Voici quand même quelques liens vers mes codes :
http://www.siteduzero.com/forum-83-400 [...] html#r4758769
http://www.siteduzero.com/forum-83-536 [...] html#r5149238
http://www.siteduzero.com/forum-83-536 [...] html#r5154515

Sinon, pour la conversion de float, c'est effectivement une question plus délicate. Voici un (ancien) code :
#include <stdio.h>
#include <float.h>

/* ecrit un double dans une chaine */
void doubleToString(char* str, double nb, size_t precision)
{
    unsigned i, unite;

    /* si nb est negatif, ecrit le signe et passe nb en positif */
    if (nb < 0)
    {
        *(str++) = '-';
        nb = -nb;
    }

    /* nb de chiffres avant la virgule */
    for (i = 1; nb >= 10; i++)
        nb /= 10;

    /* ecrit les chiffres avant la virgule */
    while (i--)
    {
        unite = (int)nb;
        *(str++) = unite + '0';
        nb = (nb-unite) * 10;
    }

    /* ecrit les chiffres apres la virgule */
    if (precision > 0)
    {
        *(str++) = '.';  /* On ecrit la virgule */
        while (nb > FLT_MIN && precision--)
        {
            unite = (int)nb;
            *(str++) = unite + '0';
            nb = (nb-unite) * 10;
        }
    }

    *str = '\0';  /* On termine la chaine */
}

int main(int argc, char **argv)
{
    char str[50];
    doubleToString(str, -125.00079432, 7);
    puts(str);
    return 0;
}


Méthode employée


Je procède par extraction d'unités (par cast de double vers int).
C'est a dire que je divise tout d'abord le nombre jusqu'à passer en dessous de 10, puis j'extrais les unités en retirant chaque unité puis en multipliant par 10.

Cette méthode n'est pas vraiment fameuse, principalement parce que l'on peut perdre en précision dans certains cas, et qu'elle dépend beaucoup de l'implémentation. Mais elle semble marcher dans la plupart des cas.
  • Partager sur Facebook
  • Partager sur Twitter
16 août 2010 à 16:16:00

Ayant eu un peu de temps, j'ai rajouté la gestion des négatifs.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

#define BUF (1 << 5)

char * my_itoa(int val, char * buf, size_t len);

int
main (void) {
	char buf[BUF+1] = {0};
	printf("%s\n", my_itoa(5, buf, BUF));

	return EXIT_SUCCESS;
}

char *
my_itoa(int val, char * buf, size_t len){
	if (len < log10(abs(val))) {
		perror("Overflow attempt.");
		return NULL;
	}
	if (!val) {
		*buf = '0';
	} else {
		char * _my_itoa(char *, int);
		
		if (val > 0) {
			buf = _my_itoa(buf + (int) log10(val), val);
		} else {
			*buf = '-';
			if (val == INT_MIN) {
				buf = _my_itoa(buf + (int) log10(INT_MAX) + 1, val);
			} else {
				buf = _my_itoa(buf + (int) log10(abs(val)) + 1, val);
			}
		}
	}
	return buf + (val > 0);
}

char *
_my_itoa (char * buf, int val) {

	if (!val) {
		return buf;
	} else if (val > 0) { /* Positive value */
		*buf = val % 10 + '0';
	} else { /* Negative value */
		if (val == INT_MIN) {
			val = INT_MAX;
			*buf = val % 10 + '1';
		} else {
			val = abs(val);
			*buf = val % 10 + '0';
		}
	}
	_my_itoa(buf - 1, val/10);
}
  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 0:31:21

#include <stdio.h>
void convertir(int n, char chaine[]) {
     sprintf(chaine, "%d", n);
}


:-°
MDR :lol:
  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 16:00:44

Ouais, sauf que le but c'est de pas utiliser sprintf sinon il n'y a plus aucun intérêt. :-°
  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 20:51:59

Citation : Lithrein

Ouais, sauf que le but c'est de pas utiliser sprintf sinon il n'y a plus aucun intérêt. :-°


C'est vrai ? o_O:-°

Bon ben alors :
void convertir(int n, char chaine[]) {
  int repere = 1, emplacement = 0;
  while(!(repere > n)) repere*=10;
  for(;repere > 1;emplacement++){
      repere/=10;
      chaine[emplacement]= (n/repere) + '0' ;
      n%=repere;}
  chaine[emplacement] = '\0';
}


EDIT: version qui gère le 0 et les négatifs :
void convertir(int n, char chaine[]) {
  int repere = 1, emplacement = 0;
  if(n<0) chaine[0]='-', emplacement=1, n=-n;
  while(!(repere > n)) repere*=10;
  if(n==0) chaine[0]='0', emplacement=1, repere=1;
  for(;repere > 1;emplacement++){
      repere/=10;
      chaine[emplacement]= (n/repere) + '0' ;
      n%=repere;}
  chaine[emplacement] = '\0';
}

  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 21:53:40

Citation : Jrem

EDIT: version qui gère le 0 et les négatifs :

void convertir(int n, char chaine[]) {
  int repere = 1, emplacement = 0;
  if(n<0) chaine[0]='-', emplacement=1, n=-n;
  while(!(repere > n)) repere*=10;
  if(n==0) chaine[0]='0', emplacement=1, repere=1;
  for(;repere > 1;emplacement++){
      repere/=10;
      chaine[emplacement]= (n/repere) + '0' ;
      n%=repere;}
  chaine[emplacement] = '\0';
}

#include <stdio.h>
#include <limits.h>

int main(void)
{
    int n = INT_MAX; /* Ou même INT_MIN */
    char s[50] = "";

    convertir(n, s);
    printf("%s\n", s);

    return 0;
}
  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 23:11:03

Oui bon si tu veux :p
Alors :
void convertir(int n, char chaine[]) {
  long long int repere = 1;
  int emplacement = 0;
  if(n<0) chaine[0]='-', emplacement=1, n=-n;
  while(!(repere > n)) repere*=10;
  if(n==0) chaine[0]='0', emplacement=1, repere=1;
  for(;repere > 1;emplacement++){
      repere/=10;
      chaine[emplacement]= (n/repere) + '0' ;
      n%=repere;}
  chaine[emplacement] = '\0';
}
  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 23:54:07

Moi jveux une version bien indentee ^^
  • Partager sur Facebook
  • Partager sur Twitter
17 août 2010 à 23:57:07

Citation : Adroneus

Moi jveux une version bien indentee ^^


+1
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 1:03:21

Citation : HighTam

INT_MIN ?


Alors là je ne comprends pas pourquoi cela ne fonctionne pas avec INT_MIN (c'est le n=-n; qui ne fonctionne pas) mais cela fonctionne avec INT_MIN+1 :) . Si quelqu'un peut me le dire pourquoi...

[EDIT] J'ai compris pourquoi, c'est parce que INT_MIN = (INT_MAX*-1)-1 , je vais corriger cela. [/EDIT]
[EDIT2] Voilà la version qui fonctionne avec INT_MIN :
void convertir(int n, char chaine[]) {
  long long int repere = 1, p=n;
  int emplacement = 0;
  if(p<0) chaine[0]='-', emplacement=1, p=-p;
  while(!(repere > p)) repere*=10;
  if(p==0) chaine[0]='0', emplacement=1, repere=1;
  for(;repere > 1;emplacement++){
      repere/=10;
      chaine[emplacement]= (p/repere) + '0' ;
      p%=repere;}
  chaine[emplacement] = '\0';
}

[/EDIT2]

Citation : Adroneus

Moi jveux une version bien indentee ^^



void convertir(int n, char chaine[])
{
    long long int repere = 1;
    int emplacement = 0;

    if(n<0)
        chaine[0]='-', emplacement=1, n=-n;

    while(!(repere > n))
        repere*=10;

    if(n==0)
        chaine[0]='0', emplacement=1, repere=1;

    for(;repere > 1;emplacement++)
    {
        repere/=10;
        chaine[emplacement]= (n/repere) + '0' ;
        n%=repere;
    }
    chaine[emplacement] = '\0';
}
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 8:03:52

Chui pas fan du long long, mais bon ça fonctionne. Ta fonction 'indentée' ne fonctionne pas.
Voilà ta fonction correctement indentée :

void convertir(int n, char chaine[]) {
  long long int repere = 1, p = n;
  int emplacement = 0;
  
  if (p < 0) {
    chaine[0] = '-';
    emplacement = 1;
    p = -p;
  }
  
  while (!(repere > p))
    repere *= 10;
  
  if (p == 0) {
    chaine[0] = '0';
    emplacement = 1;
    repere = 1;
  }
  
  for ( ; repere > 1; emplacement++) {
    repere /= 10;
    chaine[emplacement] = (p/repere) + '0' ;
    p %= repere;
  }
  chaine[emplacement] = '\0';
}

Comment tu ferais pour une conversion long long vers char* ? ;)
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 10:25:38

et non, INT_MIN = (-INT_MAX-1) et pa le truc que t'as ecrit ;)
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 11:45:51

Citation : Adroneus

et non, INT_MIN = (-INT_MAX-1) et pa le truc que t'as ecrit ;)


et si, les deux sont justes. -INT_MAX=INT_MAX*(-1) ;)

Citation

Chui pas fan du long long


Il faut n'importe quel format dans lequel on puisse stocker la plus petite puissance de 10 supérieure à INT_MAX (pour repere) et dans lequel on puisse stocker -INT_MIN (pour p). Et oui, -INT_MIN ne rentre pas dans un int... :o

Citation

Ta fonction 'indentée' ne fonctionne pas.


J'ai testé, elle fonctionne mais pas pour INT_MIN puisque je ne l'ai pas éditée...

Citation

Comment tu ferais pour une conversion long long vers char* ? ;)


Un nombre dans un pointeur ? o_O
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 13:04:32

Exact j'avais pas vu le -1 derriere --'
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 19:25:31

Citation : Jrem

Un nombre dans un pointeur ? o_O


Bah, c'est ce que tu fais en faisant char chaine[] dans ton prototype de fonction. Ca revient à écrire char * chaine .
Pour convertir un long long en char* il faudra trouver autre chose. :p
  • Partager sur Facebook
  • Partager sur Twitter
18 août 2010 à 21:49:54

Citation : Pouet_forever

Citation : Jrem

Un nombre dans un pointeur ? o_O


Bah, c'est ce que tu fais en faisant char chaine[] dans ton prototype de fonction. Ca revient à écrire char * chaine .
Pour convertir un long long en char* il faudra trouver autre chose. :p



Sauf que quand tu fais chaine[1], c'est un char et non un char* ;)
Et sinon si on sait que le long long int est positif (EDIT : ou même si il est négatif) il suffit de faire %256 , et si il est supérieur à 255 c'est trop grand, tu ne peux pas le "convertir" ;)
Mais dans ce cas là pas de problème puisque on sait que ce qui va dans le char est forcément compris entre 48 et 57 .
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2010 à 2:02:17

Personne pour les nombres flottants ? :(
  • Partager sur Facebook
  • Partager sur Twitter