mercredi 12 décembre 2012

C++ site du zero, utiliser plusieurs fichiers

http://www.siteduzero.com/tutoriel-3-420427-utiliser-plusieurs-fichiers.html

Alors pour utiliser des fonctions à plusieurs endroits, on créé plusieurs fichiers.
Semble-t-il on sépare les fonctions de leurs descriptions (.cpp et .h ?! )

dans code::blocks
create

Soit une fonction pas trop compliquée : 

#include "math.h"
int ajouteDeux(int nombreRecu)
{
    int valeur(nombreRecu + 2);
    return valeur;
}


Truc etc. J'ai créé mes trois fichiers différents (projet principal : main.cpp, une page liée qui est math.cpp dans laquelle on indique #include "math.h". Généralement, les deux (math.cpp et math.h) ont le même nom et juste pas la même extension. C'est plus par volonté que par règle rigide.

Donc une fois les trois fichiers créés, on retient que dans le .h, il y a trois lignes  et qu'il faut écrire entre la deuxième et la troisième, puisque c'est une boucle qui évite de lancer plusieurs fois le même fichier dans le script, si j'ai bien compris. (un peu comme en php, j'sais plus le nom de cette fonction d'ailleurs.)

On va mettre dans math.h le "prototype" de la fonction. : le prototype, c'est la première ligne de la fonction, après les accolades, avec un ;. Je ne suis pas sûre d'avoir compris, alors voilà ce que ça donne dans le cas présent :

int ajouteDeux(int nombreRecu);

Donc dans notre fichier math.h, maintenant, on a :
#ifndef MATH_H_INCLUDED
#define MATH_H_INCLUDED

int ajouteDeux(int nombreRecu);
#endif // MATH_H_INCLUDED



parce qu'en fait, ce qu'il faut savoir et qui est très important : C'est qu'on n'inclut jamais de cpp, mais des h.
Donc, pour utiliser la fonction ajouteDeux, la seule façon est de créer ce fichier .cpp dans le dossier, et un fichier .h qui inclut le fichier dont on a besoin.

L'avantage, c'est que si on a besoin de ces fonctions dans un autre programme, y a qu'à inclure math.h et .cpp ;)

Une bonne pratique est de regrouper les fonctions par catégorie,  genre les déplacements d'un personnage de jeu dans un même fichier, les calculs dans un autre etc.

Bonne pratique : commenter une fonction, c'est pas du luxe. 


Des valeurs par défaut pour les fonctions passées en paramètre ??


Oui, bon, je sais pas, mais j'ai l'impression que je connais déjà. 

http://www.siteduzero.com/tutoriel-3-420453-des-valeurs-par-defaut-pour-les-arguments.html 

Comme dans d'autres langages (python, php, etc.) on peut délcarer des valeurs par défaut pour une fonction.
MAIS dans ce cas, on doit le faire là où on déclare la focntion.
Dans le cas du script qui nous intéresse, celle-ci est déclarée en haut du doc, donc, dans la fonction suivie du ;
Si on a un fichier, les valeurs par défaut doivent être spécifiées dans le .h c'est une source commune d'erreur.

Evidemment, les éléments facultatifs doivent se trouver à droite.

Bon, 20/20, je continue.



Les Tableaux

Les tableaux de données fixes : Statiques.

Déclaration d'un tableau statique 
On déclare la taille du tableau au départ. Ca se fait évidemment avec les crochets :
int meilleursScores[3]; signifie qu'on garde trois entiers dans le tableau meilleursScores. A ce moment-là, l'ordi réserve la place voulu comme montré dans ce schéma :
On peut déclarer aussi que le nb de valeurs est const :
int const nombreScore(3). C'est même souvent préconisé.
Dans le cas des 10 meilleurs scores cela dit, ils vont changer, mais ils seront toujours 10.
Ce type de déclaration déclare la taille en même temps, et lesiteduzero conseille de préférer cette méthode.

Bon comme dans tous les langages, pour déclarer une valeur dans une case, on fait nomDuTableau[n] = valeur; et ça enregistre.

On fait une boucle pour parcourir le tableau, comme dans le mini programme qui suit :

int const nombreMeilleursScores(5);
int meilleursScores(nombreMeilleursScores);

meilleursScores[0] = 11520; 
meilleursScores[1] = 10110; 
meilleursScores[0] = 9320; 
meilleursScores[0] = 512; 
meilleursScores[0] = 4; 
// ensuite on parcourt le tableau :

for (int i(0); i < nombreMeilleursScores ; i++)
{
    cout << "meilleur score " << i << " : " << meilleursScores[i] << endl;
}

Boucle classique.
Au fait, erreur classique : si pas de fonction int main() { } : erreur (variable does not name a type)

REGLE A CONNAITRE important :
On NE PEUT PAS renvoyer un tableau statique à l'issue d'une fonction. Quand on le passe par argument, ça signifie donc si je comprends qu'on peut modifier ce tableau.
Donc, une fonction qui reçoit un tableau comme argument, ça donne ça :

void notrefonction(double tableau[]) 

{

// instructions

}
J'ai pas bien compris. Il ne faut rien mettre dans les crochets. Ah ben, la taille ne passe pas automatiquement en argument. Donc si on souhaite passer un tableau de ce genre pour le parcourir à l'aide d'une boucle for par exemple, faut passer la taille comme argument :
void notrefonction(double tableau[], int tailleTableau)
{
// instructions;
}

Exercice : calculer à l'aide d'une fonction la moyenne.

J'ai butté sur un problème simple : j'ai appelé une fonction en typant, or ce n'est pas nécessaire puisqu'on déclare ça dans la fonction.
Lorsqu'on appelle la fonction, on n'écrit QUE
type resultat = nomDeFonction(arg1, arg2, ... , argn);
... Logique en même temps mais bon.

Tableau dynamique

Pour utiliser un tableau dynamique il faut appeler la bibliothèque "vector" :
#include <vector>
Du coup, on parle souvent d'un "vecteur" pas forcément d'un "tableau".
Et puis pour déclarer le tableau du coup on fait comme ça :
Déclaration d'un vector 
Par exemple, j'imagine que si on dit que le tableau de notes dont les notes varient genre d'un trimestre à l'autre :
vector<double> notes(6);

important : on n'écrit pas le type en premier, mais vector. Le type est entre < et > et pour finir, la taille n'est pas donnée entre crochets mais entre parenthèses.

Atsuce 1 : on peut remplir directement les cases en donnant un argument en deuxième place dans la parenthèse :
vector<double> notes(6, 3);
déclare que le tableau dynamique notes a 6 notes de valeur 3.
Astuce 2 : on peut déclarer un tableau à cases vides :
vector<double> notes;
créé un tableau notes vide. Comme le tableau est variable, on pourra je suppose ajouter ça plus tard.
Autant la déclaration est différente, autant l'accès est similaire : crochets, boucle...
On peut réécrire la même chose que plus haut pour remplir le vecteur.
 A l'aide de la fonction push_back() on ajoute une valeur à la fin du tableau. (donnée dans la parenthèse)
 pop_back() de la même façon retire la dernière valeur, et ça, ça s'écrit un peu comme en js :
tableau.push_back(valeur);
tableau.pop_back();
La fonction pour connaître la  taille d'un tableau, c'est size :
tableau.size(); donne la taille du vecteur tableau.
Pour déclarer une fonction qui compte la moyenne d'un tableau dynamique :
#include <iostream>
#include <vector>

int moyenne(vector<double> notes, int taille)
{
double moyenne(0);
for (int i(0), i
Voilà, rien de très compliqué en fait. Bon, je vois que le blog a changé totalement mon truc... Ca me saoule de recommencer.

Ah oui, et quand on utilise dans une fonction un tableau dynamique, on le copie... Aussi, pour éviter cette perte inutile d'espace mémoire et optimiser le temps d'exécution vaut-il mieux envoyer une référence constante :

void fonction(vector<double> notes)
{
    // instructions
}
devient
void fonction(vector<double> const& notes)
{
    // instructions
}
 Evidemment, dans ce cas, le tableau n'est pas modifiable par la focntion.

(note pour moi-même : réviser ces histoires de références et constantes un de ces 4, c'est pas simple.)

Aucun commentaire:

Membres