• Aucun résultat trouvé

Nouveautés du C++ vs C

N/A
N/A
Protected

Academic year: 2022

Partager "Nouveautés du C++ vs C"

Copied!
1
0
0

Texte intégral

(1)

Nouveautés du C++ vs C

1) Commentaires :

Comme en C : pour couvrir toute une zone (une ou plusieurs lignes à la fois)

/* quelque chose à mettre en commentaires la suite de ce commentaire

dernière ligne! */

À la C++ : pour couvrir une seule ligne

// quelque chose à mettre en commentaires sur une ligne

2) Constantes :

Il existe deux manières pour définir les constantes.

define :

#define nombre 10

directive au préprocesseur, remplacement lexical de nombre par 10, aucun espace mémoire n’est alloué pour stocker 10.

const :

const int nombre=10;

directive au compilateur, espace mémoire de taille int est réservé à la variable nombre qui doit être initialisée.

Cette variable a été initialisée avec la valeur 10. Elle ne pourra pas être modifiée.

- Privilégier const à define est plus sécuritaire car le compilateur connaît l’existence de la variable et peut repérer les erreurs lors de son utilisation, par

ailleurs la variable devient disponible dans la table

IFT1166, été 2004 28

(2)

des symboles. De ce fait, le debugger connaît aussi son existence.

- En C++, il est permis d'utiliser const pour déclarer la borne d'un tableau, ce qui n’est pas le cas en C.

3

) Flexibilité des déclarations :

En C, les déclarations se font toujours avant les instructions ou bien dans { }.

En C++, il est possible d’avoir les déclarations près de l’utilisation.

#include <iostream.h>

void main() {

int N=10; // déclaration avant les instructions for (int i=0;i<N;i++) {

// i est déclarée à l’intérieur de for

// i est visible uniquement dans le bloc { } int j=10 // j déclarée au moment de son

// utilisation i+=j;

cout << "i vaut : " << i << endl;

} // fin de la boucle for }

4) Type bool :

En C, il n’y a pas de type booléen, on utilise int ou bien un type prédéfini :

#include <stdio.h>

typedef enum { false=0, true =1} Boolean;

void main() {

Boolean valide = false;

printf("%d\n",valide);

valide=true;

printf("%d\n",valide);

}

(3)

Par contre en C++, le type bool a été défini. Une variable de type bool peut prendre la valeur 0 ou 1, où :

0 -> false 1 -> true

#include <iostream.h>

void main() {

bool valide = false;

cout << valide << endl; // affiche : 0 valide=true;

cout << valide << endl; // affiche : 1 }

5) Structures en C et C++ :

Le type structure (struct) en C et C++ est semblable au type enregistrement (record) dans le langage PASCAL. C’est une collection de champs qui peuvent être de types différents.

Exemple : Une nation est une structure avec les champs possibles suivants :

- continent : entier (

Afrique vaut 1, Amérique vaut 2,...)

- nom : chaîne de caractères - capitale : chaîne de caractères - superficie : entier

- population : entier Déclaration :

struct Nation { int continent;

char nom[LONGUEUR+1], capitale[LONGUEUR+1];

int superficie, population;

};

En C : struct Nation est le nom du type En C++ : Nation est le nom valide du type Accès à un champ d’une structure :

Variable_de type_structure . champ

IFT1166, été 2004 30

(4)

Écrire les instructions pour afficher les informations de

"

unPays

"

à l’écran :

cout << setw(LONGUEUR) << unPays.nom << setw(LONGUEUR) << unPays.capitale << setw(8) << unPays.superficie << setw(12) << unPays.population

<< setw(10) << nomContinent[unPays.continent-1] << endl

;

Pointeur vers une structure : Avec la déclaration : Nation *P ;

P est un pointeur vers le type Nation.

*P est une variable de type Nation.

On peut accéder à n’importe quel champ de *P : (*P).continent, (*P).nom etc ...

Le C et C++ permet de simplifier l’écriture en utilisant l’opérateur ->

(*P).champ <========> P->champ

6

) Fichiers en C++ :

En C++, l’accès à des fichiers en entrée et en sortie se fait à l’aide des flots de fichiers d’entrée (ifstream), de sortie (ofstream), d’entrée/sortie (fstream).

Exemples

#include <fstream.h>

Déclaration de fichiers :

ifstream entree; // fichier d’entrée ofstream sortie; // fichier de sortie

fstream entree_sortie; // fichier d’entrée/sortie

Ouverture des fichiers : fonction open()

(5)

entree.open("donnees");

sortie.open ("resultats");

entree_sortie.open ("Fichier", ios::in|ios::out);

On peut tester si l’ouverture a réussi à l’aide de la fonction fail()

if ( entree.fail() )

cout << "problème d’ouverture";

if ( entree.eof() )

cout << "fin de fichier atteinte";

À l’ouverture, on peut spécifier comme deuxième paramètre certains modes particuliers. Voici les modes d’entrée- sortie possibles :

ios::app écriture à la fin du fichier

ios::in lecture au début

ios::out écriture au début

ios::nocreate le fichier doit exister à l’ouverture ios::noreplace le fichier ne doit pas exister

ios::trunc efface un fichier existant.

#include <iostream.h>

#include <fstream.h>

void main () {

fstream sortie;

char nom[10];

cout << "nom du fichier : ";

cin >> nom;

sortie.open(nom,ios::out|ios::noreplace);

if (!sortie)

cout << "le fichier existe déjà!" << endl;

}

Noter que if (!sortie) est équivalente à if (sortie.fail()) Lecture/écriture de fichiers :

Les opérations d’entrée se font comme du clavier à l’aide de l’opérateur (>>)

IFT1166, été 2004 32

(6)

Les opérations de sortie se font comme à l’écran à l’aide de l’opérateur (<<)

entree >> i >> x; // lecture sortie << setw(4) << x << endl; // écriture entree_sortie >> j;

entree_sortie << x; // Lecture suivie d’écriture

Fermeture des fichiers : sortie.close();

entree.close();

Exemple : fichier .cpp

#include <iostream.h> // pour cin, cout, ...

#include <iomanip.h> // pour les manipulateurs du formatage

#include <string.h> // pour la gestion des chaînes de caractères

#include <fstream.h> // pour les fichiers

#include <ctype.h> // pour la gestion de type ....

const int LONGUEUR = 20, //longueur du nom et de la capitale d'un pays MAX_PAYS = 150; // borne du tableau des pays

//la valeur énumérée Afrique vaut 1, Amerique vaut 2, et ainsi de suite enum { Afrique = 1, Amerique, Asie, Oceanie, Europe};

// définition d'un nouveau type (typedef) : ici chaine est le nom du nouveau type

// chaine représente le nom d'un tableau de 10 caractères typedef char chaine[10];

// nomContinent est un tableau de 5 éléments, chacun est une chaîne de caractères

chaine nomContinent[5] = { "Afrique", "Amerique", "Asie", "Oceanie",

"Europe" };

// type STRUCTURE (niveau -1 de la POO) : grouper seulement les champs de données

// en C , il faut traîner le mot struct : struct Nation est le nom du type

// en C++ : Nation est le nom valide du type struct Nation

{ int continent;

char nom[LONGUEUR+1], capitale[LONGUEUR+1];

int superficie, population;

(7)

};

/* lire le fichier du nom nomAlire, créer le tableau pays (tableau des nations)

compter et transmettre par référence le nombre de pays lus (ici n)

*/

void lireCreer(char nomALire[], Nation pays[], int & n) { ifstream aLire (nomALire, ios::in);

n = 0 ;

while (aLire >> pays[n].continent,

aLire.get(pays[n].nom, LONGUEUR+1), aLire.get(pays[n].capitale, LONGUEUR+1),

aLire >> pays[n].superficie >> pays[n].population) n++;

aLire.close();

}

// afficher les informations d'un seul pays void ecrire(Nation unPays) {

cout << setw(LONGUEUR) << unPays.nom << setw(LONGUEUR) << unPays.capitale << setw(8) << unPays.superficie << setw(12) << unPays.population

<< setw(10) << nomContinent[unPays.continent-1] << endl;

}

// afficher une liste partielle des pays

void afficher(Nation pays[],int nbPays,int debut,int fin, char quand[]) {

cout << "Liste partielle des "

<< debut << " premiers pays et "

<< fin << " derniers pays "

<< quand << " le tri : " << endl ; for(int i = 0 ; i < nbPays ; i++)

if ( i < debut || i >= nbPays-fin ){

cout << setw(3) << i+1 << ") " ; ecrire(pays[i]);

} else

if ( i == debut )

cout << " etc .... \n";

cout << endl ; }

// permuter (échanger) deux pays de type Nation par référence void permuter(Nation & pays1, Nation & pays2) {

Nation tempo = pays1;

IFT1166, été 2004 34

(8)

pays1 = pays2;

pays2 = tempo;

}

/* tri par sélection (moins rapide)

strcmp : string comparaison (comparaison de 2 chaînes) fonction dans <string.h> : niveau IFT 1160

strcmp("Bonjour", "Bonsoir") < 0 car 'j' < 's' strcmp("BINGO", "ALLO") > 0 car 'B' > 'A'

strcmp("bon", "bon") vaut 0 car les 2 chaînes sont identiques

*/

void trier(Nation pays[], int nbPays) { for(int i = 0 ; i < nbPays-1 ; i++) { int indMin = i ;

for (int j = i+1 ; j < nbPays ; j++)

if ( strcmp(pays[j].nom, pays[indMin].nom) < 0 ) indMin = j;

if ( indMin != i )

permuter(pays[i], pays[indMin]);

} }

void main()

{ Nation pays [MAX_PAYS];

int nbPays ;

lireCreer("Nation.dta", pays, nbPays);

afficher(pays, nbPays, 3, 5,"avant");

trier(pays, nbPays);

afficher(pays, nbPays, 6, 2, "apres");

}

7) Allocation dynamique :

En C, on alloue et on libère de l’espace mémoire en utilisant malloc et free.

En C++, on utilise new et delete.

p

*p p = new T ;

Demander l'espace de mémoire dynamique pour mémoriser *p qui est de type T et la valeur de *p est encore inconnue.

p pointe vers *p

?

(9)

delete p; libère l’espace mémoire alloué pour *p;

T * tab=new T[MAX]; crée dynamiquement un tableau tab de type T et de taille MAX

delete [] tab; libère l’espace mémoire pour le tableau tab;

Exemple d’un tableau dynamique :

#include <iostream.h>

#include <iomanip.h>

#include <fstream.h>

const int MAX_EMP = 275 ; struct Employe

{ int matricule;

char poste ; float nbHr, taux;

};

void lireRemplir(Employe * emp, int & n)

{ ifstream aLire ("r:\\Employes.txt",ios::in);

n = 0 ;

while ( aLire >> emp[n].poste >> emp[n].matricule >> emp[n].nbHr >> emp[n].taux)

n++;

aLire.close();

}

void afficher (Employe unEmp) { cout.setf(ios::showpoint);

cout.setf(ios::floatfield,ios::fixed);

cout << setw(5) << unEmp.matricule

<< setw(12) << setprecision(2) << unEmp.nbHr * unEmp.taux << setw(5) << " " << unEmp.poste << endl;

}

void afficher (Employe * p, int nbEmp,int debut,int fin,char * mess) { cout << "Liste des " << debut << " premiers et " << fin

<< " derniers employes:\n";

for (int i = 0 ; i < nbEmp ; i++) {

if (i < debut || i >= nbEmp - fin) { cout << setw(4) << i+1 << ") " ; afficher(*p);

}

else if (i == debut)

cout << setw(4) << i+1 << ") etc ...\n";

p++;

IFT1166, été 2004 36

(10)

} }

int indSentinelle(int aChercher, Employe * emp, int nbEmp) { int indice = -1 ;

(emp+nbEmp)->matricule = aChercher;

do

indice++;

while ( (emp+indice)->matricule != aChercher );

if (indice < nbEmp) return indice;

else

return -1 ; }

int indSequentielle(int aChercher, Employe * emp, int nbEmp) { for (int indice = 0; indice < nbEmp ; indice++)

if ( emp[indice].matricule == aChercher ) return indice;

return -1 ; }

void main() {

Employe * emp = new Employe[MAX_EMP];

int nbEmp ;

lireRemplir(emp, nbEmp);

afficher(emp, nbEmp, 5, 3, " apres la lecture ");

int ind2636 = indSentinelle(2636, emp, nbEmp);

if (ind2636 != -1)

cout << "On trouve 2636 a l'indice : " << ind2636 << endl ; cout << "indice de 9999 dans le tableau : "

<< indSentinelle(9999, emp, nbEmp) << endl ; cout << "indice de 3142 dans le tableau : "

<< indSequentielle(3142, emp, nbEmp) << endl ; }

/* Exécution:

Liste des 5 premiers et 3 derniers employes:

1) 2754 1270.72 P 2) 1848 1431.12 P 3) 2636 804.38 S 4) 1750 1138.44 A 5) 2168 1253.87 A 6) etc ...

241) 3142 1607.94 A 242) 2352 1609.77 A 243) 4915 1462.79 P On trouve 2636 a l'indice : 2

(11)

indice de 9999 dans le tableau : -1

indice de 3142 dans le tableau : 240 */

8) Surdéfinition de fonctions :

La surdéfinition permet au programmeur de déclarer plusieurs fonctions ayant le même nom, mais ayant des paramètres

différents ou de genre différent (avec return ou de type void).

Exemple : Dans l’exemple fichier.cpp précédent, définir plusieurs fonctions afficher

1) afficher un SEUL pays

2) afficher une liste partielle des pays (certains pays au début et certains autres pays de la fin)

3) afficher des pays dont le nom est identique à la capitale

4) afficher 5 pays (1 par continent) qui sont plus grand

afficher 5 autres pays (1 par continent) qui sont plus peuplés 5) afficher 1 SEUL pays d'un continent voulu avec ...

Niveau du C : 5 fonctions avec 5 noms différents : afficher1, afficher2, afficher3, afficher4, afficher5

Niveau du C++ : Grâce à la surdéfinition de fonctions, on a le droit d’utiliser le même nom de fonction ici afficher : Le C++ applique la fonction "appropriée" grâce au nombre de paramètres ou type de paramètres

// afficher les informations d'un seul pays void afficher(Nation unPays) {

cout << setw(LONGUEUR) << unPays.nom

<< setw(LONGUEUR) << unPays.capitale

<< setw(8) << unPays.superficie

<< setw(12) << unPays.population

<< setw(10) << nomContinent[unPays.continent-1]

<< endl;

}

// afficher une liste partielle des pays

void afficher(Nation pays[], int nbPays, int debut, int fin, char quand[]) {

cout << "Liste partielle des "

<< debut << " premiers pays et "

<< fin << " derniers pays "

<< quand << " le tri : " << endl ; for(int i = 0 ; i < nbPays ; i++)

if ( i < debut || i >= nbPays-fin ){

cout << setw(3) << i+1 << ") " ;

IFT1166, été 2004 38

(12)

afficher(pays[i]);

} else

if ( i == debut )

cout << " etc .... \n";

cout << endl ; }

void afficher(Nation pays[], int nbPays) {

cout << "\nListe speciale des pays dont le nom est identique a la capitale:\n";

int rang = 0;

for(int i = 0 ; i < nbPays ; i++)

if ( strcmp(pays[i].nom, pays[i].capitale) == 0) cout << setw(3) << ++rang << ". ",

afficher(pays[i]);

}

void afficher(Nation pays[], int nbPays, char codeVoulu, char message[]) {

cout << "\nPour chacun des 5 continents, le pays le plus "

<< message << endl;

for(int leConti = Afrique ; leConti <= Europe ; leConti++) { int ind = indicePlus(pays, nbPays, leConti, codeVoulu);

afficher(pays[ind]);

}

cout << endl << endl ; }

void afficher(int nbPays, Nation pays[]) { afficher(pays, nbPays, 'S', "grand");

afficher(pays, nbPays, 'P', "peuple");

}

9) Patrons de fonctions :

(13)

Modèle que le compilateur utilise pour créer des fonctions au besoin.

Exemple: fonction qui permet de retourner la valeur la plus grande

- deux int

int maximum( int a, int b) {

return a > b ? a: b;

} - deux float

float maximum( float a, float b) {

return a > b ? a: b;

} - deux long

float maximum( long a, long b) {

return a > b ? a: b;

}

On constate que nous sommes en présence du même code, seul le type traité diffère.

Le C++ permet de définir un patron (template) pour cette fonction :

template <class T>

T maximum( T a, T b) {

return a > b ? a: b;

}

T est un paramètre qui prend la place d’un type, n’importe quel type (int, float, long, char etc.)

Contrairement à la surdéfinition de fonctions, nous sommes en présence d’une seule définition qui va être valable pour tous les types.

Exemple complet :

#include <iomanip.h>

#include <iostream.h>

template < class T>

T maximum( T a, T b) {

IFT1166, été 2004 40

(14)

return a > b ? a: b;

}

void main() {

int age1 = 32, age2 = 18;

cout << "La plus grande valeur entre :\n\n";

cout << setw(8) << age1 << " ans et "

<< age2 << " ans est " << maximum(age1, age2) << " ans "

<< endl;

float taille1 = 1.72, taille2 = 1.85;

cout.setf(ios::fixed);

cout << setw(8) << setprecision(2) << taille1 << " metre et "

<< setw(6) << setprecision(2) << taille2 << " metre est"

<< setw(6) << setprecision(2) << maximum(taille1, taille2) << " metre\n";

long popu1 = 30000000, popu2 = 73000000;

cout << setw(9) << popu1 << " habitants et "

<< popu2 << " habitants est "

<< maximum(popu1, popu2) << " habitants\n";

}

/* Exécution :

La plus grande valeur entre : 32 ans et 18 ans est 32 ans

1.72 metre et 1.85 metre est 1.85 metre

30000000 habitants et 73000000 habitants est 73000000 habitants

*/

10) Paramètres par défaut :

En C++, le nombre de paramètres effectifs utilisés lors de l’appel des fonctions est inférieur ou égal au nombre de paramètres formels spécifiés dans la définition des

fonctions. On commence à omettre à partir de la fin. On peut aussi spécifier des valeurs par défaut.

Exemple :

(15)

/* Parametres par defaut (les derniers parametres) Fichier defaut.cpp

*/

#include <iostream.h>

#include <iomanip.h>

double salHebdo(double tauxHoraire, double nbHeures = 40.0) { return tauxHoraire * nbHeures;

}

void afficher(double t[],int n,char message[],int debut= 5,int fin =3 ) {

cout << "\nContenu des " << debut << " premier(s) et "

<< fin << " dernier(s) elements du "

<< message << endl;

cout.setf(ios::fixed);

for(int i= 0 ; i < n ; i++)

if ( i < debut || i >= n-fin ) cout << setw(3) << i

<< setw(10) << setprecision(2) << t[i] << endl;

else if (i == debut)

cout << " etc ...\n";

cout << endl;

}

void main() {

cout << "35 heures a 20$ de l'heure : "

<< salHebdo(20.00, 35.00) << " $ par semaine\n";

cout << "40 heures a 15.50$ de l'heure : "

<< salHebdo(15.50) << " $ par semaine\n";

double taille[15] = { 1.75, 1.62, 1.58, 1.93, 1.42, 1.61, 1.86, 1.38, 1.66 }, poids[12] = { 45.7, 64.3, 57.8, 87.6, 66.6 };

afficher(poids, 5, "tableau des poids", 2, 1);

afficher(taille, 9, "tableau des tailles");

}

Exécution :

/*

35 heures a 20$ de l'heure : 700 $ par semaine 40 heures a 15.50$ de l'heure : 620 $ par semaine

Contenu des 2 premier(s) et 1 dernier(s) elements du tableau des poids 0 45.70

IFT1166, été 2004 42

(16)

1 64.30 etc ...

4 66.60

Contenu des 5 premier(s) et 3 dernier(s) elements du tableau des tailles 0 1.75

1 1.62 2 1.58 3 1.93 4 1.42 etc ...

6 1.86 7 1.38 8 1.66

*/

11) Fonctions en ligne : Utilité :

- gérer les appels de fonctions faible (surtout pour les petites fonctions).

- éviter l’accès via la table des fonctions (gain du temps)

Syntaxe : inline fonction_donnée Exemple :

int inline abs(int x) { return (x<0)?-x:x;

}

void main() { int n,a=-4;

n=abs(a)*2; /*le programme calcule d’abord abs(a) puis le résultat est *2 */

cout << n << endl // affiche 8 }

Références

Documents relatifs

Une variable est associé à symbole (un nom qui sert d'identificateur) qui renvoie à une position de la mémoire (une adresse) dont le contenu peut prendre successivement

Si le nombre de participants est inférieur ou égale à 50 l’aide sera de 80€ par personne sinon elle ne sera plus que de 50€ par participant.. On souhaite écrire un algorithme

Mathematical modelling and nume- rical analysis - Modélisation mathématique et analyse numérique » implique l’accord avec les conditions générales d’utilisation

Un signal peut avoir une valeur moyenne nulle et une valeur efficace non-nulle. La valeur efficace d’un signal continu U

Le juge pour enfants Édouard Durand a été nommé coprésident de la commission sur l’inceste.. • BRUNO LÉVY/DIVERGENCE POUR LA VIE POUR

◮ On peut le faire avec un tableau int tab[2000] et une variable supplémentaire int taille qui sera initialisée à chaque saisie avec le nombre de valeurs que l’utilisateur

La cascade MAPK (Mitogen-Activated Protein Kinase) est une voie de signalisation paradigmatique qui joue un rˆ ole essentiel dans plusieurs ´ ev` enements cellulaires.. Dans

Or, comme d´ej` a indiqu´e, ce mod`ele est trop simpliste : il n´eglige le fait que les ´etats de Mos possible sont en aussi trois : on distingue plutˆot trois ´etats de