Comment faire une chaîne d'opérations
RésoluBonjour tout le monde,
Je développe en C une calculatrice. À ce stade ma calculatrice ne peut additionner, soustraire, multiplier, etc qu'au plus deux valeurs.
Ma préoccupation est de coder en C une calculatrice capable de faire une chaîne d'opérations. c'est-à-dire qu'elle soit de traiter plus que deux valeurs.
Exemple :
- Faire une addition
- Puis utiliser le résultat de cette pour une autre addition ou soustraction ou multiplication ou div..
- etc...
Merci
Android / Chrome 106.0.0.0
20 réponses
Plusieurs échanges portent sur la mise en œuvre d'une chaîne d'opérations dans une calculatrice en C, avec des problèmes issus d'un code très peu structuré et d'erreurs de compilation. Les échanges soulignent notamment l'utilisation de l'affectation dans les conditions if, les avertissements du compilateur et l'emploi de goto non défini, qui rendent le code confus et fragile. Des propositions de résolution avancent de ne pas tester l'affectation, de sauvegarder le résultat précédent dans une mémoire locale et de chaîner les opérations avec une boucle et des fonctions dédiées. En complément, il est suggéré de refactoriser le code autour d'un menu simple et d'éviter les constructions spaghetti, afin de clarifier l'enchaînement des opérations et garantir un comportement reproductible.
-
Bonjour,
Et aujourd'hui, comme notre chère IA a déterré un sujet pas complètement traité et qui soulève des questions intéressantes en C, faisons un peu d'archéologie.
Comme indiqué par [Dal] dans le message #21, une fois la notion de "chaîne d'opérations clarifiées), il faut commencer par réfléchir à la structure de son algorithme avant de se précipiter sur le code. Le code que je propose ci-dessous suit la proposition de [Dal].
#include <stdio.h> // printf, scanf #include <stdlib.h> // strtod #include <string.h> // strncmp typedef enum { INVALID = 0, ADD, SUB, MUL, DIV, } operator_t; double get_operand(){ char buffer[100]; char *read; // Pointera sur la fin de ce qui a été lu avec succès double a; do { printf("Saisir une valeur: "); scanf("%s", buffer); a = strtod(buffer, &read); } while (read == buffer); return a; } operator_t get_operator(){ char buffer[10]; operator_t op; do { printf("Saisir un opérateur (+, -, *, /): "); scanf("%s", buffer); if (!strncmp(buffer, "+", 1)) { op = ADD; } else if (!strncmp(buffer, "-", 1)) { op = SUB; } else if (!strncmp(buffer, "*", 1)) { op = MUL; } else if (!strncmp(buffer, "/", 1)) { op = DIV; } else { fprintf(stderr, "Opérateur %s invalide!\n", buffer); op = INVALID; } } while (op == INVALID); return op; } double add(double a, double b) { return a + b; } double subtract(double a, double b) { return a - b; } double multiply(double a, double b) { return a * b; } double divide(double a, double b) { return a / b; } int main(){ double a, b, r; operator_t op; printf("Bienvenue dans la calculatrice, appuyer sur ctrl+c pour quitter\n"); printf("Les valeurs peuvent être flottantes et/ou négatives\n"); a = get_operand(); while (true) { op = get_operator(); b = get_operand(); switch (op) { case ADD: r = add(a, b); break; case SUB: r = subtract(a, b); break; case MUL: r = multiply(a, b); break; case DIV: r = divide(a, b); break; default: fprintf(stderr, "Operateur (%d) non supporté !\n", op); return 1; } printf("Résultat %lf\n", r); a = r; } return 0; }Design du code
Il est intéressant de pointer quelques éléments sur le code. Comme évoqué par [Dal], il vaut mieux distinguer l'aspect interface (ici le terminal) et le moteur de l'algorithme lui-même. Cela rend le code non seulement plus lisible, mais également plus extensible (par exemple si un jour on souhaite réutiliser ce moteur, mais avec une interface graphique).
Interface utilisateur via le terminal (TUI) et gestion des erreurs
C'est notamment la gestion de cette interface qui va être en charge de valider la saisie correcte de la part de l'utilisateur. Si on avait une calculatrice avec une interface graphique à boutons, il n'y aurait pas les forcément mêmes erreurs possibles. L'interface utilisateur s'assure donc de transmettre des données bien formées au moteur de notre calculatrice. Dans le code proposé, ces aspects sont gérés par deux primitives de lecture :
- get_operand
- get_operator
Pour contrôler qu'une opérande ou un opérateur saisi sont valides, on s'appuie sur une boucle do ... while qui se répète jusqu'à avoir une valeur correcte.
Une fois les données suffisantes collectées pour faire un calcul, on l'effectue (ici dans main) en faisant appel aux fonctions auxiliaires de calcul. Dans le cas présent, ces opérations sont :
- add
- subtract
- multiply
- divide
Intégrité des données
- Chaînes vides : on pourrait contrôler le résultat de scanf. En vrai, c'est inutile, car on va simplement comparer cette chaîne vide avec strncmp et une chaîne attendue (par exemple "+").
- Chaînes comportant des espaces en début ou fin de saisie : on pourrait croire qu'il faut supprimer les espaces avant ou après une opérande ou un opérateur avant de le récupérer (par exemple nettoyer " 12 " pour traiter "12"). En vrai, c'est inutile, strtod le fera pour nous.
- Taille du buffer : un buffer (tampon en bon français) est une zone mémoire de taille fixe (donc dont la taille est connue au moment de compiler). Mais que ce passe-t'il si la taille du buffer est trop petite pour accueillir l'ensemble de la saisie ?
- En pratique il faut faire attention, car si scanf doit écrire dans buffer une chaîne de taille supérieure, on déclenche au mieux une erreur de segmentation (plantage du programme), ou pire une corruption des données (sans erreur de segmentation) qui peut être le début d'un point d'entrée pour une attaque.
- En C, il faut donc toujours être très vigilant à ce qu'on peut légitimement lire et écrire.
- Des outils comme valgrind permettent de détecter ce genre d'erreurs.
- Pour les résoudre, on peut
- Borner la taille de ce qui est écrit : en écrivant scanf("%10s", buffer); lira au plus 10 caractères depuis l'entrée standard, et donc n'écrira jamais plus que 10 caractères + 1 (le '\0` qui marque l'arrêt de la chaîne), ce qui permet de s'assurer que tout va bien si le buffer fait au moins 11 caractères. Attention cependant, car si stdin stocke plus de caractères, les caractères restants seront immédiatement lus par le prochain appel à scanf ne laissant pas à l'utilisateur de saisir une nouvelle valeur. Il faut alors penser à vider stdin avec fflush(stdin);.
- Borner la taille de ce qui est lu : Pour les comparaisons de chaînes, au lieu d'utiliser strcmp, il est préférable d'utiliser strncmp qui permet d'arrête la comparaison étant donnée un nombre de caractère choisi. Si ce nombre de caractère est plus petit que le buffer, strncmp ne risque pas de lire en dehors. Cela évite les erreurs mémoire inhérantes à strcmp quand les chaînes de caractères ne sont pas terminées par '\0` et pouvant conduire à une lecture "en dehors" des chaînes passées en paramètre.
Arité
L'arité d'un opérateur définit son nombre d'opérande. Pour une calculatrice classique, tous les opérateurs sont binaires (+, -, /, *), mais il est important de souligner qu'il y aussi l'opérateur unaire - utilisé pour les valeurs négatives.
Comme ici nous utilisons scanf et lit un double, il n'y a rien de spécial à faire pour traiter l'opérateur unaire -, c'est déjà traité par scanf.
Dès lors, le design proposé par [Dal] dans le message #25 est suffisant et on peut se contenter de l'algorithme de la fonction main.
Cependant, si on devait supposer d'autres opérateurs unaires (par exemple factorielle, pour rappel 6! = 1 * 2 * 3 * .. * 6 ) il faudrait être plus vigilant. Et s'il fallait supporter des opérateurs ternaires (comme par exemple condition ? a : b en langage C, ce serait encore plus complexe.
Division par zéro
Dans le code que je propose, on ne rattrape pas les cas de divisions par zéro. En effet, le type double dispose d'une valeur réservée pour une valeur infinie qui fera ce qu'il faut (c'est ce qu'on appel en algèbre un élément absorbant à gauche pour les opérateurs binaires +, -, *, /).
Bienvenue dans la calculatrice, appuyer sur ctrl+c pour quitter Les valeurs peuvent être flottantes et/ou négatives Saisir une valeur: 2 Saisir un opérateur (+, -, *, /): / Saisir une valeur: 0 Résultat inf Saisir un opérateur (+, -, *, /): + Saisir une valeur: 3 Résultat inf
Priorités des opérateurs (précédence)
En maths, certains opérateurs sont prioritaires sur d'autre, ce qui permet de sous-entendre certaines parenthèses qui deviennent dès lors superflues. Par exemple, 1 + 2 * 3 équivaut en maths à 1 + (2 * 3) = 7.
Dans le code que je propose il n'en est rien, et c'est d'ailleurs le cas pour les petites calculatrices électroniques. On traite de manière gloutonne les opérateurs de gauche à droite. Ainsi l'opération 1 + 2 * 3 est calculée comme (1 + 2) * 3 = 9.
Dans le cas présent, on pourrait s'en sortir en tapant sur la calculatrice 2 * 3 + 1. Mais que faire si on veut calculer 2 * 3 + 4 * 5, qui doit être résolu en (2 * 3) + (4 * 5) = 6 + 20 = 26. Il faut être capable de mémoriser les résultats intermédiaires (ici 6 et 20).
Calculatrice à mémoire
Comme évoqué par PierrotLeFou dans le message #3, pour répondre à ce problème, les calculatrices électroniques utilisent des touches mémoire (que personnellement je n'ai jamais su utiliser !).
Mais alors, comment font des langages comme le C, le python, où même des calculatrices scientifiques pour correctement interpréter une chaîne de caractère impliquant plusieurs opérations avec des p.
Comment bien gérer les parenthèses et les précédences
Le problème des expressions mathématiques écrite "naturellement", c'est qu'il faut définir des priorités et potentiellement recourir à des parenthèses. Heureusement les matheux ont pensé à tout, en proposant la notation polonaise inversée (NPI). En effet, les opérandes et les opérateurs sont ordonnés de sorte à ce qu'il n'y ait aucune ambiguïté possible sur l'ordre dans lequel résoudre les calculs intérmédiaires.
Ainsi, l'expression "2 * 3 + 4 * 5", c'est-à-dire (2 * 3) + (4 * 5)) se réécrit "2 3 * 4 5 * +". Intuitivement, cela revient à encoder un arbre de syntaxe abstraite (AST) dans une chaîne en partant des feuilles et en remontant progressivement vers le racine. On peut alors résoudre les opérations en lisant la chaîne de droite à gauche (les "enchaîner" pour reprendre le terme du message initial) sans se poser de question sur les priorités ou les parenthèses. Mais alors comment convertir une expression mathématique arbitraire en NPI ?
C'est là que l'algorithme de Shunting Yard est un algorithme très élégant permettant de convertir une opération.
- Étant données les spécification d'une algèbre (c'est-à-dire un ensemble muni d'opérations), les spécifications de chaque opération (arité, précédence, règles d'associativité), l'algorithme de Shunting Yard peut réécrire une expression "naturelle" en NPI. En outre, ici c'est l'algèbre des réels qui nous intéresse (R, +, -, *, /) mais on pourrait parfaitement traiter l'algèbre des expressions rationnelles.
- Pour plus de détails, voir cette page (en anglais)
L'algorithme de Shunting Yard est en pratique un peu compliqué à écrire en C, et surtout serait sans doute difficile à lire sans plus d'explication. Je propose aux plus curieux de regarder cette implémentation en Python qui sera plus compacte et donc plus "simple" à lire.
Bonne chance
-
Pour tes if qui fonc des affectations, essaies x=0 et y=0 ...
Si le résultat de l'opération vaut 0, alors le résultat du if est false (faux)Oui. Les if ne servent donc à rien et sont même dangereux.
Ce qui est à l'intérieur des parenthèses du if et qui effectue une affectation à i en appelant de nouveau les fonctions qui effectuent les opérations sur la base des opérandes précédentes "x" et "y" n'a pas de sens non plus. Il faut juste que GgManasse sauvegarde le résultat précédent quelque part (et non pas qu'il refasse l'opération) et effectue la bonne nouvelle opération à partir du résultat précédent et de la nouvelle opérande "d" (sans oublier de sauvegarder le nouveau résultat, qui pourra servir à la prochaine opération.
En fait, GgManasse a juste oublié de prendre un papier et un crayon et de réfléchir à son algorithme avant d'écrire 200 lignes de code confus pollué par ses efforts d'interaction avec l'utilisateur (menus, saisies, boucles maladroites, etc.) qui sont secondaires, et en oubliant l'essentiel.
L'algorithme de base n'est pourtant pas très difficile.
┌───────────┐ │ Res = 0 │ └─────┬─────┘ │ ┌───────▼────────┐ │Obtient Opérande│ └───────┬────────┘ │ ┌──────▼────────┐ │ Res = Opérande│ └──────┬────────┘ │ ┌─────▼───────┐ │ Affiche Res ◄───────────┐ └─────┬───────┘ │ │ │ ┌───────▼─────────┐ │ │Obtient Opérateur│ │ └───────┬─────────┘ │ │ │ ┌──────▼─────────┐ │ │Obtient Opérande│ │ └──────┬─────────┘ │ │ │ ┌───────────▼────────────────┐ │ │ Calcule ├──┘ │Res = Res Opérateur Opérande│ └────────────────────────────┘ -
Les calculatrices ont en général une "mémoire" où tu peux sauver un résultart et le rappeler plus tard
Tu as en général 4 fonction:
M rappeler le contenu de la mémoire.
MC effacer la mémoire
M+ ajouter à la mémoire
M- soustraire de la mémoire -
-
Dans une calculatrice simple la "mémoire" dont parle Pierrot n'est pas nécessairement utilisée pour enchaîner les opérations. Plus simplement, le résultat de la dernière opération est affiché et permet de continuer à appliquer des calculs si on presse une touche correspondant à un opérateur.
On pourrait simuler quelque chose qui y ressemble en C avec une interaction comme suit avec l'utilisateur pour calculer 12 + 34 / 2 et remettre à zéro la calculatrice, puis quitter le programme :
Tapez un nombre (ou Q pour quitter) : >> 12 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> + Tapez un nombre (ou C pour remettre à zéro ou Q pour quitter) : >> 34 Résultat actuel = 46 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> / Tapez un nombre (ou C pour remettre à zéro ou Q pour quitter) : >> 2 Résultat actuel = 23 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> C Résultat actuel = 0 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> Q Le programme est terminé.
-
-
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question -
Excusez-moi c'est ma première fois sur un forum, donc comment je fais pour vous envoyer le code source ?....
Grâce aux fonctions J'ai réussi à utiliser le résultat d'en calculé que je fais moi même pour l'utiliser dans une autre mais je rencontre un problème maintenant. Le nouveau calcul que je fais s'opère très bien mais il s'affiche mal en me donnant également des calculs que je n'ai pas fais, c'est calculs proviennent des conditions (if) que j'ai mis pour pouvoir faire mes autres calcul , mais les instructions (calcul ) de tous ces if s'affiche mm s'il ne sont pas remplies.
Je vous enverrai le code source et le mode d'emploi de la calculatrice des que vous m'aurez dis comment les envoyer
printf("merci");
-
Pour poster ton code sur le forum, tu :
- cliques sur l'icône "Insérer un extrait de code"
- tu choisis le langage C++ dans la liste déroulante
- tu colles ton code et tu valides en cliquant OK
- ton code sera intégré au texte de ton message
- si tu es satisfait de ton message, tu le postes (éventuellement, tu peux le prévisualiser avant pour vérifier de quoi il aura l'air un fois posté, ou pour te relire avant de le poster)
-
#include <stdio.h> #include <math.h> float somme(float a, float b) { float s; s= a+b; return(s); } float soustr(float a, float b) { float s; s= a-b; return(s); } float multi(float a, float b) { float s; s= a*b; return(s); } float division(float a, float b) { float s; if(b!=0) s= a/b; return(s); } int main(){ char reponse, decis; int choix,n; float x, y, a, b, c, delta, z, x1, x2, e, f, g, h, resul, d, i; Acceuil: printf("\n----CALCULATRIX.001-------------------------------------------------------------------------------------\n\n"); printf("1.Calcul de normal\n"); printf("2.Equation second degr : aX+bx-c = x\n"); printf("3.Programme (A + B x C - D)\n--------------------------------------------------------------------------------------------------------"); scanf("%d",&choix); system("cls"); switch(choix) { case 1 : goto CALCUL; break; case 2 : goto EQUATION; break; case 3 : goto PROGRAM; break; } CALCUL: do { printf("-----Calcule Normal----\n\n"); printf("\nSaisiser un nombre :"); scanf("%f", &x); printf("Saisiser un nombre :"); scanf("%f", &y); printf("\nEntrer(1) pour Addition +\n"); printf("Entrer(2) pour Soustraction -\n"); printf("Entrer(3) pour Multiplication *\n"); printf("Entrer(4) pour Division /\n"); printf("Entrer(5) pour la puissance\n"); scanf("%d", &n); switch(n) { case 1 : { printf("La somme de %.f + %.f = %.f ", x,y,somme(x,y)); printf("\n\n\n------------"); break; } case 2 : { printf("La soustraction de %.f - %.f = %.f ", x,y,soustr(x,y)); printf("\n\n\n------------"); break; } case 3 : { printf("La multiplication de %.f x %.f = %.f ", x,y,multi(x,y)); printf("\n\n\n------------"); break; } case 4 : { if(y!=0) printf("La division de %.f/%.f = %f. \n\n\n---------------", x, y, division(x, y)); else printf("La division par 0 est Impossible!"); break; } case 5 : { printf("la puissance est = %.2f ", pow(x,y)); printf("\n\n\n------------"); break; } default: printf("Erreur d'operation"); break; } printf("\nContinuer le cacul_(x)"); printf("\nFaire un autre calcule_(O/N)?\n"); printf("Retour a l'acceuil_(A)\n"); scanf(" %c",&reponse); switch(reponse) { case 'A' : goto Acceuil; break; case 'x' : goto suivant; break; } } while(reponse != 'N'); suivant : getc(stdin); printf("Operateur : "); scanf("%c",&decis); printf("Saisir une valeur : "); scanf("%f", &d); switch(decis) { case '+' : if (i = (somme(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if (i = (soustr(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if (i = (multi(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if (i = (division(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); break; case '-' : if(i = (soustr(x,y))) printf("\n%.f - %.f = %.f", i,d,i - d); break; case '*' : i = (multi(x,y)); printf("%.f x %.f = %.f", i,d,i * d); break; case '/' : i = (division(x,y)); if (d !=0) printf("%.f / %.f = %.4f", i, d, i / d); else printf("Calcul Error : Impossible de diviser par 0\n"); break; default: printf("OPERATEUR INCONNU\n"); break; } printf("\nContinuer le calcul_(x)"); printf("\nFaire un autre calcule_(O/N)?\n"); printf("Retour a l'acceuil_(A)\n"); scanf(" %c",&reponse); switch(reponse) { case 'A' : goto Acceuil; break; } return 0; }-
-
Salut GgManasse,
Sans regarder ton code, en compilant celui-ci avec le compilateur gcc et les Warnings, le compilateur signale des choses qui devraient attirer ton attention :
$ gcc -Wall -Wextra 37724790.c 37724790.c: In function ‘main’: 37724790.c:59:2: warning: implicit declaration of function ‘system’ [-Wimplicit-function-declaration] system("cls"); ^~~~~~ 37724790.c:154:6: warning: suggest parentheses around assignment used as truth value [-Wparentheses] if(i = ( somme(x,y))) ^ 37724790.c:156:6: warning: suggest parentheses around assignment used as truth value [-Wparentheses] if(i = (soustr(x,y))) ^ 37724790.c:158:8: warning: suggest parentheses around assignment used as truth value [-Wparentheses] if(i = (multi(x,y))) ^ 37724790.c:160:6: warning: suggest parentheses around assignment used as truth value [-Wparentheses] if(i = (division(x,y))) ^ 37724790.c:165:6: warning: suggest parentheses around assignment used as truth value [-Wparentheses] if(i = (soustr(x,y))) ^ 37724790.c:69:4: error: label ‘PROGRAM’ used but not defined goto PROGRAM; ^~~~ 37724790.c:66:4: error: label ‘EQUATION’ used but not defined goto EQUATION; ^~~~ 37724790.c:49:46: warning: unused variable ‘resul’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^~~~~ 37724790.c:49:44: warning: unused variable ‘h’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:42: warning: unused variable ‘g’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:40: warning: unused variable ‘f’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:38: warning: unused variable ‘e’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:34: warning: unused variable ‘x2’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^~ 37724790.c:49:30: warning: unused variable ‘x1’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^~ 37724790.c:49:27: warning: unused variable ‘z’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:20: warning: unused variable ‘delta’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^~~~~ 37724790.c:49:17: warning: unused variable ‘c’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:15: warning: unused variable ‘b’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; ^ 37724790.c:49:13: warning: unused variable ‘a’ [-Wunused-variable] float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i;Parmi tous les avertissements il y a en a du type de celui-ci en ligne 154 "warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if(i = ( somme(x,y)))"Est-ce exprès que tu utilises l'opérateur d'affectation = dans ta condition if ?
L'opérateur d'égalité en C est ==
Si tu veux tester l'égalité, tu dois corriger ton code.
Dans les deux cas le code a peu de sens pour moi et je ne comprends pas ce que tu fais.
Ton code ne compile pas non plus chez moi avec gcc, car il comporte ces erreurs là :
37724790.c:69:4: error: label ‘PROGRAM’ used but not defined goto PROGRAM; ^~~~ 37724790.c:66:4: error: label ‘EQUATION’ used but not defined goto EQUATION; ^~~~Ton code est très désorganisé et les goto ne facilitent pas sa compréhension (code "spaghetti").
Je ne ferais pas du tout comme cela.
Comme tu postes 200 lignes de code et que tu indiques juste :
Le nouveau calcul que je fais s'opère très bien mais il s'affiche mal en me donnant également des calculs que je n'ai pas fais, c'est calculs proviennent des conditions (if) que j'ai mis pour pouvoir faire mes autres calcul , mais les instructions (calcul ) de tous ces if s'affiche mm s'il ne sont pas remplies
ce que je comprends qu'il ne fonctionne pas comme tu l'attends, mais tu ne dis pas réellement ce qui arrive, mais ce que tu penses qu'il arrive.
Au lieu d'écrire ce que tu supposes, tu devrais juste indiquer très précisément ce que tu fais lorsque tu l'exécutes avec un exemple précis qui illustre ton problème et que l'on puisse reproduire, qui :
- indique les données que tu fournis en entrée au programme (ici, ce que tu tapes dans les différentes parties de l'exécution du programme)
- le comportement ou données que tu obtiens en sortie et qui ne te convient pas (le résultat faux)
- ce que devrait faire le programme à la place pour te satisfaire (le bon résultat)
Dans ton code il y a ces lignes (qui contiennent d'ailleurs les affectations dans le if) :
printf("Operateur : "); scanf("%c",&decis); printf("Saisir une valeur : "); scanf("%f", &d); switch(decis) { case '+' : if(i = ( somme(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if(i = (soustr(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if(i = (multi(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if(i = (division(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); break;dans cette partie de code, si l'opérateur + est choisi, tu exécutes les fonctions somme(), soustr(), multi() et division() les unes à la suite des autres en affectant le résultat à la variable i.
Tu le fais, d'ailleurs, sans utiliser d qui est la nouvelle opérante, ni utiliser le résultat de la précédente opération qui n'est stocké nulle part (il est juste affiché, par exemple ligne 94 si la première opération est une somme).
d n'est utilisé que dans les nouveaux printf() ci-dessus pour l'affichage, et le résultat de cette nouvelle opération n'est pas non plus stocké, juste affiché. Comme il est utilisé avec le résultat i des fonctions somme(), soustr(), multi() et division() avec les arguments x et y, tu obtiens ces affichages si on tente de faire 12 + 34 + 4.
(x contient 12 - y contient 34 - d contient 4) :
----CALCULATRIX.001------------------------------------------------------------------------------------- 1.Calcul de normal 2.Equation second degr : aX+bx-c = x 3.Programme (A + B x C - D) --------------------------------------------------------------------------------------------------------1 sh: 1: cls: not found -----Calcule Normal---- Saisiser un nombre :12 Saisiser un nombre :34 Entrer(1) pour Addition + Entrer(2) pour Soustraction - Entrer(3) pour Multiplication * Entrer(4) pour Division / Entrer(5) pour la puissance 1 La somme de 12 + 34 = 46 ------------ Continuer le cacul_(x) Faire un autre calcule_(O/N)? Retour a l'acceuil_(A) x Operateur : + Saisir une valeur : 4 ---46 + 4 = 50--- ----22 + 4 = -18--- ---408 + 4 = 412--- ---0 + 4 = 4--- Continuer le cacul_(x) Faire un autre calcule_(O/N)? Retour a l'acceuil_(A)
Il y a aussi un problème pour l'utilisateur, un coup il doit taper 1 pour faire une addition, un coup il doit taper +...
-
-
Merci à vous d'avoir réagi si , de mon côté à cause de l'orage ma connections étai mauvais et avant d'avoir fini il à été envoyé incomplet et le sans mode d'emploi désolé voilà le code que j viens de terminé :
#include <stdio.h> #include <math.h> float somme(float a, float b) { float s; s= a + b; return(s); } float soustr(float a, float b) { float s; s= a - b; return(s); } float multi(float a, float b) { float s; s= a*b; return(s); } float division(float a, float b) { float s; if(b != 0) s = a/b; return(s); } int main() { char reponse, decis; int choix,n; float x, y,a,b,c, delta, z, x1, x2, e,f,g,h,resul,d,i; Acceuil: printf("\n---CALCULATRIX.001\n\n"); printf("1.Calcul de normal\n"); printf("2.Equation second degr : aX+bx-c = x\n"); printf("3.Programme (A + B x C - D)\n---------------------------------------------------------------------------- ----------------------------"); scanf("%d",&choix); system("cls"); switch(choix) { case 1 : goto CALCUL; break; case 2 : goto EQUATION; break; case 3 : goto PROGRAM; break; } CALCUL : do { printf("-----Calcule Normal----\n\n"); printf("\nSaisiser un nombre :"); scanf("%f",&x); printf("Saisiser un nombre :"); scanf("%f",&y); printf("\nEntrer(1) pour Addition +\n"); printf("Entrer(2) pour Soustraction -\n"); printf("Entrer(3) pour Multiplication *\n"); printf("Entrer(4) pour Division /\n"); printf("Entrer(5) pour la puissance\n"); scanf("%d", &n); switch(n) { case 1 : { printf("La somme de %.f + %.f = %.f ", x,y,somme(x,y)); printf("\n\n\n------------"); break; } case 2 : { printf("La soustraction de %.f - %.f = %.f ", x,y,soustr(x,y)); printf("\n\n\n------------"); break; } case 3 : { printf("La multiplication de %.f x %.f = %.f ", x,y,multi(x,y)); printf("\n\n\n------------"); break; } case 4 : { if(y!=0) printf("La division de %.f/%.f = %f. \n\n\n---------------", x, y, division(x, y)); else printf("La division par 0 est Implossible!"); break; } case 5 : { printf("la puissance est = %.2f ", pow(x, y)); printf("\n\n\n------------"); break; } default : printf("Erreur d'operation"); break; } printf("\nContinuer le cacul_(x)"); printf("\nFaire un autre calcule_(O/N)?\n"); printf("Retour a l'acceuil_(A)\n"); scanf(" %c", &reponse); switch(reponse) { case 'A' : goto Acceuil; break; case 'x' : goto suivant; break; } } while(reponse != 'N'); suivant : getc(stdin); printf("Operateur : "); scanf("%c",&decis); printf("Saisir une valeur : "); scanf("%f", &d); switch(decis) { case '+' : if (i = (somme(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if (i = (soustr(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if (i = (multi(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); if (i = (division(x,y))) printf("\n---%.f + %.f = %.f---\n", i,d,i + d); break; case '-' : if(i = (soustr(x,y))) printf("\n%.f - %.f = %.f", i,d,i - d); break; case '*' : i = (multi(x,y)); printf("%.f x %.f = %.f", i,d,i * d); break; case '/' : i = (division(x,y)); if(d !=0) printf("%.f / %.f = %.4f", i,d,i / d); else printf("Calcul Error : Impossible de diviser par 0\n"); break; default : printf("OPERATEUR INCONNUE\n"); break; } printf("\nContinuer le cacul_(x)"); printf("\nFaire un autre calcule_(O/N)?\n"); printf("Retour a l'acceuil_(A)\n"); scanf(" %c",&reponse); switch(reponse) { case 'A' : goto Acceuil; break; } EQUATION : do { printf("------Equation du 2nd degre-----\n"); printf("------(aX + bx - c)------\n\n"); printf("Saisissez les valeurs de a, b et c : \n"); scanf("%f%f%f", &a, &b, &c); delta= pow(b, 2) - (4 * a * c); if (delta < 0) printf("\nD = %.f^2 - 4(%.f x %.f )< 0 \nPas de solution réelles delta étant inférieur à 0\n\n\n", b, a, c); else if (delta == 0) { z = (-b) / (2 * a); printf("\nD = -%.f/2 x %.f = 0 \nDelta étant égal à 0, la solution de x est : %.2f\n\n\n", b, a, z); } else { x1 = (-b - sqrt(delta)) / (2 * a); x2 = (-b + sqrt(delta)) / (2 * a); printf("\n -%.f - V(%.f)\nx1 = -------------\n 2 x %.f\n", b, delta, a); printf("\n -%.f + V(%.f)\nx2 = -------------\n 2 x %.f\n", b, delta, a); printf("les solutions sont : x1= %.2f\n", x1); printf(" x2= %.2f\n\n", x2); printf("\n_____________\n"); } printf("\nVeux-tu faire un autre calcule_(O/N)?\n"); printf("retour a l'acceuil_(A)\n"); scanf(" %c", &reponse); switch(reponse) { case 'A' : goto Acceuil; break; } }while (reponse !='N'); PROGRAM: do { printf("Calcul (A + B x C - D)\n\n"); printf("donner les valeurs de A, de B, de C et de D : \n"); scanf("%f%f%f%f", &e, &f, &g, &h); resul = (f * g + e - h); if(resul>=0) { printf("[ %.f + %.f x %.f - %.f ] = %.f\n", e,f,g,h,resul); printf("\n---------------\n"); } printf("\nVeux-tu faire un autre calcul (O/N)?\n"); printf("Retour à l'acceuil (A)\n"); scanf(" %c", &reponse); switch(reponse) { case 'A': goto Acceuil; break; } } while(reponse != 'N'); return 0; }Mode d'emploi :
Il y a trois options le problème dans mon programme se trouve au niveau de l'Option 1 ( Calcul normal) lors que l'on veut "continuer le Calcul" en entrant ('x') toute les autres conditions s'affiche comme j l'ais dit
-
Ensuite par rapport à la remarque sur les parenthèses lorsque j compile dans mon ordi sa me signale rien bizarrement,
Et lorsque que j'utilise (==) dans le if(i==somme(x,y)) j remarques que le if ne fonctionne pas , j'attends vos constats sur le code source, teste le aux gré de vos modifications et faite moi part de vos remarques.
-
Ha oui [Dal] ,j n'ais terminé mon code Source en mettant d'autres if dans les autres "CASE" parce les if du premier "CASE'+' : ne fonctionnait pas correctement, ça aurait été inutile d'occasionner plus d'erreurs
-
C'est du C ou de l'assembleur genre spaguetti? Même si les goto sont valides en C, ça donne du code horrible.
Tu devrais utiliser plus de fonctions pour afficher tes menus et faire les différentes actions.
Ça serait plus facile à lire et mettre au point.Ton main ne devrait contenir qu'un seul switch sans renvoi à un autre ...
-
Salut GgManasse,
Tu devrais lire avec attention mes précédents messages qui contiennent mes "constats" sur ton code source. Si tu ne tiens pas compte de ces observations pour améliorer ton propre code, c'est un peu dommage.
Reste que, comme je l'ai dit, je ne ferais pas du tout comme cela et je ne crois pas que partir de ton code soit une bonne idée. Il y a des nombreuses incohérences dans ton code et j'en ai mentionné une partie. En ce qui me concerne, je ferais table rase et réfléchirais à une bonne architecture et aux données dont on a besoin.
Tout d'abord, tes fonctions somme(), soustr(), etc. ne sont pas très utiles. Il te suffit de faire ceci.
double make_calculation(double op1, char operator, double op2) { double res; switch (operator) { case '+': res = op1 + op2; break; case '-': res = op1 - op2; break; case '*': res = op1 * op2; break; case '/': res = op1 / op2; break; }; return res; }Tu dois aussi comprendre que la calculatrice que tu dois faire est une machine à états finis. Elle démarre à un état, et passe d'un état à un autre selon ce qui est tapé sur la calculatrice, celle-ci devant garder la trace :
- du stade auquel elle se trouve
- du résultat actuel
- de l'opérateur précédemment saisi
Ce genre d'informations peut être avantageusement regroupé dans une struct, comme celle-ci, au lieu d'être éparpillées dans le code :
struct calc { enum calc_state state; double res; char operator; };qui peut être passée à des fonctions qui traitent les fonctions d'affichage et qui traitent la saisie de l'utilisateur en faisant varier l'état.
avec un enum répertoriant les états possibles, par exemple :
enum calc_state { STATE_C, STATE_OPERATOR, STATE_RESULT };Sur la base de ces exemples, on peut faire un code qui initialise les données de départ descriptives de l'état de la calculatrice void calc_init(struct calc * c) et une fonction void calc_enter(struct calc * c, char * s) qui prend en entrée les données descriptives de l'état de la calculatrice et la saisie de l'utilisateur et fait varier les données descriptives de l'état de la calculatrice selon ce qui est tapé.
Voilà ce que cela donne comme conception, avec ces fonctions à implémenter, ainsi que leurs fonctions auxiliaires :
#include <stdio.h> #include <stdlib.h> #include <assert.h> enum calc_state { STATE_C, STATE_OPERATOR, STATE_RESULT }; char * calc_instructions[] = { [STATE_C] = "Tapez un nombre (ou Q pour quitter)", [STATE_RESULT] = "Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter)", [STATE_OPERATOR] = "Tapez un nombre (ou Q pour quitter)" }; enum calc_entry_type { TYPE_OPERAND, TYPE_OPERATOR, TYPE_COMMAND, TYPE_UNKNOWN }; char valid_operators[] = "+-*/"; char valid_commands[] = "CQ"; struct calc { enum calc_state state; double res; char operator; }; void calc_init(struct calc * c) { c->state = STATE_C; c->res = 0.0; c->operator = ' '; } void calc_display(struct calc * c) { if (c->state == STATE_RESULT) printf("= %f\n", c->res); printf("%s\n", calc_instructions[c->state]); } int is_valid_double(double * d, char * s) { /* TODO */ } int is_valid_operator(char * c, char * s) { /* TODO */ } double make_calculation(double op1, char operator, double op2) { double res; switch (operator) { case '+': res = op1 + op2; break; case '-': res = op1 - op2; break; case '*': res = op1 * op2; break; case '/': res = op1 / op2; break; }; return res; } void calc_enter(struct calc * c, char * s){ /* TODO */ } int main(void) { { struct calc c; calc_init(&c); calc_display(&c); assert(c.state == STATE_C); printf(">> %s\n", "12"); calc_enter(&c, "12"); calc_display(&c); assert(c.res == 12); assert(c.state == STATE_RESULT); printf(">> %s\n", "+"); calc_enter(&c, "+"); calc_display(&c); assert(c.operator == '+'); assert(c.state == STATE_OPERATOR); printf(">> %s\n", "34"); calc_enter(&c, "34"); calc_display(&c); assert(c.res == 46); assert(c.state == STATE_RESULT); printf(">> %s\n", "/"); calc_enter(&c, "/"); calc_display(&c); printf(">> %s\n", "2"); calc_enter(&c, "2"); calc_display(&c); assert(c.res == 23); assert(c.state == STATE_RESULT); printf(">> %s\n", "*"); calc_enter(&c, "*"); calc_display(&c); printf(">> %s\n", "3"); calc_enter(&c, "3"); calc_display(&c); assert(c.res == 69); assert(c.state == STATE_RESULT); } return 0; }Les fonctions calc_enter() et les deux fonctions auxiliaires is_valid_double() et is_valid_operator() sont à implémenter.
is_valid_double() et is_valid_operator() permettent de vérifier qu'une chaîne de caractère saisie est un double (cela se fait en 5 lignes) ou que c'est un des opérateurs supportés par ta calculatrice (9 lignes).
Une fois cela fait, la fonction calc_enter() qui prend la saisie de l'utilisateur et fait varier les données descriptives de l'état de la calculatrice selon ce qui est tapé prend une 20aine de lignes chez moi pour faire passer les tests.
Les tests assert() qui sont dans main() passent alors.
Ils simulent une interaction avec l'utilisateur qui calcule 12 + 34, applique / 2 sur le résultat, et applique * 3 sur le résultat et testent que les les données descriptives de l'état de la calculatrice évoluent de la façon attendue :
Tapez un nombre (ou Q pour quitter) >> 12 = 12.000000 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> + Tapez un nombre (ou Q pour quitter) >> 34 = 46.000000 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> / Tapez un nombre (ou Q pour quitter) >> 2 = 23.000000 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter) >> * Tapez un nombre (ou Q pour quitter) >> 3 = 69.000000 Tapez un opérateur (+, -, * ou / ou C pour remettre à zéro ou Q pour quitter)
Pour rendre le résultat des tests plus parlant, j'ai mis des appels à calc_display(&c); et j'ai mis un printf(">> %s\n", s); dans les tests qui affichent les choses (ces affichages ne sont pas réellement nécessaires).
Quand tu seras arrivé là, il suffirait d'ajouter une fonction traitant les commandes C ou Q pour mettre tout cela dans une boucle interactive gérant un vrai utilisateur humain.
Fais cela en dernier, lorsque tes fonctions seront au point.
Tu peux aussi ignorer cette façon de faire et tenter de déboguer ton code. Pour cela, tu devrais suivre les indications que j'ai déjà données et poster un code modifié.
-
Pour tes if qui fonc des affectations, essaies x=0 et y=0 ...
Si le résultat de l'opération vaut 0, alors le résultat du if est false (faux)
@[dal]: on peut simuler un "cls" qui marche sur tous les systèmes en affichant plusieurs lignes vides. -
#include <stdio.h> #include <math.h> float somme(float a, float b) { float s; s = a + b; return(s); } float soustr(float a, float b) { float s; s = a - b; return(s); } float multi(float a, float b) { float s; s = a * b; return(s); } float division(float a, float b) { float s; if(b != 0) s = a / b; return(s); } int main() { char reponse, decis; int choix,n; float x, y, a, b, c, delta, z, x1, x2, e, f, g, h, resul, d, i; Accueil: printf("\n----CALCULATRIX.001--------------------------\n\n"); printf("1.Calcul de normal\n"); printf("2.Equation second degr : aX+bx-c = x\n"); printf("3.Programme (A + B x C - D)\n---------------------------------------------------------------------------- ----------------------------\n"); scanf("%d",&choix); system("cls"); switch(choix) { case 1 : goto CALCUL; break; case 2 : goto EQUATION; break; case 3 : goto PROGRAM; break; } CALCUL : do { printf("-----Calcule Normal----\n\n"); printf("\nSaisiser un nombre :"); scanf("%f",&x); printf("Saisiser un nombre :"); scanf("%f",&y); printf("\nEntrer(1) pour Addition +\n"); printf("Entrer(2) pour Soustraction -\n"); printf("Entrer(3) pour Multiplication *\n"); printf("Entrer(4) pour Division /\n"); printf("Entrer(5) pour la puissance : "); scanf("%d", &n); switch(n) { case 1 : { printf("La somme de %.f + %.f = %.f ", x,y,somme(x,y)); printf("\n\n\n------------"); i=somme(x,y); break; } case 2 : { printf("La soustraction de %.f - %.f = %.f", x,y,soustr(x,y)); printf("\n\n\n------------"); i=soustr(x, y); break; } case 3 : { printf("La multiplication de %.f x %.f = %.f ", x, y, multi(x, y)); printf("\n\n\n------------"); i = multi(x, y); break; } case 4 : { if(y != 0) printf("La division de %.f/%.f = %.f\n\n\n---------------", x, y, division(x, y)); else printf("La division par 0 est implossible!"); i = division(x, y); break; } case 5 : { printf("la puissance est = %.2f ", pow(x, y)); printf("\n\n\n------------"); break; } default : printf("Erreur d'operation"); break; } printf("\nContinuer le cacul_(x)"); printf("\nFaire un autre calcule_(O/N)?\n"); printf("Retour a l'accueil_(A)\n"); scanf(" %c", &reponse); switch (reponse) { case 'A' : goto Accueil; break; case 'x' : goto suivant; break; } }while (reponse !='N'); suivant : getc(stdin); printf("Operateur : "); scanf("%c",&decis); printf("Saisir une valeur : "); scanf("%f", &d); switch(decis) { case '+' : if (i == somme(x, y)) printf("\n---%.f + %.f = %.4f---\n", i, d, i + d); else if (i == soustr(x, y)) printf("\n---%.f + %.f = %.f---\n", i, d, i + d); else if (i == multi(x, y)) printf("\n---%.f + %.f = %.f---\n", i, d, i + d); else(i == division(x, y)) ; printf("\n---%.f + %.f = %.f---\n", i,d,i + d); break; case '-' : if(i = (soustr(x,y))) printf("\n%.f - %.f = %.f", i, d, i - d); break; case '*' : i = (multi(x,y)); printf("%.f x %.f = %.f", i, d, i * d); break; case '/' : i = (division(x,y)); if(d !=0) printf("%.f / %.f = %.4f", i, d, i / d); else printf("Calcul Error : Impossible de diviser par 0\n"); break; default : printf("OPERATEUR INCONNUE\n"); break; } printf("\nContinuer le calcul (x)"); printf("\nFaire un autre calcul (O/N)?\n"); printf("Retour à l'accueil (A)\n"); scanf(" %c", &reponse); switch(reponse) { case 'A' : goto Accueil; break; } EQUATION : do { printf("------Equation du 2nd degre-----\n"); printf("------(aX + bx - c)------\n\n"); printf("Saisiser les valeurs de a,b et c : \n"); scanf("%f%f%f", &a, &b, &c); delta = pow(b, 2) - (4 * a * c); if (delta < 0) printf("\nD = %.f^2 - 4(%.f x %.f )< 0 \nPas de solution réelles delta étant inférieur à 0\n\n\n", b, a, c); else if (delta == 0) { z = (-b) / (2 * a); printf("\nD = -%.f/2 x %.f = 0 \nDelta étant egal à 0, la solution de x est :%.2f\n\n\n", b, a, z); } else { x1 = (-b - sqrt(delta)) / (2 * a); x2 = (-b + sqrt(delta)) / (2 * a); printf("\n -%.f - V(%.f)\nx1 = -------------\n 2 x %.f\n", b, delta, a); printf("\n -%.f + V(%.f)\nx2 = -------------\n 2 x %.f\n", b, delta, a); printf("les solutions sont : x1= %.2f\n", x1); printf(" x2= %.2f\n\n", x2); printf("\n_____________\n"); } printf("\nVeux-tu faire un autre calcul (O/N)?\n"); printf("Retour à l'accueil (A)\n"); scanf(" %c", &reponse); switch (reponse) { case 'A': goto Accueil; break; } } while (reponse !='N'); PROGRAM: do { printf("Calcul (A + B x C - D)\n\n"); printf("Donner les valeurs de A, de B, de C et de D : \n"); scanf("%f%f%f%f", &e, &f, &g, &h); resul = (f * g + e - h); if (resul >= 0) { printf("[ %.f + %.f x %.f - %.f ] = %.f\n", e, f, g, h, resul); printf("\n---------------\n"); } printf("\nVeux-tu faire un autre calcul (O/N)?\n"); printf("Retour à l'accueil (A)\n"); scanf(" %c", &reponse); switch (reponse) { case 'A': goto Accueil; break; } }while(reponse !='N'); return 0; } -
J'ai corrigé les erreurs cette nuit et donc le problème ( utiliser le résultat d'un calcul pour un autre quelconque Calcul) dans 1.Calcul normal fonction enfin il suffit de faire x après un calcul, j'ai surtout beaucoup réfléchi sur la manière dont mes conditions étaient écrie après que Dal mais fait remarquer que je n'avais pas effectué de variable i pour récupérer les résultats de mes calculs, ha! et encore merci je viens de voir les exemples de code que t'a envoyé.
-
Il ne suffit pas de faire des "patch" sur ton code pour que ça marche.
Il faut repenser ton code au complet comme le suggère[dal] -
-
-
-
Tu n'as pas dû tester très en profondeur.
Voilà deux exemples tirés de mes deux premier tests.
(12 + 34) / 2 = 0.1765 selon ton programme au lieu de 23
-----Calcule Normal---- Saisiser un nombre :12 Saisiser un nombre :34 Entrer(1) pour Addition + Entrer(2) pour Soustraction - Entrer(3) pour Multiplication * Entrer(4) pour Division / Entrer(5) pour la puissance : 1 La somme de 12 + 34 = 46 ------------ Continuer le cacul_(x) Faire un autre calcule_(O/N)? Retour a l'acceuil_(A) x Operateur : / Saisir une valeur : 2 0 / 2 = 0.1765 Continuer le cacul_(x) Faire un autre calcule_(O/N)? Retour a l'acceuil_(A) ^C
Si je veux faire 12 + 34 + 4 + 5 je peux pas continuer l'opération pour faire la dernière addition.
-----Calcule Normal---- Saisiser un nombre :12 Saisiser un nombre :34 Entrer(1) pour Addition + Entrer(2) pour Soustraction - Entrer(3) pour Multiplication * Entrer(4) pour Division / Entrer(5) pour la puissance : 1 La somme de 12 + 34 = 46 ------------ Continuer le cacul_(x) Faire un autre calcule_(O/N)? Retour a l'acceuil_(A) x Operateur : + Saisir une valeur : 4 ---46 + 4 = 50.0000--- ---46 + 4 = 50--- Continuer le cacul_(x) Faire un autre calcule_(O/N)? Retour a l'acceuil_(A) x ------Equation du 2nd degre----- ------(aX + bx - c)------ Saisiser les valeurs de a,b et c :
si je choisis x pour continuer le calcul, le programme affiche "Equation du 2nd degre".
-
Aussi, ton programme tel que tu l'as posté sur le forum ne compile pas chez moi. Pour qu'il compile, j'ai dû rectifier toutes les lignes où le contenu des printf entre guillemets était sur plusieurs lignes sans guillemet fermant sur la ligne ouvrante.
Je ne sais pas si cela est dû à un problème de copier-coller sur le forum.
Par exemple, lignes 96 et 97 du dernier code source que tu as posté.
printf("La division par 0 est Implossible!");Cela ne peut pas compiler. Si on veut mettre un printf trop long sur plusieurs lignes (là ce n'est pas long, mais admettons) il faut écrire l'une de ces deux formes :
/* mettre un antislash en fin de ligne */ printf("La division par 0 est \ impossible !\n"); /* délimiter chaque ligne avec des guillemets */ printf("La division par 0 est " "impossible !\n");Les deux façons de faire sont équivalentes. Le préprocesseur va considérer traiter cela comme une seule et unique chaîne.
Tu pourrais aussi corriger les nombreuses fautes d'orthographe ou de frappe : "cacul", "calcule", "acceuil", "Implossible", "saisiser", "operateur inconnue" (sic).
Ton code n'implémente pas l'algorithme que j'ai donné et tu n'as tenu compte d'aucune de nos autres observations sauf celle concernant le stockage du résultat.
L'utilisation de goto est en général très mal vue (elle est bannie par certains). Dans de rares cas elle est considérée acceptable si elle simplifie le code C, mais ton code n'est dans aucun de ces cas.
Par exemple :
- pour sortir d'une double boucle imbriquée
- ou pour gérer la sortie d'une fonction vers la fin de la fonction centralisant les opérations communes de nettoyage à faire selon les différents cas d'erreurs (fermeture de fichiers, libération de mémoire,etc.)
Revenir sauter en arrière est en général une mauvaise idée.
Tu as un main() qui fait plus de 200 lignes au lieu de le découper en fonctions comme on te l'a dit.
Ton main pourrait faire ceci ce qui permettrait de percevoir immédiatement la structure générale de ton programme :
int main(void) { while (true) { afficher_menu(); switch (demander_choix_menu()) { case 1: calculatrice(); break; case 2: equation_second_degre(); break; case 3: programme_ABCD(); break; case 4: return 0; break; default: afficher_erreur_selection_menu(); break; }; } return 0; }On fait cela sans goto, dont tu n'as pas besoin, et qui rendent ton code confus (on appelle le genre de code que tu écris du "code spaghetti", ou "programmation spaghetti" : https://fr.wikipedia.org/wiki/Programmation_spaghetti comme on te l'a déjà fait remarquer.
-
