Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Débuter
Débuter Forum d'entraide pour débuter en langage C. Avant de poster -> FAQ C
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 19/02/2013, 12h12   #1
Luke spywoker
Membre éclairé
 
Avatar de Luke spywoker
 
Homme
Etudiant informatique autodidacte
Inscription : juin 2010
Messages : 591
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Etudiant informatique autodidacte

Informations forums :
Inscription : juin 2010
Messages : 591
Points : 370
Points : 370
Par défaut Problème de calcul et d'affichage de nombres réels

Salut les programmeurs C,

Je continue de découvrir le C mais je n'ai pas encore commencé l'apprentissage de la standard library en profondeur d'où cette question réellement a 2 centimes :

À 2 cents plus exactement car j'ai fait un programme qui calcule ce dont vous avez besoin exactement pour payer une addition :
On entre une somme en Euro et le programme calcule de combien de billets et pièces de chaque sorte vous avez besoin pour avoir l'appoint dont je vous épargne le code source.
Le problème est que je demande l'entrée avec:
Code :
scanf("%f",&euro_entry) ;
Le programme fait des modulo grâce à deux fonctions:
Code :
1
2
3
4
5
6
7
int get_euro_mod(float s, int i) {
  return s/i ;
}
 
int get_cents_mod(float s, float i) {
 return s/i ;
}
successifs décroissant sur la somme entrée.
Code :
1
2
3
4
5
6
 
euro_500=get_euro_mod(euro_entry, 500) ;
euro_entry=euro_entry- (get_euro_mod(euro_entry, 500)*500) ;
// ... 
cents_01=get_cents_mod(euro_entry, 0.01) ;
euro_entry= euro_entry- (get_cents_mod(euro_entry, 0.01)*0.01) ;
J'ai bien essayé de formater l'entrée afin d'avoir un float a deux chiffres, sans succès, après, le point pour que l'appoint soit bon: le résultat est faussé à cause de la longueur de la représentation de la somme entrée.
J'ai clairement identifié le problème venant de scanf() qui ne permet pas de constante tel : "%.2f" ou du moins qui génère des warnings et des erreurs de traitement dans ce cas là.

Merci pour vos réponses.
__________________
Pour faire tes armes:
Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
Et sois toujours bien armé avant de te lancer.
Le hasard ne sourit qu'aux gens préparés...
Blog: http://3dcyberspace.unblog.fr/
Site: Sanctuaire cybernétique
Luke spywoker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2013, 13h42   #2
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 699
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Ingénieur systèmes embarqués
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 699
Points : 4 155
Points : 4 155
Salut,

C'est bien de continuer le C

Tu devrais regarder cette discussion : http://www.developpez.net/forums/d13...es-virgule-lu/

Une solution peut-être de lire avec fgets(), de convertir en un nombre de centimes et de faire les calculs avec des entiers et un facteur de 100.
__________________
Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

Pour vos problèmes d'embarqué, utilisez le forum dédié !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 19/02/2013, 17h52   #3
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Salut
Tu n'as pas bien explique ton soucis mais je pense que je le devine. Je crois que tu es confronte au probleme inherent a tous les ordis et tous les langages a propos du codage des decimaux.
En effet, pour un ordi, un decimal est un nombre code a base de puissances negatives de 2. Donc 0.25 en base 10 etant 2^(-2) sera code 0.01 en base 2.

Mais ce systeme ne marche pas pour tous les nombres et ainsi 0.6 sera code 0.1001001001001. Et dans l'autre sens si on decode ce chiffre, cela ne donne pas exactement 0.6 (cela donne 0.5999999 ou bien 0.6000001).

D'ou la proposition de bktero de travailler exclusivement en centimes (entiers) quitte a convertir lors de la saisie et de l'affichage.

Une autre solution serait d'utiliser une bibliotheque dediee a la gestion des decimaux. Ce genre de bibliotheque (qui existe en natif dans d'autres langages comme Python) code les decimaux chiffre par chiffre et effectue ensuite les calculs comme au primaire (chaque chiffre est pris independemment pour etre calcule avec chaque autre chiffre). Calculs (relativement) longs mais resultats garantis sans erreurs. Je sais qu'il en existe une ecrite en C qu'on peut telecharger et utiliser ensuite facilement dans ses codes C (on en parle parfois sur ce fofo)...
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/02/2013, 00h45   #4
Luke spywoker
Membre éclairé
 
Avatar de Luke spywoker
 
Homme
Etudiant informatique autodidacte
Inscription : juin 2010
Messages : 591
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Etudiant informatique autodidacte

Informations forums :
Inscription : juin 2010
Messages : 591
Points : 370
Points : 370
Merci pour vos réponses,
Je connaissait le problème des nombres a virgule flottante et les problèmes de la représentation binaire de ceux-ci , d'ailleurs j'ai écrit un module en python qui permet de manipuler: additionner, soustraire et multiplier des string binaires et la division ne fait pas partie des fonctions du module justement a cause de ce problème, c'est pas vraiment un module réellement utile mais ca fait un peu de lecture car il ,est documenter et les méthodes de calcules sont calquer sur les règles du calcule binaire vous pouvez éventuellement jeter un œil a mon module:
Module python de manipulation et de calcule de nombres binaires.

Seulement je pensait qu'il existait une possibilité plus trivial avec le format de la constante de scanf, mais comme vous infirmez, il va falloir formater l'entrée comme dit dans la FAQ.

Merci pour vos réponses.
__________________
Pour faire tes armes:
Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
Et sois toujours bien armé avant de te lancer.
Le hasard ne sourit qu'aux gens préparés...
Blog: http://3dcyberspace.unblog.fr/
Site: Sanctuaire cybernétique
Luke spywoker est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 20/02/2013, 14h04   #5
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par Luke spywoker Voir le message
vous pouvez éventuellement jeter un œil a mon module:
Module python de manipulation et de calcule de nombres binaires.
Juste pour le plaisir alors parce que Python possede deja le module "decimal" qui gere de facon complete et exacte les calculs sur nombres decimaux...
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 20/02/2013, 14h58   #6
droggo
Expert Confirmé
 
Inscription : août 2006
Messages : 3 414
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 3 414
Points : 3 769
Points : 3 769
Hai,
Citation:
Envoyé par Sve@r Voir le message
Juste pour le plaisir alors parce que Python possede deja le module "decimal" qui gere de facon complete et exacte les calculs sur nombres decimaux...
De manière générale, ou spécifique pour la monnaie ?

Car si c'est "général", alors c'est impossible : on tombe très souvent sur des nombres qui ont une infinité de décimales, il faut donc bien les limiter quelque part.
__________________
Il court en ce moment une espèce de grippe, mais elle ne court pas très vite, car on peut l'attraper sans courir.
droggo est déconnecté   Envoyer un message privé Réponse avec citation 11
Vieux 20/02/2013, 17h57   #7
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par droggo Voir le message
Hai,

De manière générale, ou spécifique pour la monnaie ?

Car si c'est "général", alors c'est impossible : on tombe très souvent sur des nombres qui ont une infinité de décimales, il faut donc bien les limiter quelque part.
Le module "decimal", comme son nom l'indique, et aussi comme je l'ai mentionne dans mon post qui parlait de la gestion des nombres decimaux dans l'informatique, est la pour traiter les nombres... decimaux c'est a dire des nombres qui peuvent s'exprimer sous forme d'un nombre entier divise par une puissance de 10. Et non pour gerer les nombres rationnels ou irrationnels...

Pour gerer les rationnels je ne sais pas ce que Python propose en natif mais j'ai de mon cote developpe ma propre librairie basee sur les calculs des fractions...
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 21/02/2013, 20h54   #8
Luke spywoker
Membre éclairé
 
Avatar de Luke spywoker
 
Homme
Etudiant informatique autodidacte
Inscription : juin 2010
Messages : 591
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Etudiant informatique autodidacte

Informations forums :
Inscription : juin 2010
Messages : 591
Points : 370
Points : 370
Réponse rapide:
Je n'arrive pas obtenir un float a précision de 2 chiffres après le virgule car écrire:
Code :
1
2
3
4
5
6
7
#include <stdio.h>
#include <stdlib.h>
main() {
  float euro ;
  scanf("%f",&euro) ;
  printf("%f",euro) ;
}
donne :
512.12
512.119995
Et en essayant obtenir la précision a deux chiffres:
Code :
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>
 
main() {
  char *euro ;
  float res ;
  fgets(euro,255,stdin) ;
  res=strtof(euro,NULL) ;
  printf("%f",res) ;
}
J'obtiens le même résultat car je suppose que strtof fait la même opération de transformation sur la chaîne que avec scanf("%f",&euro) ???
Je continuerai a chercher car le problème est plus grave que le formatage des entrées:
j'ai remarquer que mes fonctions subissaient le même sort.
Merci pour vos réponses.
__________________
Pour faire tes armes:
Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
Et sois toujours bien armé avant de te lancer.
Le hasard ne sourit qu'aux gens préparés...
Blog: http://3dcyberspace.unblog.fr/
Site: Sanctuaire cybernétique
Luke spywoker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2013, 08h04   #9
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 699
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Ingénieur systèmes embarqués
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 699
Points : 4 155
Points : 4 155
Citation:
Envoyé par Bktero Voir le message
Tu devrais regarder cette discussion : http://www.developpez.net/forums/d13...es-virgule-lu/

Une solution peut être de lire avec fgets(), de convertir en un nombre de centimes et de faire les calculs avec des entiers et un facteur de 100.



Code :
1
2
char *euro ;
  fgets(euro,255,stdin) ;
L'erreur de segmentation te dira sûrement merci un jour de ne pas allouer 255 octets pour y faire pointer euro !
__________________
Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

Pour vos problèmes d'embarqué, utilisez le forum dédié !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2013, 10h08   #10
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par Luke spywoker Voir le message
Je continuerai a chercher car le problème est plus grave que le formatage des entrées
Oui, c'est le probleme de la conversion des nombres decimaux (plus generalement des nombres flottants) en binaire puis reconversion en decimal. Perte de certaines decimales due a l'imprecision de la methode de conversion.

Code c :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#define PRECISION              (255)
 
int main() {
  char saisie[PRECISION + 1] ;
  unsigned long cents ;
  while(1)
  {
    fgets(saisie, PRECISION + 1, stdin);
    if (sscanf(saisie, "%lu", &cents) == 1) break;
    printf("saisie[%s] incorrecte - recommencez\n", saisie);
  }
  printf("%lu => %.02f",cents, cents / 100.0);
}
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 22/02/2013, 11h31   #11
Luke spywoker
Membre éclairé
 
Avatar de Luke spywoker
 
Homme
Etudiant informatique autodidacte
Inscription : juin 2010
Messages : 591
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Etudiant informatique autodidacte

Informations forums :
Inscription : juin 2010
Messages : 591
Points : 370
Points : 370
Merci pour vos réponses,
pour Bktero :
Citation:
L'erreur de segmentation te dira sûrement merci un jour de ne pas allouer 255 octets pour y faire pointer euro !
Excuser mais je vient du python et quand on parle de longueur on parle souvent de longueur de chaîne de caractères, par ailleurs je n'ai jamais utiliser malloc() et je suis en train de lire un livre qui l'utilise a outrance mais je n'en suis pas encore a la partie: allocation de la mémoire.
Comme un char vaut 1 octet la chaine euro n'a pas besoin de 255 octets effectivement.
mais concernant le float c'est une autre question.

Sve@r merci d'avoir mis en lumière ce que l'on m'avait déjà dit au début du poste: de séparé la partie entière de la partie décimale pour le traitement, seulement je fait avec les moyens du bords pour l'instant mais est je suis tomber sur strtof qui ne change rien au problème comme dit plus haut.

Je vais essayer d'arriver a un résultat exact, merci pour vos réponses éclairées.
__________________
Pour faire tes armes:
Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
Et sois toujours bien armé avant de te lancer.
Le hasard ne sourit qu'aux gens préparés...
Blog: http://3dcyberspace.unblog.fr/
Site: Sanctuaire cybernétique
Luke spywoker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2013, 14h29   #12
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par Luke spywoker Voir le message
Excuser mais je vient du python et quand on parle de longueur on parle souvent de longueur de chaîne de caractères, par ailleurs je n'ai jamais utiliser malloc() et je suis en train de lire un livre qui l'utilise a outrance mais je n'en suis pas encore a la partie: allocation de la mémoire.
Moi je viens du C et suis passe il y a qq temps a Python ben je ne reviendrai pas au C. Devoir reinventer sans cesse la roue et ecrire 40 lignes de C pour faire un append() Python...
En fait, quand tu utilises un pointeur (char *euro), la variable "euro" contient une valeur aleatoire car non initialisee. Mais quand tu demandes de remplir la zone avec n'importe quoi (une saisie, une autre variable, etc), ca va aller direct taper a l'adresse correspondant a cette valeur et commencer a y ecrire. Et la c'est la cata. Cette adresse est peut-etre celle d'une autre variable, etc. Et le pire c'est que si c'est l'adresse d'une autre variable non seulement le compilo ne te dira rien mais ton programme fonctionnera sans planter. Mais il te fera n'importe quoi (on appelle cela "comportement indetermine").
Pour simplifier: chaque fois que tu utilises un pointeur (char *truc), tu n'as pas le droit d'aller ecrire dans la zone pointee (dans "*truc") si tu n'as pas d'abord ecrit "truc=une adresse valide" (bien souvent ce sera truc=malloc(...) ; la fonction malloc te renvoyant l'adresse d'une zone allouee donc forcement valide (sauf si allocation ratee mais c'est un autre soucis)
De mon cote je ne me suis pas embete avec du malloc: j'ai declare un tableau de 255 octets et j'ai indique a fgets() de se limiter a ce nombre (mais definit au debut donc facilement modifiable => une seule modif, une recompilation et tout remarche)...

Citation:
Envoyé par Luke spywoker Voir le message
Sve@r merci d'avoir mis en lumière ce que l'on m'avait déjà dit au début du poste: de séparé la partie entière de la partie décimale pour le traitement, seulement je fait avec les moyens du bords pour l'instant mais est je suis tomber sur strtof qui ne change rien au problème comme dit plus haut.
Petit detail: on ne t'a pas indique de separer les entiers des decimaux ; on t'a conseille de ne travailler qu'en centimes entiers. Apres tout, si la miche de pain coute 1.95E; elle coute alors 195 centimes...
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2013, 17h11   #13
Luke spywoker
Membre éclairé
 
Avatar de Luke spywoker
 
Homme
Etudiant informatique autodidacte
Inscription : juin 2010
Messages : 591
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Etudiant informatique autodidacte

Informations forums :
Inscription : juin 2010
Messages : 591
Points : 370
Points : 370
Brefs je suis parvenue a mes fins grâce a vos bon conseils,
et je suis tellement content d'y être arriver que je vous montre ici le code source final un peu barban d'opérations consécutives répétitives mais c'est le prix a payer pour écrire en C.

J'ai réussi en faisant entré l'utilisateur la somme en euro avec fgets() que dont je sépare le tableau résultant en deux partie:
-la partie entière et la partie décimale.
PS: il n'y a aucune vérification de l'entrée utilisateur et je n'ai pas pris la peine de commenter le code.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAXSIZE 64 
int get_euro_divmod(int f, int i) ;
int get_cents_divmod(int f, int i) ;
main(int argc, char argv[]) {
  int euro_500=0, euro_200=0, euro_100=0,euro_50=0,euro_20=0,euro_10=0, euro_5=0;
  int euro_2=0, euro_1=0 ;
  int cents_50=0, cents_20=0, cents_10=0, cents_5=0, cents_2=0, cents_1=0 ;
  int euro_entry, cents_entry ;
  char entry[MAXSIZE] ;
  char integer_part[]={} ;
  char decimal_part[]={} ;
  int c_entry, c_int_part, c_dec_part, bool ; // c_ == counter_
  printf("Enter the Euros value:\n") ;
  fgets(entry,MAXSIZE,stdin) ;
  c_int_part = c_dec_part = bool= 0 ;
  for (c_entry=0 ; c_entry < ((int) strlen(entry)) ; c_entry++) {
    if (entry[c_entry] == '.') {
      bool=1 ;
      continue ;
    }
    if (bool == 0 ) {
      integer_part[c_int_part]=entry[c_entry] ;
      c_int_part++ ;
    }
    else if (bool == 1 ) { 
      decimal_part[c_dec_part]=entry[c_entry] ;
      c_dec_part++ ;
    }
  }
  integer_part[++c_int_part]='\0' ;
  decimal_part[++c_dec_part]='\0' ;
  //printf("%s.%s",integer_part,decimal_part) ;    
  euro_entry=strtol(integer_part,NULL,10) ;
  cents_entry=strtol(decimal_part,NULL,10) ;
 
  euro_500=get_euro_divmod(euro_entry,500) ;
  euro_entry-=(get_euro_divmod(euro_entry,500) * 500 ) ;
 
  euro_200=get_euro_divmod(euro_entry,200) ;
  euro_entry-=(get_euro_divmod(euro_entry,200) * 200 ) ;
 
  euro_100=get_euro_divmod(euro_entry,100) ;
  euro_entry-=(get_euro_divmod(euro_entry,100) * 100 ) ;
 
  euro_50=get_euro_divmod(euro_entry,50) ;
  euro_entry-=(get_euro_divmod(euro_entry,50) * 50 ) ;
 
  euro_20=get_euro_divmod(euro_entry,20) ;
  euro_entry-=(get_euro_divmod(euro_entry,20) * 20 ) ;
 
  euro_10=get_euro_divmod(euro_entry,10) ;
  euro_entry-=(get_euro_divmod(euro_entry,10) * 10 ) ;
 
  euro_5=get_euro_divmod(euro_entry,5) ;
  euro_entry-=(get_euro_divmod(euro_entry,5) * 5 ) ;
 
  euro_2=get_euro_divmod(euro_entry,2) ;
  euro_entry-=(get_euro_divmod(euro_entry,2) * 2 ) ;
 
  euro_1=get_euro_divmod(euro_entry,1) ;
  euro_entry-=(get_euro_divmod(euro_entry,1) * 1 ) ;
 
  cents_50=get_cents_divmod(cents_entry,50) ;
  cents_entry-=(get_cents_divmod(cents_entry,50) * 50 ) ;
 
  cents_20=get_cents_divmod(cents_entry,20) ;
  cents_entry-=(get_cents_divmod(cents_entry,20) * 20 ) ;
 
  cents_10=get_cents_divmod(cents_entry,10) ;
  cents_entry-=(get_cents_divmod(cents_entry,10) * 10 ) ;
 
  cents_5=get_cents_divmod(cents_entry,5) ;
  cents_entry-=(get_cents_divmod(cents_entry,5) * 5 ) ;
 
  cents_2=get_cents_divmod(cents_entry,2) ;
  cents_entry-=(get_cents_divmod(cents_entry,2) * 2 ) ;
 
  cents_1=get_cents_divmod(cents_entry,1) ;
  cents_entry-=(get_cents_divmod(cents_entry,1) * 1 ) ;
 
  printf("You musst have:\n500.00: %i\n200.00: %i\n100.00: %i\n 50.00: %i\n 20.00: %i\n 10.00: %i\n  5.00: %i\n  2.00: %i\n  1.00: %i\n  0.50: %i\n  0.20: %i\n  0.10: %i\n  0.05: %i\n  0.02: %i\n  0.01: %i\n",euro_500, euro_200, euro_100, euro_50, euro_20, euro_10, euro_5, euro_2, euro_1, cents_50, cents_20, cents_10, cents_5, cents_2,cents_1) ; 
 
 
 
 
}
 
int get_euro_divmod(int f, int i) {
  return f/i ;
}
 
int get_cents_divmod(int f, int i) {
  return f/i ;
}
Si vous voulez faire des remarques donnez vous en a cœur joie je suis tout oui, mais le programme marche.
Merci pour vos réponse et de part ce biais pour votre contribution.
Le problème est résolus.
__________________
Pour faire tes armes:
Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
Et sois toujours bien armé avant de te lancer.
Le hasard ne sourit qu'aux gens préparés...
Blog: http://3dcyberspace.unblog.fr/
Site: Sanctuaire cybernétique
Luke spywoker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/02/2013, 10h04   #14
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par Luke spywoker Voir le message
Si vous voulez faire des remarques donnez vous en a cœur joie je suis tout ouie, mais le programme marche.
Beaucoup de repetitions de code. Et si un jour on rajoute un billet de 25E, faudra faire beaucoup de modifs pour integrer cette nouvelle monnnaie.

La je ne suis pas chez moi mais des mardi, je te montrerai une autre facon de faire bien plus souple et bien plus optimisee basee sur un tableau de structures contenant d'un cote la monnaie a utiliser/diviser et de l'autre le libelle correspondant
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/02/2013, 13h33   #15
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par Sve@r Voir le message
La je ne suis pas chez moi mais des mardi, je te montrerai une autre facon de faire bien plus souple et bien plus optimisee basee sur un tableau de structures contenant d'un cote la monnaie a utiliser/diviser et de l'autre le libelle correspondant
Chose promise...

Code c :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdio.h>
#include <string.h>
 
 
// Structure de découpage
typedef struct {
	char *libelle;
	unsigned long valeur;
	unsigned short nb;
} t_monnaie;
 
// Fonction de nettoyage monnaie
void clean(t_monnaie *monnaie)
{
	t_monnaie *pt;
 
	for (pt=monnaie; pt->libelle != NULL; pt++) pt->nb=0;
}
 
// Fonction de décomposition somme
void calcul(t_monnaie *monnaie, unsigned long somme)
{
	t_monnaie *pt;
	for (pt=monnaie; pt->libelle != NULL; pt++)
	{
		pt->nb=somme / pt->valeur;
		somme%=pt->valeur;
	}
}
 
// Fonction d'affichage somme
void affiche(t_monnaie *monnaie, unsigned long somme)
{
	t_monnaie *pt;
	printf("Pour composer la somme de %.02f, il sera nécessaire d'aligner:\n", somme / 100.0);
	for (pt=monnaie; pt->libelle != NULL; pt++)
	{
		if (pt->nb == 0) continue;
		printf("%u %s\n", pt->nb, pt->libelle);
	}
	fputc('\n', stdout);
}
 
// Fonction de conversion chaine contenant somme euro en centimes
unsigned long convert(char *somme)
{
	char *pt;
	unsigned short cents;
 
	// Recherche "."
	if ((pt=strchr(somme, '.')) != NULL)
	{
		// Blocage de la somme sur ce "."
		*pt='\0';
 
		// Récupération centimes situés après "."
		cents=strtoul(pt+1, NULL, 10);
	}
	else
		cents=0;
 
	// Renvoi somme convertie en centimes
	return strtoul(somme, NULL, 10) * 100 + cents;
}	
 
int main(int argc, char *argv[])
{
    t_monnaie monnaie[]={
		{"billets de 500 €", 50000, 0},
		{"billets de 200 €", 20000, 0},
		{"billets de 100 €", 10000, 0},
		{"billets de 50 €", 5000, 0},
		{"billets de 20 €", 2000, 0},
		{"billets de 10 €", 1000, 0},
		{"billets de 5 €", 500, 0},
		{"pièces de 2 €", 200, 0},
		{"pièces de 1 €", 100, 0},
		{"pièces de 0.5 €", 50, 0},
		{"pièces de 0.2 €", 20, 0},
		{"pièces de 0.1 €", 10, 0},
		{"pièces de 0.05 €", 5, 0},
		{"pièces de 0.02 €", 2, 0},
		{"pièces de 0.01 €", 1, 0},
		{NULL, 0, 0},
	};
 
	char **arg;
	unsigned long cents;
 
	for (arg=argv + 1; *arg; arg++)
	{
		clean(monnaie);
		cents=convert(*arg);
		calcul(monnaie, cents);
		affiche(monnaie, cents);
	}
}

Résultat
Citation:
test.exe 1798.59 352.92
Pour composer la somme de 1798.59, il sera nécessaire d'aligner:
3 billets de 500 €
1 billets de 200 €
1 billets de 50 €
2 billets de 20 €
1 billets de 5 €
1 pièces de 2 €
1 pièces de 1 €
1 pièces de 0.5 €
1 pièces de 0.05 €
2 pièces de 0.02 €

Pour composer la somme de 352.92, il sera nécessaire d'aligner:
1 billets de 200 €
1 billets de 100 €
1 billets de 50 €
1 pièces de 2 €
1 pièces de 0.5 €
2 pièces de 0.2 €
1 pièces de 0.02 €
Le principe: un tableau contenant les éléments à manipuler. Bon là où c'est un poil critiquable, c'est que ce tableau contient à la fois les valeurs et à la fois le résultat pour composer la somme. En fait je voulais que l'utilisateur puisse utiliser le résultat pour autre chose qu'un bête affichage. Mais pour ça une solution bien meilleure aurait été de créer le résultat durant le calcul mais c'était plus compliqué (malloc etc).
Mais à la base ce que je voulais te montrer, c'est que la force de ce genre de code réside dans
  • sa modularité (une fonction pour nettoyer le résultat, une autre pour calculer, une autre pour afficher). Il y en a même une qui se contente de convertir une chaine contenant une somme en € (style "123.45") en centimes (12345). Tu peux donc changer à vonlonté et non plus passer la somme dans la ligne de commande mais la faire saisir à l'utilisateur, cela marche aussi
  • la souplesse du tableau. Déjà inutile de se casser le tronc à connaitre sa taille pour les boucles. Une valeur supplémentaire à NULL et suffit de s'y caler. Ensuite rajoute-lui un billet de 25€ si tu en as envie, tu n'auras rien d'autre à écrire que la ligne adéquate parmi les autres lignes du tableau. Certains pourraient dire que faut penser quand-même à la mettre au bon endroit ce qui est vrai mais un petit qsort() au début peut même pallier à cet inconvénient

Donc voilà. Essaye de t'inspirer de ces principes pour plus tard. Ecrire programme ce n'est pas seulement écrire un code qui fonctionne mais aussi essayer de penser à son évolutivité future...
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 27/02/2013, 09h51   #16
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
Détails du profil
Informations personnelles :
Nom : Homme Pierre
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 1 185
Points : 2 500
Points : 2 500
Une réalisation élégante, j'aime beaucoup.

Par contre, j'aurai typé le "libelle" du t_monnaie en const char*, surtout qu'il est initialisé via une chaine littérale
__________________
Mes principes de bases du codeur qui veut pouvoir dormir:
  • Une variable de moins est une source d'erreur en moins.
  • Un pointeur de moins est une montagne d'erreurs en moins.
  • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
  • La plus sotte des questions est celle qu'on ne pose pas.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2013, 20h25   #17
Sve@r
Expert Confirmé Sénior
 
Avatar de Sve@r
 
Homme Frédéric
Ingénieur développement logiciels
Inscription : février 2006
Messages : 3 495
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Âge : 45
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : février 2006
Messages : 3 495
Points : 6 604
Points : 6 604
Citation:
Envoyé par leternel Voir le message
Une réalisation élégante, j'aime beaucoup.
Merci

Citation:
Envoyé par leternel Voir le message
Par contre, j'aurai typé le "libelle" du t_monnaie en const char*, surtout qu'il est initialisé via une chaine littérale
Arf suis pas trop à l'aise avec "quand mettre les const". Savais même pas qu'on pouvait en mettre dans une structure. On peut alors mettre aussi la valeur en const unsigned long non ???

PS: j'avais oublié de mettre "cents" à 0 dans le cas où la somme n'a pas de ".". J'ai rectifié cet oubli...
__________________
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Tout ce qu'un individu reçoit sans rien faire pour l'obtenir, un autre individu a dû travailler pour le produire sans en tirer profit.
Tout Pouvoir ne peut distribuer aux uns que ce qu'il a préalablement confisqué à d'autres car on n'accroît pas les biens en les divisant.
Quand la moitié d'un peuple croit qu'il ne sert à rien de faire des efforts car l'autre moitié les fera pour elle, et quand cette dernière moitié se dit qu'il ne sert à rien d'en faire car ils bénéficieront à d'autres, cela s'appelle le déclin et la fin d'une nation.
Dr. Adrian Rogers, 1931
Sve@r est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2013, 21h16   #18
ram-0000
Rédacteur/Modérateur

 
Avatar de ram-0000
 
Homme Raymond
Inscription : mai 2007
Messages : 9 036
Détails du profil
Informations personnelles :
Nom : Homme Raymond
Localisation : France

Informations forums :
Inscription : mai 2007
Messages : 9 036
Points : 27 757
Points : 27 757
Citation:
Envoyé par Sve@r Voir le message
la souplesse du tableau. Déjà inutile de se casser le tronc à connaitre sa taille pour les boucles. Une valeur supplémentaire à NULL et suffit de s'y caler. Ensuite rajoute-lui un billet de 25€ si tu en as envie, tu n'auras rien d'autre à écrire que la ligne adéquate parmi les autres lignes du tableau. Certains pourraient dire que faut penser quand-même à la mettre au bon endroit ce qui est vrai mais un petit qsort() au début peut même pallier à cet inconvénient
Un de mes profs disait : "ajoutez de l'intelligence à vos données, il y aura moins de tests et cela sera plus lisible".
__________________
Raymond
Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
e-verbe Un logiciel de conjugaison des verbes de la langue française.

Ma page personnelle sur DVP
.
ram-0000 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2013, 21h55   #19
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 699
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Ingénieur systèmes embarqués
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 699
Points : 4 155
Points : 4 155
Un joli code
__________________
Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

Pour vos problèmes d'embarqué, utilisez le forum dédié !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2013, 11h27   #20
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
Détails du profil
Informations personnelles :
Nom : Homme Pierre
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 1 185
Points : 2 500
Points : 2 500
Citation:
Envoyé par Sve@r Voir le message
Merci

Arf suis pas trop à l'aise avec "quand mettre les const". Savais même pas qu'on pouvait en mettre dans une structure. On peut alors mettre aussi la valeur en const unsigned long non ???
Ce n'est pas difficile, il suffit de choisir son dicton: "const toujours, mute plus tard" ou "dans le doute, const".

en gros, pour un type T, ca donne:
  1. une variable? const si nécessaire
  2. un tableau, const si possible
  3. un pointeur? const T *! sauf pour un passage d'argument par référence variable, bien sûr (typiquement, un pointeur sur un contexte à modifier)
  4. T == char? alors const char *, sauf si la fin du monde est en train de se produire… et encore, dans ce cas là, envisage une solution de rechange
__________________
Mes principes de bases du codeur qui veut pouvoir dormir:
  • Une variable de moins est une source d'erreur en moins.
  • Un pointeur de moins est une montagne d'erreurs en moins.
  • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
  • La plus sotte des questions est celle qu'on ne pose pas.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 01h27.


 
 
 
 
Partenaires

Hébergement Web