Aller au contenu


Photo
- - - - -

Padawan C++


  • Veuillez vous connecter pour répondre
24 réponses à ce sujet

#1 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 20 juillet 2017 - 01:29

Plop les maker's, bon voilà comme certains le savent j'essaye d'apprendre le C++.

J'ai préfèré ouvrir un post ici pour ne pas pourrir celui de Glenn ^^

Donc, j'essaye de me faire des petits exercices comme ça histoire d'apprendre et me suis confronter un truc tout balot, le calcul d'une moyenne de chiffres via une fonction en passant par un tableau, et là, (c'est le drame), suis bloqué sur un truc, je post le code ^^


main.cpp

#include <iostream>
#include "moyenne.h"
using namespace std;

int main ()
{
    int const nombreMeilleursScores (5);

    double meilleursScores [nombreMeilleursScores];

    meilleursScores[0] = 19.5;
    meilleursScores[1] = 12;
    meilleursScores[2] = 10;
    meilleursScores[3] = 6;
    meilleursScores[4] = 15;

    fonction(meilleursScores, nombreMeilleursScores);

    cout << "La moyenne des scores est : " << fonction << endl;

    return 0;
}

moyenne.cpp

#include <iostream>
#include "moyenne.h"

using namespace std;

double fonction (double tableau[], int tailleTableau)
{
    double moyenne(0);
    for(int i(0); i < tailleTableau; ++i)
    {
        moyenne += tableau[i];
    }
    moyenne /= tailleTableau;
    return moyenne;
}

moyenne.h

#ifndef MOYENNE_H_INCLUDED
#define MOYENNE_H_INCLUDED

double fonction (double tableau[], int tailleTableau);

#endif // MOYENNE_H_INCLUDED

Et lorsque je lance le programme j'obtiens la moyenne de 1, donc je me dis qu'il ne prend pas toutes les valeurs du tableau.

Je ne vois pas comment faire...

 

Edit : ou alors faudrait il que je place un for dans mon main pour la fonction ??? (un truc du genre)

 

Merci


Modifié par Oliver17, 20 juillet 2017 - 01:34 .

signature_01.png -->

 

Mon Tipeee
 


#2 maximusk

maximusk

    Membre passionné

  • Membres
  • PipPipPip
  • 304 messages
  • Gender:Male
  • Location:Le Mans

Posté 20 juillet 2017 - 01:56

Le for dans le main, non. Ta fonction est censée calculer la moyenne de tout ton tableau, donc tu l'appelles une fois et c'est tout.

 

Ton problème ici, c'est que tu ne récupères pas le résultat de ta fonction, et qu'au lieu d'afficher ce résultat que tu ne récupères pas, tu affiches la fonction elle même (d'ailleurs je ne sais pas comment ça marche et pourquoi ça affiche 1).

#include <iostream>
#include "moyenne.h"
using namespace std;

int main ()
{
    int const nombreMeilleursScores (5);

    double meilleursScores [nombreMeilleursScores];

    meilleursScores[0] = 19.5;
    meilleursScores[1] = 12;
    meilleursScores[2] = 10;
    meilleursScores[3] = 6;
    meilleursScores[4] = 15;
    
    // Ici tu récupères le résultat
    double moy (fonction(meilleursScores, nombreMeilleursScores));

    // Et ici tu l'affiches
    cout << "La moyenne des scores est : " << moy << endl;

    return 0;
}


#3 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 20 juillet 2017 - 02:12

Ok, il fallait juste que je déclare une variable avec un type lorsque j'appel la fonction, si je résume bien.

 

Pour le 1 sinon, là, tu me pose une colle, j'en ai aucune idée.

 

J'ai testé et ça fonctionne, j'aurais du réfléchir un peu plus.

 

Par contre sur un autre exercice, juste avec une fonction qui ajoute +2 lorsqu'on lui donne un chiffre, je n'ai pas eu besoin de mettre le type dans le main pour avoir le résultat.

Et là je dois le faire (mettre double), POURQUOI ?.

 

Merci. ^^


signature_01.png -->

 

Mon Tipeee
 


#4 maximusk

maximusk

    Membre passionné

  • Membres
  • PipPipPip
  • 304 messages
  • Gender:Male
  • Location:Le Mans

Posté 20 juillet 2017 - 02:26

Tu aurais aussi pu faire comme ça (vu que tu ne cherches pas a stocker ou à exploiter la moyenne, juste à l'afficher) :

#include <iostream>
#include "moyenne.h"
using namespace std;

int main ()
{
    int const nombreMeilleursScores (5);

    double meilleursScores [nombreMeilleursScores];

    meilleursScores[0] = 19.5;
    meilleursScores[1] = 12;
    meilleursScores[2] = 10;
    meilleursScores[3] = 6;
    meilleursScores[4] = 15;

    // Et ici tu calcules la moyenne et tu l'affiches en une fois
    cout << "La moyenne des scores est : " << fonction(meilleursScores, nombreMeilleursScores) << endl;

    return 0;
}

C'est à mon avis ce que tu avais fait dans l'autre exo, et c'est pour ça que ça marchait.

 

Ce que j'ai fait avant, ce n'est pas "mettre le type dans le main". En fait, j'ai crée une variable appellée "moy", de type "double", et de valeur "fonction(meilleursScores, nombreMeilleursScores)". Ce n'est pas nécessaire, juste utile si tu veux utiliser la moyenne une deuxième fois sans la recalculer.

 

Ton problème, c'est surtout que tu appelais la fonction pour rien*  ligne 17 (tu ne récupères pas et n'utilise pas son résultat), et que tu ne l'appelais pas dans ta ligne d'affichage (il manquait les parenthèses et les paramètres).

 

* D'ailleurs, selon les réglages du compilateur, il est possible qu'il ne l'ait même pas mise dans l'executable.



#5 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 20 juillet 2017 - 03:42

Oki doki, bon ben vais continuer à apprendre ...

 

 

* D'ailleurs, selon les réglages du compilateur, il est possible qu'il ne l'ait même pas mise dans l'executable.

 

 

 

Alors la, aucune idée.

 

 

Merci ^^


signature_01.png -->

 

Mon Tipeee
 


#6 cocothebo

cocothebo

    Membre passionné

  • Membres
  • PipPipPip
  • 341 messages
  • Gender:Male

Posté 20 juillet 2017 - 07:02

A mon avis, il vaut mieux utiliser la syntaxe du C pour faire les déclarations de variable, soit

double moy = ...

plutot que

double moy (... 

(Même si ça revient au même, ça reste plus "conventionnel" je trouve)

 

Effectivement si le compilo est suffisamment "intelligent", il peut optimiser et enlever les appels et fonctions non nécessaires, pour le vérifier il faut desassembler le binaire généré! (par exemple)



#7 maximusk

maximusk

    Membre passionné

  • Membres
  • PipPipPip
  • 304 messages
  • Gender:Male
  • Location:Le Mans

Posté 20 juillet 2017 - 07:48

A mon avis, il vaut mieux utiliser la syntaxe du C pour faire les déclarations de variable, soit

double moy = ...

plutot que

double moy (... 

(Même si ça revient au même, ça reste plus "conventionnel" je trouve)

 

Je suis d'accord, je crois même que c'est la première fois que j'utilise cette syntaxe pour une variable. Mais vu que tout le code était écrit comme ça, j'ai suivi.



#8 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 21 juillet 2017 - 08:12

Perso je suis les cours tel qu'ils sont.

 

Mais j'aurais pris aussi le = perso, je trouve ça plus propre à la lecture.

 

Ça ne risque rien de mélanger les deux syntaxes C et C++ ??

 

Car sinon au lieu de mettre double, je met des float que je trouve aussi plus logique à lire.


signature_01.png -->

 

Mon Tipeee
 


#9 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 768 messages
  • Gender:Male

Posté 21 juillet 2017 - 05:07

Ça ne risque rien de mélanger les deux syntaxes C et C++ ??
Car sinon au lieu de mettre double, je met des float que je trouve aussi plus logique à lire.

Si tu n'as pas de calcul astronomique, je pense que le float devrait suffire.
Un compilateur C++, compile très bien du C. Je ne sais pas s'il existe encore des compilateurs C, sauf peut-être pour les machines Unix.

#10 maximusk

maximusk

    Membre passionné

  • Membres
  • PipPipPip
  • 304 messages
  • Gender:Male
  • Location:Le Mans

Posté 21 juillet 2017 - 11:15

La syntaxe avec le "=" n'est pas spécifique au C, donc il n'y a pas de problème à l'utiliser en C++. Par contre, certaines choses du C peuvent poser problème en C++, pour créer un tableau avec l'allocation dynamique par exemple (dans certains cas, quand tu utilises malloc, le compilateur C++ va gentiment t'engueuler pour te dire que c'est du C et qu'en C++ on doit utiliser new. C'est pour ça que quand on à un gros bout de code spécifique au C, on le met dans un bloc "extern C", pour préciser au compilateur que ce n'est pas du C++.

 

Et pour double ou float, rien a voir avec le C ou C++, c'est une question de taille (oui, la taille ça compte, en tout cas pour les variables), ou plutôt de précision. Tu pourras stocker des nombres beaucoup plus grands ou proches de 0 dans un double (un truc d'a peu pres 10^-308 à 10^308). Par contre, du prendras plus de mémoire, donc si tout peut rentrer dans un float, il vaut mieux éviter double.



#11 Path

Path

    Made By Humans

  • Modérateur
  • PipPipPipPipPip
  • 2 504 messages
  • Gender:Male
  • Location:Paris

Posté 21 juillet 2017 - 11:33

oui, la taille ça compte, en tout cas pour les variables

Oui, une grosse variable, ça compte, surtout si tu sais t'en servir, c'est mieux.

Courage Oliver, penses au moment, où plus tard, tu diras bof, trop facile !!

Oui, je sais, je dois sortir et vite :)



#12 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 22 juillet 2017 - 01:13

Ouais, sors, vite lol ^^

 

Bah, je n'ai jamais été contre le C++, c'est juste que c'est bien prise de tête je trouve, mais bon.

 

Faut que je prenne les bons réflexes surtout, donc je vais rester sur la façon de travailler du tuto d'openclassrooms.


signature_01.png -->

 

Mon Tipeee
 


#13 maximusk

maximusk

    Membre passionné

  • Membres
  • PipPipPip
  • 304 messages
  • Gender:Male
  • Location:Le Mans

Posté 22 juillet 2017 - 03:12

Prendre les bons reflexes, c'est bien. Mais c'est vrai qu'initialiser des variables de base (j'entends par la les int, float, bool, et autres) avec un constructeur (normalement pour la programmation orientée objet), je trouve ça pas terrible, et je pense que beaucoup de gens qui font du C++ seront d'accord avec moi. 



#14 Resethel

Resethel

    Membre

  • Membres
  • 19 messages
  • Gender:Male

Posté 23 juillet 2017 - 12:03

Prendre les bons reflexes, c'est bien. Mais c'est vrai qu'initialiser des variables de base (j'entends par la les int, float, bool, et autres) avec un constructeur (normalement pour la programmation orientée objet), je trouve ça pas terrible, et je pense que beaucoup de gens qui font du C++ seront d'accord avec moi. 

 

Ça dépend ! Moi j'aime bien, je trouve ça plus correct, après j'ai commencé en apprenant le C/C++ c'est peut être pour ça ^^



#15 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 25 juillet 2017 - 07:48

Je viens de lire le passage sur les pointeurs, et si je ne dis pas de bêtises c'est là ou l'on reconnait les performances du C++, libérer la mémoire, détruire une variable et éviter les fuites. :)

 

C'est super intéressant, va falloir que je me relise ça pour bien me le mettre en tête.

 

Par contre faut pas se foirer, à savoir à quel moment bien utiliser les pointeurs, si ça vaut le coup ou non.

Car j'imagine que l'on ne peut pas pointer tout et n'importe quoi ?

 

Par contre les tableaux et dynamique, beurk, le bordel.

Ecrire dans un fichier et se retrouver au poil de cul prés, beurk aussi.

Les fonctions et découper sont fichier, mouais ça passe, mais faire deux fichiers (.h et .cpp) pour si peux...

Et j'en passe, enfin bon, je pense que c'est un coup à prendre, j'espère percer...

 

(mais le C++ reste une usine à gaz) ^^

 

:)


signature_01.png -->

 

Mon Tipeee
 


#16 maximusk

maximusk

    Membre passionné

  • Membres
  • PipPipPip
  • 304 messages
  • Gender:Male
  • Location:Le Mans

Posté 25 juillet 2017 - 09:34

Les pointeurs, c'est compliqué quand on débute, mais super pratique (surtout sur microcontrôleur ou pour manipuler du matos).
Par contre, c'est vrai qu'il ne faut pas se planter. Si tu as un OS et que tu te plantes, tu te feras engueuler et ton programme plantera (la fameuse segmentation fault). Par contre sans OS (sur microcontrôleur par exemple), je ne peux pas te dire ce qui se passera, c'est totalement imprévisible en fonction de l'endroit ou le pointeur pointera.

Par contre, j'ai tendance a ne pas utiliser les tableaux dynamiques en c++ (sauf cas particulier comme la manipulation d'images). Pour le reste, on a les vectors, qui sont beaucoup plus pratique.

Et découper ses programmes en fichiers, c'est bien. Tu n'es pas obligé d'avoir un .h pour chaque .cpp. Tu peux mettre du code dans un .h moyennant quelques hacks, ou inclure un .cpp directement.
La ou c'est pratique, c'est sur des gros programmes, tu codes dans le .cpp et tu mets des enormes commentaires qui détaillent chaque fonction, classe, variable, dans le .h, comme ça si quelqu'un qui ne connait pas doit travailler dessus, il n'a qu'a lire les .h au lieu de se taper tout le code.

#17 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 768 messages
  • Gender:Male

Posté 25 juillet 2017 - 12:21

Par contre faut pas se foirer, à savoir à quel moment bien utiliser les pointeurs, si ça vaut le coup ou non.

Demandes toi si ta fonction pourrait être utilisée dans un autre programme, ou même dans ton programme mais dans différents contextes.
Si oui, alors les paramètres de cette fonction devraient être des pointeurs.

#18 R1D1

R1D1

    Modérateur et Membre passionné

  • Modérateur
  • PipPipPipPipPip
  • 1 211 messages
  • Gender:Male
  • Location:Autriche

Posté 25 juillet 2017 - 02:44

Et découper ses programmes en fichiers, c'est bien. Tu n'es pas obligé d'avoir un .h pour chaque .cpp. Tu peux mettre du code dans un .h moyennant quelques hacks, ou inclure un .cpp directement.
La ou c'est pratique, c'est sur des gros programmes, tu codes dans le .cpp et tu mets des enormes commentaires qui détaillent chaque fonction, classe, variable, dans le .h, comme ça si quelqu'un qui ne connait pas doit travailler dessus, il n'a qu'a lire les .h au lieu de se taper tout le code.

Mauvaise idée : si tu inclues les cpp, la moindre modification de ta fonction provoque la recompilation de tous les objets correspondant. Pour un petit projet, ça n'est pas forcément gênant, mais ça peut vite devenir horrible quand ton projet grandit, ou que tu utilises des libraires externes.
Pour ce qui est des commentaires, la bonne pratique est de les réduire au minimum nécessaire. Le code doit être le plus explicite possible, quitte à le re-factoriser ou le re-séparer en fonctions. Et les commentaires ne doivent pas expliquer ce que fait le code (ça doit se comprendre à partir du code) mais expliquer certains choix d'implémentations.
Les seuls commentaires descriptifs sont ceux qui servent à générer des documentations automatiquement (par exemple avec Doxygen).
Une fois de plus, ce sont des bonnes pratiques qui ne sont pas obligatoires, mais d'expérience, ça réduit la difficulté à re-rentrer dans le code plus tard ou les chances de se perdre entre les différents fichiers.
 

Demandes toi si ta fonction pourrait être utilisée dans un autre programme, ou même dans ton programme mais dans différents contextes.
Si oui, alors les paramètres de cette fonction devraient être des pointeurs.

???
Je ne suis pas sûr de comprendre ce que tu veux dire par là.
Une fonction prend un pointeur en argument si elle doit modifier cet argument. Si tu veux utiliser une fonction spécifique dans un autre programme, tu déclares ta fonction dans un header, tu l'implémentes dans un fichier cpp, puis dans ton code principal (qui contient le main), tu fais un #include "chemin/vesr/le/header.h", et tu indiques au compilateur qu'il faut également compiler le fichier correspondant puis éditer les liens avec ces objets.
Que cette fonction prenne ou non un pointeur en argument ne rentre pas en compte.

Un petit example:
programmeprincipal.cpp
-----
#include <vector>
#include <string>

#include "mafonction.h"

int main(int argc, char** argv)
{
   std::string qualificatifs[] = {"pas du tout", "un peu", "beaucoup", "passionnément", "à la folie"};
   std::vector<std::string> degreAmour(qualificatifs, qualificatifs + sizeof(qualificatifs) / sizeof(qualificatifs[0]));
   int amourActuel = 0;

   for(int i = 0 ; i < 10 ; i++)
   {
     direMonAmourDesBananes(degreAmour, &amourActuel);
   }

   return 1;
}
-----
mafonction.h
-----
#pragma once
#include <vector>
#include <string>

void direMonAmourDesBananes(std::vector<std::string> da, int * aa);

-----
mafonction.cpp
-----
#include <iostream>
#include "mafonction.h"

// on utilise un pointeur pour aa pour illustrer un cas où un pointeur est nécessaire.
void direMonAmourDesBananes(std::vector<std::string> da, int * aa)
{
   if(*aa == da.size()){ (*aa) = 0; }
   else
   {
     std::cout << "J'aime " << (*aa < (da.size()-1) ? da.at(*aa)+" " : "") << "les bananes" << ( *aa == (da.size() -1) ? " "+da.at(*aa) : "") << "." << std::endl;
     (*aa)+=1;
   }
}
r1d1@nova:~/codeTests/basicCompilationExample$ g++ *.cpp -c
r1d1@nova:~/codeTests/basicCompilationExample$ g++ -Wall *.o -o monprogramme
r1d1@nova:~/codeTests/basicCompilationExample$ ./monprogramme 
J'aime pas du tout les bananes.
J'aime un peu les bananes.
J'aime beaucoup les bananes.
J'aime passionnément les bananes.
J'aime les bananes à la folie.
J'aime pas du tout les bananes.
J'aime un peu les bananes.
J'aime beaucoup les bananes.
J'aime passionnément les bananes.
Quelques compléments d'information :
- la structure (*aa < (da.size()-1) ? da.at(*aa)+" " : "") est une condition ternaire : c'est l'équivalent python de :
"Vrai" if variable == True else "Faux"
- Vu que je veux afficher un texte différent à chaque fois que j'appelle la fonction, et que c'est ma variable amourActuel qui tient le compte du nombre d'appels, j'ai besoin de passer son adresse (le pointeur vers ma variable) dans la fonction pour pouvoir l'incrémenter.
Si je ne passe que la valeur de la variable (ce qu'on obtient quand on utilise le nom), je fais une copie de la valeur qui n'a de portée que dans la fonction (donc la copie est détruite quand la fonction se termine et la valeur de amourActuel n'est pas modifiée).
- Je compile d'abord chaque code cpp individuellement (grâce à l'option -c), puis je combine mes objets en un seul (édition de liens : https://fr.wikipedia.org/wiki/Édition_de_liens).
- Les bananes, c'est trop cool pour écrire des exemples de code.
R1D1 - Calculo Sed Ergo Sum -- en ce moment, M.A.R.C.E.L.
Avatar tiré du site bottlebot

#19 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 758 messages
  • Gender:Male

Posté 26 juillet 2017 - 09:06

這是中國給我。 :(

 

Je ne met pas la traduction hein...


signature_01.png -->

 

Mon Tipeee
 


#20 Telson

Telson

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 975 messages
  • Gender:Male
  • Location:Punaauai - Tahiti

Posté 26 juillet 2017 - 10:26

Merci R1D1.....Cool.....






0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users