Petite correction sur mon code

Le problème exposé dans ce sujet a été résolu.

Je suis actuellement le cour de zeste-de-savoir sur le C++, voila je voulais quelqu’un de plus expérimenté dans ce langage revois mon code… Et si possible avoir un point de vue critique afin de m’améliorer encore plus. Merci en avance pour votre attention.

Pour trouver le PGCD d’un nombre j’ai utilisé la méthode de soustraction :

#include <iostream>

int main () { std::cout « "a = "; int a { 0 };

while (!(std::cin >> a))
{
    std::cout << "Erreur de saisie, re-saisir a = ";
    std::cin.clear(); // remet cin dans un etat fonctionnel
    std::cin.ignore(500, '\n'); // vide le buffer
}

std::cout << "b = ";
int b { 0 };

while(!(std::cin >> b))
{
    std::cout << "Erreur de saisie, re-saisir b = ";
    std::cin.clear(); // remet cin dans un etat fonctionnel
    std::cin.ignore(500, '\n'); // vide le buffer
}

int soustraction { a - b };

while (soustraction != 0)
{
    if (soustraction > b)
    {
        a = soustraction;
        soustraction = a - b;
    }

     else
    {
        a = b;
        b = soustraction;
        soustraction = a - b;
    }
 }

std::cout << "Le PGCD vaut : " << a << ".\n";

return 0;

}

+0 -0

Niveau code, j’ai rien à ajouter de plus que gbdivers. Peut-être prendre l’habitude de créer une fonction pour mettre l’essentiel d’un algorithme (pour pouvoir le réutiliser au besoin).

Pour ce qui est de l’implémentation par-contre, j’ai quelques remarques.

  • int soustraction { a - b }; Tu pars du principe que a > b non ?
  • while (soustraction != 0) généralement, on préfère les conditions basées sur la comparaison >= 0, > 0 ou l’inverse <= 0, < 0.

Ces deux remarques réunies engendre une boucle infinie lorsque a < b.

+2 -0

Oui je partais du principe que a > b, c’était à partir de là que j’avais construit mon raisonnement.

Et pour ce qui est de créer une fonction, je ne possède pas encore le bagage nécessaire, je ne suis qu’au chapitre sur le Tableau. Mais je compte bien le faire.

J’ai fais de mon mieux pour que ce petit programme ne rentre pas dans une boucle infinie (si a < b) J’ai donc réécris mon code comme ci-dessous :

#include <iostream>

int main () { std::cout « "a = "; int a { 0 };

while (!(std::cin >> a))
{
    std::cout << "Erreur de saisie, re-saisir a = ";
    std::cin.clear(); // remet cin dans un etat fonctionnel
    std::cin.ignore(500, '\n'); // vide le buffer
}

std::cout << "b = ";
int b { 0 };

while (!(std::cin >> b))
{
    std::cout << "Erreur de saisie, re-saisir b = ";
    std::cin.clear(); // remet le flux dans un etat fonctionnel 
    std::cin.ignore(500, '\n'); // vide le buffer
}

if (a < b)
{
    int c { a };
    a = b;
    b = c;
}

int soustraction { a - b };

while(soustraction != 0)
{
    if (soustraction > b)
    {
        a = soustraction;
        soustraction = a - b;
    }
    else 
    {
        a = b;
        b = soustraction;
        soustraction = a - b;
    }
}
    
std::cout << "Le PGCD vaut : " << a << std::endl;

return 0;

}

Je vais essayer de repenser autrement afin d’écrire un code qui prend en compte une condition avec les opérateurs >=, > ou <=, <…

Autre question pourquoi préfère-t-on les conditions basées sur les opérateurs >=, >, <=, <

Est-ce seulement à cause du risque d’une boucle infinie ou bien il y a d’autres raisons à ça ?

+0 -0

Autant pour moi à propos des fonctions. Prend le temps d’apprendre ^^

Autre question pourquoi préfère-t-on les conditions basées sur les opérateurs >=, >, <=, < ? Est-ce seulement à cause du risque d’une boucle infinie ou bien il y a d’autres raisons à ça ?

amalure

Les boucles infinies entre autres. Ce qu’on cherche à éviter c’est travailler sur des valeurs qui n’ont plus de sens, pour éviter de les propager par exemple.

Il peut y avoir d’autres raisons, mais elles ne sont pas importantes.

Par exemple le cas de < 0 (ou > 0) est souvent plus rapide que == 0. Mais ce sont des micro-optimisations dont on ne tient compte que dans des programmes spécifiques. Les critères générals d’un bon code étant sa facilité de compréhension et sa ré-utilisabilité plus que ses performances.

+1 -0
  • Nom de variable mal choisi : soustraction. C’est un nom pour une action. Ici, a - b, c’est une différence.

  • Calculer un pgcd, ça se sépare naturellement des actions de lire des données, et d’afficher des résultats. En faire une fonction.

  • les séquences pour demander les nombres a et b sont similaires. En faire une fonction qu’on appellerait comme ça, par exemple

int a = demander_nombre("a");
int b = demander_nombre("b");
std::cout << .... << pgcd(a, b) << std::endl;

Dans le genre

int demander_nombre(const std::string & nom) {
   int valeur;
   while (!(std::cin >> valeur)) {
    std::cout << "Erreur de saisie, re-saisir " << nom << " = ";
    std::cin.clear(); // remet cin dans un etat fonctionnel
    std::cin.ignore(500, '\n'); // vide le buffer
   }
}
+1 -0

Ouais je m’en doutais aussi que j’avais mal choisi ce nom (soustraction). Mon premier choix portais sur <résultat> mais je crois que c’est un peu tiré du cheveux et trop général comme nom de variable. C’est mieux et je préfère <différence> par rapport à l’ancien…

En ce qui concerne de créer une fonction afin de séparer les 2 actions, je compte bien le faire plus tard, vu que je n’ai pas encore lu le chapitre sur les fonctions… En fait j’avais constaté que je progressais trop vite. Du coup j’ai préféré prendre un certain recul afin de solidifier mes acquis.

Merci pour votre analyse et exemple, je compte bien l’étudier une fois sur les fonctions.

Déjà, resultat, c’est mieux que nombre ou entier !


Il y a un problème avec les cours qui enseignent à la fois un langage et la programmation. Ils ne mettent pas assez en avant l’aspect procédural, à savoir que

  1. pour résoudre un problème on le découpe en morceaux plus petits
  2. chaque morceau doit avoir un rôle bien identifiable
  3. les fonctions sont l’outil de base, la manière naturelle pour contenir un morceau de code, en lui donnant avec un nom qui reflète le rôle. Eventuellement avec des paramètres pour l’appliquer à des données différentes.

Surtout qu’en C++ des fonctions, le programmeur en voit dès le départ : au moins main(), et ici clear() et ignore(), sans parler de << qui est une forme d’écriture pour operator<<().

Intérêt supplémentaire : le code qu’on écrit ayant une facheuse tendance à ne pas vouloir marcher, il est plus facile de vérifier indépendamment et corriger des fonctions de quelques lignes qui font chacune une petite chose, qu’un pavé de code qui est censé tout faire et "déconne quelque part". Plus la botte de foin est petite, plus vite on trouve l’aiguille.


En prime, il y aurait aussi l’action qui ordonne deux nombres, et qu’on va nommer, au hasard, ordonner :

void ordonner(int & a, int & b) { // peut modifier les paramètres : passage par référence
  if (a < b)
  {
    int c { a };
    a = b;
    b = c;
  }
}
+1 -0

J’ai vu sur un autre tutoriel que clear(), ignore() sont des méthodes… et sur celui de zeste-de-savoir que ce sont des fonctions. Du coup j’ai considéré que méthode = fonction (je ne me trompe pas j’espère).

Oui tout a fait d’accord et c’est logique, mieux vaut découper son programme en plusieurs actions dont chacune remplie une tache bien précise (fonction)… car c’est bien plus facile de corriger quelques lignes de codes qu’un ensemble de codes qui fait tout à la fois (Si je comprends bien vos propos).

Super ça m’aide bcp l’exemple sur la troisième fonction… Je comprends bcp mieux le rôle des fonctions (découper un problème en sous-tache).

J’ai vu sur un autre tutoriel que clear(), ignore() sont des méthodes… et sur celui de zeste-de-savoir que ce sont des fonctions. Du coup j’ai considéré que méthode = fonction (je ne me trompe pas j’espère).

Ne t’embêtes pas avec ça.


Pour la petite histoire, et pour chipoter:

Officiellement en C++ il n’y a que des fonctions. Certaines sont dites membres car définies à l’intérieur de classes.

Dans certains langages OO, on va parler de méthodes. En général c’est désigné de façon équivalente aux fonctions membres. Maintenant, le créateur du C++ a posé une définition dans son livre de référence: "méthode est un terme parfois employé pour désigner des fonctions membres virtuelles". Cependant, ceux qui utilisent "méthode" ne considèrent pas que cela implique "virtuel" — notion que tu verras plus tard.

Les termes officiels et sans ambiguïté en C++ sont:

  • fonction
  • fonction libre
  • fonction membre (publique, protégée ou privée)
  • fonction (sous-entendue membre) virtuelle
  • fonction (sous-entendue membre) virtuelle pure — équivalent aux abstract methods dans d’autres langages OO ou UML

Hors C++, on va croiser aussi

  • fonction pure, qui désigne des fonctions qui n’ont aucun effet de bord: elles prennent des entrées pour calculer une sortie qui sera renvoyée, rien n’est modifié.
  • procédure: fonction qui ne retourne rien (un peu l’antithèse des fonctions pures) — je ne sais pas si on peut dire qu’une procédure avec des paramètres out peut être considérée pure si elle n’a aucun autre effet de bord…
  • routine, sous-programme…

Pour l’instant je préfère garder une définition basique : une méthode désigne une fonction membre… Avec le temps, j’aurai sûrement une définition bien plus détaillé et fourni de ce qu’une méthode…

Merci pour la précision et la petite histoire… ce fut un plaisir de la lire même si je rencontre trop de vocabulaire que je ne comprends point (preuve qu’il me reste bcp de chose à apprendre en C++ et en programmation)… Je relirai sûrement avec le temps.

+0 -0

Le vocabulaire peut varier d’un langage à un autre.

Déjà, ce qui s’appelle communément "fonction" en C et dans les langages qui s’en inspirent, ce n’est absolument pas une fonction dans aucun sens du terme.

MichelBillaud

Ça me parait vraiment bizarre. Ok, les fonctions qui renvoient void sont censées se nommer des procédures, mais toutes les autres fonctions se nomment bien fonction.

+0 -0

On (ceux qui adoptent la terminologie du langage) les appelle fonction, mais dans le dictionnaire, il y a deux sens pour ce mot

  • rôle, comme dans "remplir une fonction
  • relation entre des quantités (maths)

En programmation, c’est pas une relation, c’est un truc qui effectue un certain traitement.

On le rapproche des fonctions pour diverses raisons

  • les fonctions de fortran, qui au début (fin années 50) étaient des relations écrites en début de programmes genre F(X)=A*X + B, et ont été ensuite généralisées en "unités de programme" contenant des instructions quelconques
  • les explications par analogie qu’on fait aux débutants à propos des paramètres
  • l’existence de bibliothèques de "fonctions predefinies" effectuant les calculs qui correspondent aux fonctions numeriques courantes, racines, trigo, etc
  • le fait qu’assez souvent on conseille une approche fonctionnelle, où la fonction des "fonctions" est de calculer et retourner un truc a partir des parametres, sans modifier quoi que ce soit d’autre
+0 -1
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte