Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercices pour débutants en C

Au menu : zSommeChiffres (nombres, algo)

7 janvier 2010 à 8:45:45

Citation : Pouet_forever


Pour clore le débat, la réponse donnée par Le Conjugueur est



Très bien ce petit applet, il faut que GurneyH le rajoute dans les références avec l'énoncé de l'exercice.
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 9:05:50

Bon bah avec tout ça mon code devrait être bon maintenant :D
J'ai rajouté et modifié quelques trucs. J'ai rajouté la gestion des espaces (merci Lithrein :p ) et j'ai rajouté une fonction plutôt qu'utiliser strtol :)
J'ai viré 2 variables globales et les ai mises dans les fonctions. Je laisse la dernière parce que je m'en sert dans les 3 fonctions et je trouve ça plus propre que de le passer en paramètre :)

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

/* ============ Variables globales ============ */

char const * const unites [20] = {
	"zero", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf",
	"dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf"
};

/* ============ Fonctions ============ */

/* Fonction qui prend en argument 1 nombre entre 0 et 99 (tous 2 inclus).
 * Une chaîne de caractère 'str' dans laquelle on va mettre la décomposition du nombre.
 * Un paramètre 'mil' pour savoir si le nombre est dans les mille -> invariable.
 */

void dix(int nb, char *str, int mil) {
	char const * const dizaines [10] = {
		"", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante",
		"quatre-vingt", "quatre-vingt"
	};
	char tmp[100] = "";
	int unit = nb % 10;
	int disse = nb / 10;
	
	if (nb == 0 || (nb == 1 && mil == 1))
		return;
	
	if (nb < 20) {
		strcat(str, unites[nb]);
		strcat(str, " ");
		return;
	}
	
	if (nb == 80) {
		strcat(str, dizaines[disse]);
		if (!mil)
			strcat(str, "s");
		strcat(str, " ");
		return;
	}
	
	strcat(tmp, dizaines[disse]);
	
	if (unit == 1 && disse != 8 && disse != 9)
		strcat(tmp, " et ");
	else if (unit != 0)
		strcat(tmp, "-");
	else
		strcat(tmp, " ");
	
	if (disse == 7 || disse == 9)
		strcat(tmp, unites[unit+10]);
	else if (unit != 0)
		strcat(tmp, unites[unit]);
	
	strcat(str, tmp);
	strcat(str, " ");
}

/* Fonction qui décompose la centaine du nombre.
 * La fonction prend un nombre sur 3 chiffres 0 <= nb <= 999.
 * Les autres sont les mêmes paramètres que la fonction dix.
 */

void cent(int nb, char *str, int mil) {
	char tmp[100] = "";
	
	if (nb > 99) {
		int mod = nb / 100;
		
		if (mod > 1)
			sprintf(tmp, "%s ", unites[mod]);
		strcat(tmp, "cent");
		
		if (!mil && mod > 1 && nb % 100 == 0)
			strcat(tmp, "s");
		strcat(tmp, " ");
	}
	
	dix(nb % 100, tmp, mil);
	
	strcpy(str, tmp);
}

void supp_espaces(char *str) {
	int i, j;
	for (i=j = 0; str[i] != '\0'; i++) {
		str[j] = str[i];
		if (str[i] != ' ')
			j++;
	}
	str[j] = '\0';
}

int estZero(char *str) {
	for ( ; *str; str++)
		if (*str != '0')
			return 0;
	return 1;
}

/* Fonction qui prend une chaîne qui contient le nombre à décomposer.
 * Retourne le nombre en toutes lettres.
 */

char * z0zero(char *src) {
	char const * const centaines [7] = {
		"mille", "million", "milliard", "billion", "trillion", "quatrillion", "quintillion"
	};
	static char res[500];
	char str[500] = "";
	int i, j, indice;
	int tmp, mult, len;
	int mil = 0;
	
	supp_espaces(src);
	len = strlen(src);
	
	if (estZero(src)) {
		sprintf(res, "%s", unites[0]);
		return res;
	}
	
	/* On parcoures notre tableau 'centaine'.
	 * 0 == "cent", 1 == "mille", 2 == "million", 3 == "milliard", etc.
	 */
	for (j = 0; j < 8; j++) {
		tmp = 0;
		mult = 1;
		*str = '\0';
		/* Si le nombre est mille ou pas.
		 * "mille" est invariable, c'est pour le 's'. */
		if (j == 1)
			mil = 1;
		else
			mil = 0;
		
		indice = 3 * (j+1);
		for (i = len-1-indice+3; i >= 0 && i >= len-indice; i--, mult*=10)
			tmp += (src[i] - '0') * mult;
		
		cent(tmp, str, mil);
		
		if (j != 0 && tmp != 0) {
			strcat(str, centaines[j-1]);
			if (tmp != 1 && j != 1)
				strcat(str, "s");
			strcat(str, " ");
		}
		
		strcat(str, res);
		strcpy(res, str);
		
		if (i < 0)
			break;
	}
	
	len = strlen(res) -1;
	if (res[len] == ' ')
		res[len] = '\0';
	
	return res;
}

int main(void) {
	char str[] = "180 000 080";
	
	printf("%s -> ", str);
	printf("%s", z0zero(str));
	return EXIT_SUCCESS;
}
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 13:10:02

Le lien vers l'applet, a été ajouté. J'aurais du y penser dès le départ...
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
7 janvier 2010 à 18:25:17

Voilà, normalement ça marche sans bug, les accords sont faits, etc, reste plus qu'à simplifiez trim.

/**
 * Attention : si vous etes sous GNU/Linux pensez à liez les fonctions mathématiques avec -lm pour libm.so
 * Attention : if you're under a GNU/Linux system, think to link mathematical functions with -lm for libm.so
 * Ex : gcc -Wall -Wextra -lm main.c
 * Todo : fixer : bug espace
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define xstr(s) str(s)
#define str(s) #s

#define TAILLE_MAX 100

void
clean_stdin (void) {
    int c;
    while ((c=getchar()) != '\n' && c != EOF);
}

void
trim (char * s) {
    int NbSpace = 0;
    int i, j;
    size_t sLen;
    char * tmp;

    sLen = strlen(s);

    for (i=0 ; s[i] ; ++i) { /* Détermination du nombre d'espaces */
        NbSpace = (s[i] == ' ')? NbSpace+1 : NbSpace;
    }
    if (0 == NbSpace) {
        return;
    }
    tmp = malloc(sLen-NbSpace+1);
    for (i=0, j=0; s[i]; ++i) { /* Création de la nouvelle chaine */
        if (s[i] != ' ') {
            tmp[j] = s[i];
            ++j;
        }
    }
    tmp[sLen-NbSpace] = '\0';

    for (i=0 ; tmp[i] ; ++i) { /* Overwrite sur l'ancien chaine */
        s[i] = tmp[i];
    }
    for(; s[i] ; ++i) { /* On complète avec des 0 pour avoir une chaîne standard */
        s[i] = '\0';
    }
    free(tmp);
}

void
z0zero (char * src, char * dst) {
    const char * unites[10] = {"zero", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"};
    const char * unites_irr[6] = {"onze", "douze", "treize", "quatorze", "quinze", "seize"};
    const char * dizaines[10] = {"dix", "vingt", "trente", "quarente", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"};
    const char * centaines[8] = {"cent", "mille", "million", "milliard", "billion", "trillon", "quatrillon", "quintillon"};
    int index, SIndex, i;
    char srcLen;

    trim(src); /* Suppression des espaces */
    srcLen = strlen(src);

    if (srcLen > 24) {
        fprintf(stderr, "Erreur : Votre nombre est trop grand");
        return;
    }

    /* Multiple de 3 le plus proche */
    if (0 == srcLen%3) {
        index = srcLen/3;
    } else {
        index = floor(srcLen/3.0);
    }
    if (0 == (srcLen-index*3)%3) { /* Le premier chiffre est : */
        SIndex = 3; /* Une centaine */
    } else if (0 == (srcLen-index*3)%2) {
        SIndex = 2; /* Une dizaine */
    } else {
        SIndex = 1; /* Une unite */
    }

    for (i=0 ; src[i];) {
        if (3 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50] = {0};
                sprintf(buf, "%s%s%s%s ", (val>1)?unites[val]:"", (val>1)?" ":"" , centaines[0], (index != 2 && '0' == src[i+1] && '0' == src[i+2] && val > 1)? "s" : "");
                strcat(dst, buf);
            }
            ++i;
            --index;
            --SIndex;
        }
        if (2 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50];
                sprintf(buf, "%s%s%s", (1 == val && src[i+1]-'0'> 0 && src[i+1]-'0'< 7)? unites_irr[src[i+1]-'0'-1] : dizaines[val-1], (index != 1 && 8 == val && '0' == src[i+1])?"s":"", ((7 == val || 9 == val) && (src[i+1]-'0'>6 || '0' == src[i+1]))?"-dix":"");
                strcat(dst, buf);
            }
            if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
                i += 2;
                SIndex -= 2;
                strcat(dst, " ");
            } else {
                ++i;
                --SIndex;
            }
        }
        if (1 == SIndex) {
            int val = src[i]-'0';
            if (!(srcLen == 4 && val == 1 && 0 == i)) {
                char buf[50];
                sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' != 8 || src[i-1]-'0' != 9))))?"-":"", (i != 0 && 1 == val && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
                strcat(dst, buf);
            }
            ++i;
        }
        if (index > 0 && srcLen > 3 &&(src[i-1] != '0' || src[i-2] != '0' || src[i-3] != '0')) {
            char buf[50] = {0};
            sprintf(buf, "%s%s ", centaines[index], (index >1 && (src[i-1]-'0'>1 || src[i-2]-'0'>0 || src[i-3]-'0'>0))?"s":"");
            strcat(dst, buf);
        }
        SIndex = 3;
    }
}

int
main (void) {
    char * input;
    char NombreEnLettres[500] = {""};
    signed char bool;

    input = malloc(TAILLE_MAX+1);

    /* On s'ocuppe de la saisie de l'utilisateur */
    bool = 0;
    puts("max : 999 999 999 999 999 999 999 999\nexemples: 1 000 000, 1000000");
    while (bool == 0) {
        puts("Saisissez votre nombre :");
        if (scanf(" %"xstr(TAILLE_MAX)"[0-9 ][^\n]", input) == 1) {
            int c;
            if ((c = getchar()) != '\n') { /* Saisie trop longue */
                fprintf(stderr, "Erreur : Nombre trop long\n");
                clean_stdin();
            } else {
                bool = 1;
            }
        } else {
            fprintf(stderr, "Erreur : Echec de la saisie\n");
            clean_stdin();
        }
    }

    z0zero(input, NombreEnLettres);
    printf("%s\n", NombreEnLettres);

    free(input);

    return EXIT_SUCCESS;
}


$ ./Lithrein_z0zero
max : 999 999 999 999 999 999 999 999
exemples: 1 000 000, 1000000
Saisissez votre nombre :
80 080
quatre-vingt mille quatre-vingts


$ ./Lithrein_z0zero
max : 999 999 999 999 999 999 999 999
exemples: 1 000 000, 1000000
Saisissez votre nombre :
80 081 080 091 080
quatre-vingts billions quatre-vingt-un milliards quatre-vingts millions quatre-vingt-onze mille quatre-vingts


$ ./Lithrein_z0zero
max : 999 999 999 999 999 999 999 999
exemples: 1 000 000, 1000000
Saisissez votre nombre :
10 000 000
dix millions


$ ./Lithrein_z0zero
max : 999 999 999 999 999 999 999 999
exemples: 1 000 000, 1000000
Saisissez votre nombre :
999 999 999 999 999 999 999 999
neuf cent quatre-vingt-dix-neuf quintillons neuf cent quatre-vingt-dix-neuf quatrillons neuf cent quatre-vingt-dix-neuf trillons neuf cent quatre-vingt-dix-neuf billions neuf centquatre-vingt-dix-neuf milliards neuf cent quatre-vingt-dix-neuf millions neuf cent quatre-vingt-dix-neuf mille neuf cent quatre-vingt-dix-neuf


Citation : Pouet_forever

Tout imbriquer dans des sprintf comme ça je trouve ça complètement illisible.


@Pouet_forever : the aim is here ...
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 18:54:46

Ya des petits problèmes sur les " et " :)

21
vingt- et un


800001
huit cent  mille  et un


C'est quarante pas quarente :) (un peu comme moi avec milliard :lol: )
Tu me dira t'as fait la même faute avec trillion, et compagnie :-°

Citation : Lithrein

@Pouet_forever : the aim is here ...


As u wish :)
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:09:52

==> Pouet_forever :) :

Citation : HighTam

Citation : Pouet_forever

Fait attention à cette écriture j'ai déjà eu des problèmes. Mets des accolades :)

if (*src-'0' <= 6)
    if (c == '7' && *src == '1')
        sprintf(dst, "%s et %s", dst, to16[10+*src-'0']);
    else
        sprintf(dst, c == '1' ? "%s%s" : "%s-%s", dst, to16[10+*src-'0']);
else
    sprintf(dst, c == '1' ? "%sdix-%s" : "%s-dix-%s" , dst, to16[*src-'0']);


Hmm, pourquoi ? Quel genre de problème as tu eu ?

int main(void)
{
    int i = 2;
    if (i < 5)
        if (i > 2)
            puts("2 < i < 5");
        else
            puts("i <= 2");
    else
        puts("i > 5");

    return 0;
}

i <= 2
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:19:25

Si jamais tu enlèves ton else imbriqué mais que tu laisse cette indentation tu risques de ne pas comprendre pourquoi ça ne donne pas le résultat attendu ;)
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:21:03

Correction des fautes.
/**
* Attention : si vous etes sous GNU/Linux pensez à liez les fonctions mathématiques avec -lm pour libm.so
* Attention : if you're under a GNU/Linux system, think to link mathematical functions with -lm for libm.so
* Ex : gcc -Wall -Wextra -lm main.c
* Todo : fixer : bug espace
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define xstr(s) str(s)
#define str(s) #s

#define TAILLE_MAX 100

void
clean_stdin (void) {
int c;
while ((c=getchar()) != '\n' && c != EOF);
}

void
trim (char * s) {
int NbSpace = 0;
int i, j;
size_t sLen;
char * tmp;

sLen = strlen(s);

for (i=0 ; s[i] ; ++i) { /* Détermination du nombre d'espaces */
NbSpace = (s[i] == ' ')? NbSpace+1 : NbSpace;
}
if (0 == NbSpace) {
return;
}
tmp = malloc(sLen-NbSpace+1);
for (i=0, j=0; s[i]; ++i) { /* Création de la nouvelle chaine */
if (s[i] != ' ') {
tmp[j] = s[i];
++j;
}
}
tmp[sLen-NbSpace] = '\0';

for (i=0 ; tmp[i] ; ++i) { /* Overwrite sur l'ancien chaine */
s[i] = tmp[i];
}
for(; s[i] ; ++i) { /* On complète avec des 0 pour avoir une chaîne standard */
s[i] = '\0';
}
free(tmp);
}

void
z0zero (char * src, char * dst) {
const char * unites[10] = {"zero", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"};
const char * unites_irr[6] = {"onze", "douze", "treize", "quatorze", "quinze", "seize"};
const char * dizaines[10] = {"dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"};
const char * centaines[8] = {"cent", "mille", "million", "milliard", "billion", "trillion", "quatrillion", "quintillion"};
int index, SIndex, i;
char srcLen;

trim(src); /* Suppression des espaces */
srcLen = strlen(src);

if (srcLen > 24) {
fprintf(stderr, "Erreur : Votre nombre est trop grand");
return;
}

/* Multiple de 3 le plus proche */
if (0 == srcLen%3) {
index = srcLen/3;
} else {
index = floor(srcLen/3.0);
}
if (0 == (srcLen-index*3)%3) { /* Le premier chiffre est : */
SIndex = 3; /* Une centaine */
} else if (0 == (srcLen-index*3)%2) {
SIndex = 2; /* Une dizaine */
} else {
SIndex = 1; /* Une unite */
}

for (i=0 ; src[i];) {
if (3 == SIndex) {
int val = src[i]-'0';
if (val > 0) {
char buf[50] = {0};
sprintf(buf, "%s%s%s%s ", (val>1)?unites[val]:"", (val>1)?" ":"" , centaines[0], (index != 2 && '0' == src[i+1] && '0' == src[i+2] && val > 1)? "s" : "");
strcat(dst, buf);
}
++i;
--index;
--SIndex;
}
if (2 == SIndex) {
int val = src[i]-'0';
if (val > 0) {
char buf[50];
sprintf(buf, "%s%s%s", (1 == val && src[i+1]-'0'> 0 && src[i+1]-'0'< 7)? unites_irr[src[i+1]-'0'-1] : dizaines[val-1], (index != 1 && 8 == val && '0' == src[i+1])?"s":"", ((7 == val || 9 == val) && (src[i+1]-'0'>6 || '0' == src[i+1]))?"-dix":"");
strcat(dst, buf);
}
if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
i += 2;
SIndex -= 2;
strcat(dst, " ");
} else {
++i;
--SIndex;
}
}
if (1 == SIndex) {
int val = src[i]-'0';
if (!(srcLen == 4 && val == 1 && 0 == i)) {
char buf[50];
sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1] != '0' && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
strcat(dst, buf);
}
++i;
}
if (index > 0 && srcLen > 3 &&(src[i-1] != '0' || src[i-2] != '0' || src[i-3] != '0')) {
char buf[50] = {0};
sprintf(buf, "%s%s ", centaines[index], (index >1 && (src[i-1]-'0'>1 || src[i-2]-'0'>0 || src[i-3]-'0'>0))?"s":"");
strcat(dst, buf);
}
SIndex = 3;
}
}

int
main (void) {
char * input;
char NombreEnLettres[500] = {""};
signed char bool;

input = malloc(TAILLE_MAX+1);

/* On s'ocuppe de la saisie de l'utilisateur */
bool = 0;
puts("max : 999 999 999 999 999 999 999 999\nexemples: 1 000 000, 1000000");
while (bool == 0) {
puts("Saisissez votre nombre :");
if (scanf(" %"xstr(TAILLE_MAX)"[0-9 ][^\n]", input) == 1) {
int c;
if ((c = getchar()) != '\n') { /* Saisie trop longue */
fprintf(stderr, "Erreur : Nombre trop long\n");
clean_stdin();
} else {
bool = 1;
}
} else {
fprintf(stderr, "Erreur : Echec de la saisie\n");
clean_stdin();
}
}

z0zero(input, NombreEnLettres);
printf("%s\n", NombreEnLettres);

free(input);

return EXIT_SUCCESS;
}

Je sens que je vais réécrire le code en plus lisible car pour corriger les bugs c'est de plus en plus dur :euh:
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:22:22

Citation : Pouet_forever

Si jamais tu enlèves ton else imbriqué mais que tu laisse cette indentation tu risques de ne pas comprendre pourquoi ça ne donne pas le résultat attendu ;)


Bien, je ferai attention :)
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:30:59

Citation : Lithrein

Je sens que je vais réécrire le code en plus lisible car pour corriger les bugs c'est de plus en plus dur :euh:


Bon ça me rassure :p
Finalement je disais pas trop de conneries ^^

101101101
cent  et un millions cent  et un mille cent  et un
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:36:47

@Pouet_forever : tu n'as pas la dernière version, j'ai modifié le code juste au dessus, je pensais que personne n'avait eu le temps de tester.
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 19:47:25

Je pense que c'est celle-là (vérifie) :

/**
 * Attention : si vous etes sous GNU/Linux pensez à liez les fonctions mathématiques avec -lm pour libm.so
 * Attention : if you're under a GNU/Linux system, think to link mathematical functions with -lm for libm.so
 * Ex : gcc -Wall -Wextra -lm main.c
 * Todo : fixer : bug espace
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define xstr(s) str(s)
#define str(s) #s

#define TAILLE_MAX 100

void
clean_stdin (void) {
    int c;
    while ((c=getchar()) != '\n' && c != EOF);
}

void
trim (char * s) {
    int NbSpace = 0;
    int i, j;
    size_t sLen;
    char * tmp;
	
    sLen = strlen(s);
	
    for (i=0 ; s[i] ; ++i) { /* Détermination du nombre d'espaces */
        NbSpace = (s[i] == ' ')? NbSpace+1 : NbSpace;
    }
    if (0 == NbSpace) {
        return;
    }
    tmp = malloc(sLen-NbSpace+1);
    for (i=0, j=0; s[i]; ++i) { /* Création de la nouvelle chaine */
        if (s[i] != ' ') {
            tmp[j] = s[i];
            ++j;
        }
    }
    tmp[sLen-NbSpace] = '\0';
	
    for (i=0 ; tmp[i] ; ++i) { /* Overwrite sur l'ancien chaine */
        s[i] = tmp[i];
    }
    for(; s[i] ; ++i) { /* On complète avec des 0 pour avoir une chaîne standard */
        s[i] = '\0';
    }
    free(tmp);
}

void
z0zero (char * src, char * dst) {
    const char * unites[10] = {"zero", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"};
    const char * unites_irr[6] = {"onze", "douze", "treize", "quatorze", "quinze", "seize"};
    const char * dizaines[10] = {"dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"};
    const char * centaines[8] = {"cent", "mille", "million", "milliard", "billion", "trillion", "quatrillion", "quintillion"};
    int index, SIndex, i;
    char srcLen;
	
    trim(src); /* Suppression des espaces */
    srcLen = strlen(src);
	
    if (srcLen > 24) {
        fprintf(stderr, "Erreur : Votre nombre est trop grand");
        return;
    }
	
    /* Multiple de 3 le plus proche */
    if (0 == srcLen%3) {
        index = srcLen/3;
    } else {
        index = floor(srcLen/3.0);
    }
    if (0 == (srcLen-index*3)%3) { /* Le premier chiffre est : */
        SIndex = 3; /* Une centaine */
    } else if (0 == (srcLen-index*3)%2) {
        SIndex = 2; /* Une dizaine */
    } else {
        SIndex = 1; /* Une unite */
    }
	
    for (i=0 ; src[i];) {
        if (3 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50] = {0};
                sprintf(buf, "%s%s%s%s ", (val>1)?unites[val]:"", (val>1)?" ":"" , centaines[0], (index != 2 && '0' == src[i+1] && '0' == src[i+2] && val > 1)? "s" : "");
                strcat(dst, buf);
            }
            ++i;
            --index;
            --SIndex;
        }
        if (2 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50];
                sprintf(buf, "%s%s%s", (1 == val && src[i+1]-'0'> 0 && src[i+1]-'0'< 7)? unites_irr[src[i+1]-'0'-1] : dizaines[val-1], (index != 1 && 8 == val && '0' == src[i+1])?"s":"", ((7 == val || 9 == val) && (src[i+1]-'0'>6 || '0' == src[i+1]))?"-dix":"");
                strcat(dst, buf);
            }
            if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
                i += 2;
                SIndex -= 2;
                strcat(dst, " ");
            } else {
                ++i;
                --SIndex;
            }
        }
        if (1 == SIndex) {
            int val = src[i]-'0';
            if (!(srcLen == 4 && val == 1 && 0 == i)) {
                char buf[50];
                sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
                strcat(dst, buf);
            }
            ++i;
        }
        if (index > 0 && srcLen > 3 &&(src[i-1] != '0' || src[i-2] != '0' || src[i-3] != '0')) {
            char buf[50] = {0};
            sprintf(buf, "%s%s ", centaines[index], (index >1 && (src[i-1]-'0'>1 || src[i-2]-'0'>0 || src[i-3]-'0'>0))?"s":"");
            strcat(dst, buf);
        }
        SIndex = 3;
    }
}

int
main (void) {
    char * input;
    char NombreEnLettres[500] = {""};
    signed char bool;
	
    input = malloc(TAILLE_MAX+1);
	
    /* On s'ocuppe de la saisie de l'utilisateur */
    bool = 0;
    puts("max : 999 999 999 999 999 999 999 999\nexemples: 1 000 000, 1000000");
    while (bool == 0) {
        puts("Saisissez votre nombre :");
        if (scanf(" %"xstr(TAILLE_MAX)"[0-9 ][^\n]", input) == 1) {
            int c;
            if ((c = getchar()) != '\n') { /* Saisie trop longue */
                fprintf(stderr, "Erreur : Nombre trop long\n");
                clean_stdin();
            } else {
                bool = 1;
            }
        } else {
            fprintf(stderr, "Erreur : Echec de la saisie\n");
            clean_stdin();
        }
    }
	
    z0zero(input, NombreEnLettres);
    printf("%s\n", NombreEnLettres);
	
    free(input);
	
    return EXIT_SUCCESS;
}
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 20:10:37

Et non, tu n'as pas la bonne.

$ diff main.c txt
119c119
<                 sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1] != '0' && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
---
>                 sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 21:06:14

Si tu penses franchement que j'ai vu quelque chose de modifié là-dedans :p
Ca m'a l'air correct :)
Maintenant tu peux essayer de régler les espaces en trop ^^
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
7 janvier 2010 à 21:15:27

OBTW, l'ordre des grands nombre c'est pas million-milliard-billion-trillion-quadrillion-etc. c'est million-ard billion-ard trillion-ard etc. (@Lithrein)
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 21:22:12

Citation : ttthebest

OBTW, l'ordre des grands nombre c'est pas million-milliard-billion-trillion-quadrillion-etc. c'est million-ard billion-ard trillion-ard etc. (@Lithrein)


Je fais seulement confiance à mon dictionnaire ...

Citation : Pouet_forever

Si tu penses franchement que j'ai vu quelque chose de modifié là-dedans :p


C'est pour ça que j'ai utilisé diff.

Citation : Pouet_forever

Maintenant tu peux essayer de régler les espaces en trop ^^


Oui, mais c'est pas si simple :lol: .

Edit : Pas si difficile finalement.
/**
 * Attention : si vous etes sous GNU/Linux pensez à liez les fonctions mathématiques avec -lm pour libm.so
 * Attention : if you're under a GNU/Linux system, think to link mathematical functions with -lm for libm.so
 * Ex : gcc -Wall -Wextra -lm main.c
 * Todo : fixer : bug espace
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define xstr(s) str(s)
#define str(s) #s

#define TAILLE_MAX 100

void
clean_stdin (void) {
    int c;
    while ((c=getchar()) != '\n' && c != EOF);
}

void
trim (char * s) {
    int NbSpace = 0;
    int i, j;
    size_t sLen;
    char * tmp;

    sLen = strlen(s);

    for (i=0 ; s[i] ; ++i) { /* Détermination du nombre d'espaces */
        NbSpace = (s[i] == ' ')? NbSpace+1 : NbSpace;
    }
    if (0 == NbSpace) {
        return;
    }
    tmp = malloc(sLen-NbSpace+1);
    for (i=0, j=0; s[i]; ++i) { /* Création de la nouvelle chaine */
        if (s[i] != ' ') {
            tmp[j] = s[i];
            ++j;
        }
    }
    tmp[sLen-NbSpace] = '\0';

    for (i=0 ; tmp[i] ; ++i) { /* Overwrite sur l'ancien chaine */
        s[i] = tmp[i];
    }
    for(; s[i] ; ++i) { /* On complète avec des 0 pour avoir une chaîne standard */
        s[i] = '\0';
    }
    free(tmp);
}

void
z0zero (char * src, char * dst) {
    const char * unites[10] = {"zero", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"};
    const char * unites_irr[6] = {"onze", "douze", "treize", "quatorze", "quinze", "seize"};
    const char * dizaines[10] = {"dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"};
    const char * centaines[8] = {"cent", "mille", "million", "milliard", "billion", "trillion", "quatrillion", "quintillion"};
    int index, SIndex, i;
    char srcLen;

    trim(src); /* Suppression des espaces */
    srcLen = strlen(src);

    if (srcLen > 24) {
        fprintf(stderr, "Erreur : Votre nombre est trop grand");
        return;
    }

    /* Multiple de 3 le plus proche */
    if (0 == srcLen%3) {
        index = srcLen/3;
    } else {
        index = floor(srcLen/3.0);
    }
    if (0 == (srcLen-index*3)%3) { /* Le premier chiffre est : */
        SIndex = 3; /* Une centaine */
    } else if (0 == (srcLen-index*3)%2) {
        SIndex = 2; /* Une dizaine */
    } else {
        SIndex = 1; /* Une unite */
    }

    for (i=0 ; src[i];) {
        if (3 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50] = {0};
                sprintf(buf, "%s%s%s%s ", (val>1)?unites[val]:"", (val>1)?" ":"" , centaines[0], (index != 2 && '0' == src[i+1] && '0' == src[i+2] && val > 1)? "s" : "");
                strcat(dst, buf);
            }
            ++i;
            --index;
            --SIndex;
        }
        if (2 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50];
                sprintf(buf, "%s%s%s", (1 == val && src[i+1]-'0'> 0 && src[i+1]-'0'< 7)? unites_irr[src[i+1]-'0'-1] : dizaines[val-1], (index != 1 && 8 == val && '0' == src[i+1])?"s":"", ((7 == val || 9 == val) && (src[i+1]-'0'>6 || '0' == src[i+1]))?"-dix":"");
                strcat(dst, buf);
                if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
                    strcat(dst, " ");
                }
            }
            if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
                i += 2;
                SIndex -= 2;
            } else {
                ++i;
                --SIndex;
            }
        }
        if (1 == SIndex) {
            int val = src[i]-'0';
            if (!(srcLen == 4 && val == 1 && 0 == i)) {
                char buf[50];
                sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1] != '0' && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
                strcat(dst, buf);
            }
            ++i;
        }
        if (index > 0 && srcLen > 3 &&(src[i-1] != '0' || src[i-2] != '0' || src[i-3] != '0')) {
            char buf[50] = {0};
            sprintf(buf, "%s%s ", centaines[index], (index >1 && (src[i-1]-'0'>1 || src[i-2]-'0'>0 || src[i-3]-'0'>0))?"s":"");
            strcat(dst, buf);
        }
        SIndex = 3;
    }
}

int
main (void) {
    char * input;
    char NombreEnLettres[500] = {""};
    signed char bool;

    input = malloc(TAILLE_MAX+1);

    /* On s'ocuppe de la saisie de l'utilisateur */
    bool = 0;
    puts("max : 999 999 999 999 999 999 999 999\nexemples: 1 000 000, 1000000");
    while (bool == 0) {
        puts("Saisissez votre nombre :");
        if (scanf(" %"xstr(TAILLE_MAX)"[0-9 ][^\n]", input) == 1) {
            int c;
            if ((c = getchar()) != '\n') { /* Saisie trop longue */
                fprintf(stderr, "Erreur : Nombre trop long\n");
                clean_stdin();
            } else {
                bool = 1;
            }
        } else {
            fprintf(stderr, "Erreur : Echec de la saisie\n");
            clean_stdin();
        }
    }

    z0zero(input, NombreEnLettres);
    printf("%s\n", NombreEnLettres);

    free(input);

    return EXIT_SUCCESS;
}
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
7 janvier 2010 à 21:37:48

Ah, diff... Ça me fait penser à un pote sous Linux qui code avec moi, et qui a essayé de me faire installer plein de trucs genre fink&co jusqu'à ce que je découvre opendiff, qui roxxe...
  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 22:57:51

Citation : Lithrein



Edit : Pas si difficile finalement.



Je n'ai pas vu de sortie erronée. Mais je trouve ton code peu lisible (pas dans la forme mais dans le fond). Des pâtés comme ça :

if (!(srcLen == 4 && val == 1 && 0 == i)) {
                char buf[50];
                sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1] != '0' && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
                strcat(dst, buf);
            }


sont plutôt indigestes.

Ne pas tester le retour de malloc, c'est donner le mauvais exemple.

Ta gestion des entrées de façon sécurisée avec gestion de l'erreur est plus qu'honorable. Il reste néanmoins encore quelques erreurs :


max : 999 999 999 999 999 999 999 999
exemples: 1 000 000, 1000000
Saisissez votre nombre :
0000063
zero million soixante-trois


candide@candide-desktop:~$ ./x
max : 999 999 999 999 999 999 999 999
exemples: 1 000 000, 1000000
Saisissez votre nombre :
000

candide@candide-desktop:~$ ./x

  • Partager sur Facebook
  • Partager sur Twitter
7 janvier 2010 à 23:13:43

Citation : candide

Ne pas tester le retour de malloc, c'est donner le mauvais exemple.


En effet, grave erreur de ma part. (En voulant aller trop vite on fait de belles bêtises)

Citation : candide

Il reste néanmoins encore quelques erreurs


En effet, je ne retire pas les zéros au début du nombre proposé (et il ne faut jamais faire confiance à l'utilisateur), je vais le rajouter.

Je reconnais que mon code source a une légère tendance a être illisible et peu digeste. cf les sprintfs
Je le réécrirai de manière plus compréhensible dés j'aurais le temps.
  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 8:53:46

A mon tour de vous proposer ma version actuelle. :)

Une première version(trop)commentée.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LEN         256

char *sauterZeros(char *s)
{
    while (*s == '0')
        ++s;

    return s;
}


void nombre1chiffre(char *s, int n)
{
    char *s_chiffres[] =
    {
        "zero", "un", "deux", "trois", "quatre", "cinq",
        "six", "sept", "huit", "neuf",
    };

    strcat(s, s_chiffres[n]);
}


void nombre2chiffres(char *s, int n, int p)
{
    char *s_dizaines[] =
    {
        "vingt", "trente", "quarante", "cinquante",
        "soixante", "soixante", "quatre-vingt", "quatre-vingt"
    };

    /* Nombre entre 10 et 19 (première dizaine) */
    char *s_pdizaines[] =
    {
        "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize",
        "dix-sept", "dix-huit", "dix-neuf",
    };

    ldiv_t d = ldiv(n, 10);

    if (d.quot > 1)
    {
        /* Le nombre est supérieur ou égal à 10 */
        /* 20 est à l'indice 0 dans notre tableau, c'est pourquoi on soustrait
         * 2 à notre chiffre des dizaines pour obtenir l'index correct de sa
         * représentation en lettre */
        strcat(s, s_dizaines[d.quot - 2]);

        if (d.quot == 7 || d.quot == 9)
        {
            /* Le nombre est dans l'ensemble [70, 79] U [90, 99]
             * On concatenera onze pour 1, douze pour 2... etc...
             */
            n = d.rem + 10;
        }
        if (d.quot == 8 && d.rem == 0)
        {
            /* 20 s'accorde quand ils est multiplié par un nombre sans être
             * suivis par un autre nombre : quatre-vingts, quatre-vingt un.
             */
            if (p != 1)
                strcat(s, "s");
        }
        if (d.rem >= 1 || (d.rem == 0 && (d.quot == 7 || d.quot == 9)))
        {
            /* On est en présence d'un nombre composé */

            if (d.rem == 1 && d.quot != 8 && d.quot != 9)
            {
                /* Pour les nombres se terminant en 1, on ajoute la conjonction
                 * et.
                 * 81 et 91 sont écrits avec un trait d'union:
                 */
                strcat(s, " et ");
            }
            else
            {
                /* Prennent un trait d'union tous les nombres composés
                 * inférieurs à 100 ne se terminant pas en 1 sauf 81 et 91
                 */
                strcat(s, "-");
            }
        }
    }

    /* On affiche la partie droite de notre nombre, si besoin */
    if (n >= 10 && n <= 19)
    {
        /* On se trouve dans l'intervalle [10, 19] */
        strcat(s, s_pdizaines[n - 10]);
    }
    else if (d.rem > 0 || d.quot == 0)
    {
        /* S'il y a un reste, il y a obligatoirement un chiffre à concatèner.
         * Si le reste est nul et que le quotient est égal à 0, le paramètre
         * n a la valeur 0, on concatène sa traduction.
         */
        nombre1chiffre(s, d.rem);
    }
}



void nombre3chiffres(char *s, int n, int p)
{
    ldiv_t d = ldiv(n, 100);

    if (d.quot == 0)
    {
        /* Le nombre était inférieur à 100.*/
        if (p != 1 || d.rem > 1)
            nombre2chiffres(s, n, p);
    }
    else
    {
        /* Le nombre est supérieur ou égal à 100 */
        if (d.quot > 1)
        {
            /* Le nombre est supérieur ou égal 200
             * On concatène le nombre de centaines, suivi d'un espace.
             */
            nombre1chiffre(s, d.quot);
            strcat(s, " ");
        }

        /* On ajoute le mot cent */
        strcat(s, "cent");

        if (d.quot > 1 && d.rem == 0)
        {
            /* 100 s'accorde quand il est multiplié par un nombre sans être
             * suivis par un autre nombre : deux cents, deux cent un.
             */
            if (p != 1)
                strcat(s, "s");
        }
        else if (d.rem > 0)
        {
            strcat(s, " ");
            nombre2chiffres(s, d.rem, p);
        }
    }
}

char *z0zero(char *src, char *dst)
{
    char const *s_p3[] =
    {
        "mille", "million", "milliard"
    };
    int n;
    
    /* On s'assure que la chaîne des destination débute bien par '\0' */
    dst[0] = '\0';
    /* on saute les zéros inutiles */
    src = sauterZeros(src);

    /* Nombre de chiffre de la chaîne source */
    n = strlen(src);
    if (strlen(src) == 0)
    {
        /* cas particulier du zéro. */
        nombre1chiffre(dst, 0);
    }
    else
    {
        int q, r;

        /* Tant que le nombre actuel à plus de trois chiffres */
        while (n > 3)
        {
            char s_q[4] = {0};
            int nq;
            /* Groupe courant */
            int p = n / 3;
            if (n % 3 == 0)
                p--;
            /* Nombre de chiffres du groupe courant */
            nq = n - p * 3;
            /* On copie le groupe courant dans une chaîne temporaire */
            strncpy(s_q, src, nq);
            /* On convertit le groupe courant en entier */
            q = strtol(s_q, NULL, 10);
            /* On convertit la partie droite du nombre en entier */
            r = strtol(src + nq, NULL, 10);
            /* On traduit le groupe courant en mot */
            nombre3chiffres(dst, q, p);
            if (q > 1 || p != 1)
                strcat(dst, " ");
            /* On ajoute la traduction de la puissance de 1000
             * correspondant au groupe actuel
             */
            strcat(dst, s_p3[p - 1]);
            /* mille est invariables, les autres, non */
            if (p != 1 && q > 1)
                strcat (dst, "s");
            /* Si la traduction n'est pas terminée, on ajoute un espace */
            if (r != 0)
                strcat(dst, " ");

            /* On saute les zéros devenus inutiles dans la partie restante */
            src = sauterZeros(src + nq);
            /* Nouvelle longueur de la chaîne */
            n = strlen(src);
        }
        /* dernier groupe, les centaines. */
        if (n > 0)
            nombre3chiffres(dst, strtol(src, NULL, 10), 0);

    }
    return dst;
}


int main(void)
{
    char s[] = "80000000";
    char res[MAX_LEN] = {0};

    printf("%s -> %s\n", s, z0zero(s, res));

    return 0;
}


Une autre, sans commentaires
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LEN         256

char *sauterZeros(char *s)
{
    while (*s == '0')
        ++s;

    return s;
}


void nombre1chiffre(char *s, int n)
{
    char *s_chiffres[] =
    {
        "zero", "un", "deux", "trois", "quatre", "cinq",
        "six", "sept", "huit", "neuf",
    };

    strcat(s, s_chiffres[n]);
}


void nombre2chiffres(char *s, int n, int p)
{
    char *s_dizaines[] =
    {
        "vingt", "trente", "quarante", "cinquante",
        "soixante", "soixante", "quatre-vingt", "quatre-vingt"
    };

    char *s_pdizaines[] =
    {
        "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize",
        "dix-sept", "dix-huit", "dix-neuf",
    };

    ldiv_t d = ldiv(n, 10);

    if (d.quot > 1)
    {
        strcat(s, s_dizaines[d.quot - 2]);

        if (d.quot == 7 || d.quot == 9)
            n = d.rem + 10;

        if (d.quot == 8 && d.rem == 0)
            if (p != 1)
                strcat(s, "s");

        if (d.rem >= 1 || (d.rem == 0 && (d.quot == 7 || d.quot == 9)))
            strcat(s, d.rem == 1 && d.quot != 8 && d.quot != 9 ? " et " : "-");
    }

    if (n >= 10 && n <= 19)
        strcat(s, s_pdizaines[n - 10]);
    else if (d.rem > 0 || d.quot == 0)
        nombre1chiffre(s, d.rem);

}



void nombre3chiffres(char *s, int n, int p)
{
    ldiv_t d = ldiv(n, 100);

    if (d.quot == 0)
    {
        if (p != 1 || d.rem > 1)
            nombre2chiffres(s, n, p);
    }
    else
    {
        if (d.quot > 1)
        {
            nombre1chiffre(s, d.quot);
            strcat(s, " ");
        }

        strcat(s, "cent");

        if (d.quot > 1 && d.rem == 0)
        {
            if (p != 1)
                strcat(s, "s");
        }
        else if (d.rem > 0)
        {
            strcat(s, " ");
            nombre2chiffres(s, d.rem, p);
        }
    }
}

char *z0zero(char *src, char *dst)
{
    char const *s_p3[] =
    {
        "mille", "million", "milliard"
    };
    int n;
    
    dst[0] = '\0';
    src = sauterZeros(src);
    n = strlen(src);
    if (n == 0)
        nombre1chiffre(dst, 0);
    else
    {
        int q, r;

        while (n > 3)
        {
            int nq;
            int p = n / 3;
            char s_q[4] = {0};
            if (n % 3 == 0)
                p--;

            nq = n - p * 3;

            strncpy(s_q, src, nq);
            q = strtol(s_q, NULL, 10);
            r = strtol(src + nq, NULL, 10);
            nombre3chiffres(dst, q, p);
            if(q > 1 || p != 1)
                strcat(dst, " ");
            strcat(dst, s_p3[p - 1]);
            if(p != 1 && q > 1)
                strcat (dst, "s");
            if(r != 0)
                strcat(dst, " ");

            src = sauterZeros(src + nq);
            n = strlen(src);
        }

        if (n > 0)
            nombre3chiffres(dst, strtol(src, NULL, 10), 0);
    }
    return dst;
}




int main(void)
{
    char s[] = "10000000001";
    char res[MAX_LEN] = {0};

    printf("%s -> %s\n", s, z0zero(s, res));

    return 0;
}


Aucune gestion d'erreur...
Je suis curieux de savoir si je gère bien tous les cas(on peut(je peux :-°))facilement passer à travers des trucs grossiers), ce qui était loin d'être le cas à mon essai précédent... :-°

a+

edit : 1ère correction, sur le second code... Je ne sais pas pourquoi, je sens que ce ne sera pas la dernière... :-°
edit : Modification apportées aux premier code également...
edit : Erreur signalée par candide corrigée.
idem pour celle de Ph+. >_<
edit: Normalement, plus d'erreurs...
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
8 janvier 2010 à 9:26:38

Je connaissais pas ldiv et ldiv_t c'est bien comme truc ^^
T'as des espaces en trop desfois :D

0000 ->  mille zero
00010 -> dix mille
2001020 -> deux millions  mille vingt
  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 9:40:48

Rhâaa...

Je regarde ça, merci Pouet. :)

Vu! J'édite la version sans commentaire à mon post précédent.

Les corrections ont été apportées sur les 2 versions.
En attendant les prochaines...)
a+
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
8 janvier 2010 à 11:37:22

Citation : GurneyH

A mon tour de vous proposer ma version actuelle. :)



Juste vu cette erreur :

500000000000 -> cinq cents milliard



Je trouve le code bien construit (l'algorithme se lit bien et va à la simplicité).

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 11:47:54

Vu, merci candide, celle là elle était bête, en plus mon code ne correspondait pas aux commentaires... :-°

J'édite les 2 versions de suite.
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
8 janvier 2010 à 12:16:18

@GurneyH: j'ai survolé ton code et j'ai trouvé une petite redondance inutile ^^ :
n = strlen(src);
if (strlen(src) == 0)
    nombre1chiffre(dst, 0);

A part ça, sans le tester, ton code est assez plaisant à lire. ;o)
pH+
  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 14:08:10

Effectivement, le passage que tu montres est bien joli! :-°
C'est dingue, comment je peux passer à coté de trucs comme çà!
En tout cas,

Citation : Ph+


A part ça, sans le tester, ton code est assez plaisant à lire. ;o)


C'est le but. :)
Par contre, tu m'as montré une belle bourde!...
Je corrige plus tard -> dodo :-°
edit : corrigé...
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
8 janvier 2010 à 16:16:17

Je veux des exercices sur les tableaux et les matrices en utilisant les pointeurs svp ! J'ai pas bien compris les pointeurs. :(
  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 17:41:27

Voilà la dernière version sans erreur :
/**
 * Attention : si vous etes sous GNU/Linux pensez à liez les fonctions mathématiques avec -lm pour libm.so
 * Attention : if you're under a GNU/Linux system, think to link mathematical functions with -lm for libm.so
 * Ex : gcc -Wall -Wextra -lm main.c
 * Todo : fixer : bug espace
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define xstr(s) str(s)
#define str(s) #s

#define TAILLE_MAX 100

void
clean_stdin (void) {
    int c;
    while ((c=getchar()) != '\n' && c != EOF);
}

char*
removeZeroes (char * s) {
    size_t sLen = strlen(s), i = 0;
    while ('0' == s[i] && i != sLen-1)
        ++i;

    return s+i;
}

void
trim (char * s) {
    int i, j;

    for (i=j = 0; s[i] != '\0'; i++) {
        s[j] = s[i];
        if (s[i] != ' ')
            j++;
    }
    s[j] = '\0';
}

void
z0zero (char * src, char * dst) {
    const char * unites[10] = {"zero", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"};
    const char * unites_irr[6] = {"onze", "douze", "treize", "quatorze", "quinze", "seize"};
    const char * dizaines[10] = {"dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"};
    const char * centaines[8] = {"cent", "mille", "million", "milliard", "billion", "trillion", "quatrillion", "quintillion"};
    int index, SIndex, i;
    char srcLen;

    trim(src); /* Suppression des espaces */
    src = removeZeroes(src);
    srcLen = strlen(src);

    if (srcLen > 24) {
        fprintf(stderr, "Erreur : Votre nombre est trop grand");
        return;
    }

    /* Multiple de 3 le plus proche */
    if (0 == srcLen%3) {
        index = srcLen/3;
    } else {
        index = floor(srcLen/3.0);
    }
    if (0 == (srcLen-index*3)%3) { /* Le premier chiffre est : */
        SIndex = 3; /* Une centaine */
    } else if (0 == (srcLen-index*3)%2) {
        SIndex = 2; /* Une dizaine */
    } else {
        SIndex = 1; /* Une unite */
    }

    for (i=0 ; src[i];) {
        if (3 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50] = {0};
                sprintf(buf, "%s%s%s%s ", (val>1)?unites[val]:"", (val>1)?" ":"" , centaines[0], (index != 2 && '0' == src[i+1] && '0' == src[i+2] && val > 1)? "s" : "");
                strcat(dst, buf);
            }
            ++i;
            --index;
            --SIndex;
        }
        if (2 == SIndex) {
            int val = src[i]-'0';
            if (val > 0) {
                char buf[50];
                sprintf(buf, "%s%s%s", (1 == val && src[i+1]-'0'> 0 && src[i+1]-'0'< 7)? unites_irr[src[i+1]-'0'-1] : dizaines[val-1], (index != 1 && 8 == val && '0' == src[i+1])?"s":"", ((7 == val || 9 == val) && (src[i+1]-'0'>6 || '0' == src[i+1]))?"-dix":"");
                strcat(dst, buf);
                if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
                    strcat(dst, " ");
                }
            }
            if ((1 == val && src[i+1]-'0'< 7) || '0' == src[i+1] || ((7 == val || 9 == val) && '0' == src[i+1])) { /*Faut-il sauter les unites*/
                i += 2;
                SIndex -= 2;
            } else {
                ++i;
                --SIndex;
            }
        }
        if (1 == SIndex) {
            int val = src[i]-'0';
            if (!(srcLen == 4 && val == 1 && 0 == i)) {
                char buf[50];
                sprintf(buf, "%s%s%s ", (i != 0 && src[i-1] != '0' && (val != 1 || (1 == val && (src[i-1]-'0' == 8 || src[i-1]-'0' == 9))))?"-":"", (i != 0 && 1 == val && src[i-1] != '0' && src[i-1]-'0' != 8 && src[i-1]-'0' != 9)?" et ":"", (i != 0 && (7 == src[i-1]-'0' || 9 == src[i-1]-'0') && val < 7)? unites_irr[val-1] : unites[val]);
                strcat(dst, buf);
            }
            ++i;
        }
        if (index > 0 && srcLen > 3 &&(src[i-1] != '0' || src[i-2] != '0' || src[i-3] != '0')) {
            char buf[50] = {0};
            sprintf(buf, "%s%s ", centaines[index], (index >1 && (src[i-1]-'0'>1 || src[i-2]-'0'>0 || src[i-3]-'0'>0))?"s":"");
            strcat(dst, buf);
        }
        SIndex = 3;
    }
}

int
main (void) {
    char input[TAILLE_MAX+1];
    char NombreEnLettres[500] = {""};
    signed char bool;

    /* On s'ocuppe de la saisie de l'utilisateur */
    bool = 0;
    puts("max : 999 999 999 999 999 999 999 999\nexemples: 1 000 000, 1000000");
    while (bool == 0) {
        puts("Saisissez votre nombre :");
        if (scanf(" %"xstr(TAILLE_MAX)"[0-9 ][^\n]", input) == 1) {
            int c;
            if ((c = getchar()) != '\n') { /* Saisie trop longue */
                fprintf(stderr, "Erreur : Nombre trop long\n");
                clean_stdin();
            } else {
                bool = 1;
            }
        } else {
            fprintf(stderr, "Erreur : Echec de la saisie\n");
            clean_stdin();
        }
    }

    z0zero(input, NombreEnLettres);
    printf("%s\n", NombreEnLettres);

    return EXIT_SUCCESS;
}
  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 21:38:55

Devant la clarté du code de GurneyH je me suis dit que je pouvais sûrement améliorer mon code. Et c'est ce que j'ai fait :D
Je ne décompose plus ma chaîne en partant de la fin mais en partant du début (fini la boucle infernale :p )
J'ai repris l'idée du ldiv_t (que je ne connaissais pas ^^ )

Voilà mon code bien éclairci je trouve :

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

#define LEN_MAX_100 100
#define LEN_MAX_500 500

/* Fonction qui supprime les espaces et les 0 en trop. */

void supp_espaces(char *src, char *str) {
	int i, j;
	int zero = 1;
	for (i=j = 0; src[i] != '\0' && j < LEN_MAX_100-1; i++) {
		str[j] = src[i];
		if (src[i] != '0')
			zero = 0;
		else if (src[i] == '0' && zero) {
			continue;
		}
		if (src[i] != ' ')
			j++;
	}
	str[j] = '\0';
}

/* Fonction qui vérifie si le nombre est zéro.
 * Renvoie 1 si le nombre est 0, 0 dans le cas contraire. */

int estZero(char *str) {
	for ( ; *str; str++)
		if (*str != '0')
			return 0;
	return 1;
}

/* Conerti 'i' lettres en nombre. */ 

int convert(char * (*str), int i) {
	int tmp = 0;
	int j;
	
	for (j = 0; j < i && **str; j++, (*str)++) {
		tmp *= 10;
		tmp += **str - '0';
	}
	return tmp;
}

/* Fonction qui renvoie dans 'str' la décomposition du nombre 0 <= nb <= 99 */

void dix(int nb, char *str) {
	char const * const dizaines [10] = {
		"", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante",
		"quatre-vingt", "quatre-vingt"
	};
	char const * const unites [20] = {
		"", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf",
		"dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf"
	};
	
	char tmp[LEN_MAX_100] = "";
	ldiv_t div = ldiv(nb, 10);
	
	if (nb == 0)
		return;
	
	if (nb >= 20)
		strcat(tmp, dizaines[div.quot]);
	
	if (div.rem == 1 && nb >= 20 && div.quot != 8 && div.quot != 9)
		strcat(tmp, " et ");
	else if ((div.rem || nb == 90 || nb == 70) && nb >= 20)
		strcat(tmp, "-");
	
	if ((nb >= 10 && nb < 20) || div.quot == 7 || div.quot == 9)
		strcat(tmp, unites[div.rem+10]);
	else if (div.rem != 0)
		strcat(tmp, unites[div.rem]);
	
	strcat(str, tmp);
}

/* Décompose la centaine du nombre. 0 <= nb <= 999 */

void cent(int nb, char *str) {
	char tmp[LEN_MAX_100] = "";
	ldiv_t div = ldiv(nb, 100);
	
	if (nb > 99) {
		if (div.quot > 1) {
			dix(div.quot, tmp);
			strcat(tmp, " ");
		}
		strcat(tmp, "cent");
		if (div.rem != 0)
			strcat(tmp, " ");
	}
	
	dix(div.rem, tmp);
	
	strcpy(str, tmp);
}

/* Décompose les nombres au dessus de la centaine 0 <= nb <= inf */

void mille(char *res, char *src, ldiv_t div) {
	enum { CENT, MILLE };
	char const * const centaines [7] = {
		"mille", "million", "milliard", "billion", "trillion", "quatrillion", "quintillion"
	};
	char str[LEN_MAX_500] = "";
	int i, tmp;
	ldiv_t div_tmp;
	
	for (i = div.quot; i >= 0; i--) {
		
		tmp = convert(&src, div.rem);
		/* Tout le reste est obligatoirement basé sur 3 chiffres. */
		div.rem = 3;
		
		div_tmp = ldiv(tmp, 100);
		*str = '\0';
		
		if (i != MILLE || (i == MILLE && tmp != 1))
			cent(tmp, str);
		strcat(res, str);
		
		/* Si le nombre = 0 on ne fait rien.
		 * Si le nombre n'est pas mille et se fini par 80 ou ...
		 * ... si le nombre est une centaine entière on met un 's'. */
		if (i != MILLE &&
			((div_tmp.quot > CENT+1 && div_tmp.rem == CENT) || (tmp != 0 && div_tmp.rem == 80)))
			strcat(res, "s");
		
		if (i != CENT && tmp != 0) {
			/* Si le nombre est != de 1000 on met un espace */
			if (i != MILLE || (i == MILLE && tmp != 1))
				strcat(res, " ");
			strcat(res, centaines[i-1]);
			if (i != MILLE && tmp > 1)
				strcat(res, "s");
			strcat(res, " ");
		}
	}
}

char * z0zero(char *src) {
	static char res[LEN_MAX_500];
	char tmp[LEN_MAX_100] = "";
	int len;
	ldiv_t div;
	
	*res = '\0';
	supp_espaces(src, tmp);
	
	if (estZero(tmp)) {
		sprintf(res, "%s", "zero");
		return res;
	}
	
	len = strlen(tmp);
	if (len > 8*3) {
		sprintf(res, "%s", "Erreur: Nombre trop grand.");
		return res;
	}
	div = ldiv(len, 3);
	
	if (div.rem == 0) {
		div.quot--;
		div.rem = 3;
	}
	
	mille(res, tmp, div);
	
	len = strlen(res);
	if (res[len-1] == ' ')
		res[len-1] = '\0';
	
	return res;
}


int main(void) {
	char *x[] =
    { "0", "1", "2", "3", "4", "5", "7", "8", "9", "10", "11", "12", "13",
		"14", "15", "16", "17", "18", "19", "20", "21", "29", "30", "40", "42",
		"51",
		"60", "69", "70", "71", "77", "80", "81", "85", "90", "91", "99", "100",
		"101",
		"110", "130", "173", "196", "200", "205", "217", "223", "256", "268",
		"273",
		"280", "297", "734", "1000", "1001", "1017", "1020", "1032", "1111",
		"2000",
		"2100", "2200", "3003", "3780", "10000", "10005", "10900", "11000",
		"11700",
		"12000", "18805", "61400", "77010", "80000", "80078", "90000", "92002",
		"97459",
		"100000", "100007", "204003", "310857", "700005", "1000000", "2000000",
		"2001001",
		"72424600", "79828480", "200000000", "708000000", "1000000000", "2000000000",
		"2000500000",     "2000780001"
	};
	int i, n = sizeof x / sizeof *x;
	
	for (i = 0; i < n; i++)
    {
		printf("%s.\n",   z0zero(x[i]));
    }
	return EXIT_SUCCESS;
}


Dîtes moi si vous voyez des erreurs :)

@ Lithrein : Je n'ai pas trouvé d'erreurs :)

Edit : Enlèvement d'un paramètre inutile.
Edit2 : Correction d'un petit truc avec 90 ^^
Edit3 : Correction suite aux remarques de candide.
Edit4 : Suppression des espaces de fin inutiles + 70.
  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2010 à 22:33:27

Shareman, stp, tu peux mettre à jour ? :ange:
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !