La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Structures de données IFT-10541

Présentations similaires


Présentation au sujet: "Structures de données IFT-10541"— Transcription de la présentation:

1 Structures de données IFT-10541
Abder Alikacem Du C au C++ Édition Septembre 2009 Département d’informatique et de génie logiciel

2 Plan Introduction Du C au C++ Les commentaires, Le type bool
02/04/2017 Plan Introduction Du C au C++ Les commentaires, Le type bool Déclaration et visibilité des variables Le qualificatif const Les fonctions inline Les fonctions statiques Surcharge des fonctions Fonctions avec arguments par défaut Les fonctions d’entrée/sortie Vice-rectorat à la recherche / octobre 2005

3 Historique des langages de programmation
02/04/2017 Historique des langages de programmation ~ ‘Premier programme' (Ada Lovelace) Calcul (Konrad Zuse) FORTRAN (John Backus) ALGOL LISP (McCarthy) COBOL (Grace Hopper) BASIC (Kemeny, Kurtz) APL PL/1 (Heinz Zemanek) Simula (Dahl, Nygaard) MUMPS (Octo Barnett, Neil Pappalardo, Kurt Marble (MIT)) HAL (de la NASA pour le Space Shuttle) Logo (Seymour Papert) BCPL Forth (Charles H. Moore) Pascal (Niklaus Wirth, Kathleen Jensen) sh C (Brian W. Kernighan, Dennis Ritchie) (premier de Ken Thompson) ML Prolog (Colmerauer et. al.) Modula-2 awk Smalltalk (Alan Kay) Ada Objective C (ObjC) (Brad Cox) C++ (Bjarne Stroustrup) Eiffel (Bertrand Meyer) Perl (Larry Wall) Erlang (Joe Armstrong et al.) Tcl (John Ousterhout) Python (Guido van Rossum) Ruby (Yukihiro Matsumoto) Delphi Java (Sun Microsystems) PHP (Rasmus Lerdorf), JavaScript D (Walter Bright) C# (Microsoft dans le cadre de .NET) Visual Basic .NET Delphi.NET BlitzMax Basic, OOP, OpenGL Chrome (Next Generation Object Pascal pour .NET) Vice-rectorat à la recherche / octobre 2005

4 Définition de Wikipedia
02/04/2017 Définition de Wikipedia Le C++ est un langage de programmation qui permet la programmation procédurale la programmation orientée objet la programmation générique. Au cours des années 1990, le C++ est devenu l'un des langages de programmation les plus populaires dans l'industrie informatique. Le langage C++ n'appartient à personne et par conséquent n'importe qui peut l'utiliser sans payer de droits. Bjarne Stroustrup a développé le C++ au cours des années 1980, alors qu'il travaillait dans le laboratoire de recherche Bell d'AT&T. Il s'agissait en l'occurrence d'améliorer le langage C et il l'avait d'ailleurs nommé C with classes (« C avec des classes »). Les premières améliorations se concrétisèrent donc par l'ajout du support des classes, suivies par de nombreuses autres comme les fonctions virtuelles, la surcharge d'opérateurs, l'héritage (simple ou multiple), les « templates », la gestion d'exceptions... Le langage C++ est normalisé par l'ISO. Sa première normalisation date de 1998 (ISO/CEI 14882:1998), et sa dernière de 2003 (ISO/CEI 14882:2003). La normalisation de 1998 standardise la base du langage (Core Language) ainsi que la bibliothèque C++ standard (C++ Standard Library). La normalisation de 2003 inclut également la Standard Template Library et la C Standard Library . Il existe de nombreuses autres bibliothèques en C++ non incluses dans le standard. De plus, le C++ permet l'utilisation des nombreuses bibliothèques C existantes. Vice-rectorat à la recherche / octobre 2005

5 Bjarne Stroustrup Bjarne Stroustrup définit le successeur de
02/04/2017 Bjarne Stroustrup Bjarne Stroustrup définit le successeur de C. Plutôt que D ou P (soit la suite de C dans l’alphabet, ou la suite de C dans BCPL), Stroustrup baptise son bébé C++ (le premier nom donné à ce nouveau langage était “C with classes”.), entendant par là que C++ est «a better C», un C meilleur, incrémenté. Dans l'idée de Stroustrup, C++ devait conserver les idées de base ayant conduit à la réalisation de C (typage statique, efficacité d'exécution, langage compilé). Il est intéressant de constater que UNIX, C et C++ sont tous des bricolages de laboratoire. Vice-rectorat à la recherche / octobre 2005

6 02/04/2017 Langages C, C++ et UNIX En ce sens, ces trois produits sont à l’opposé de produits comme CHILL ou ADA, ayant fait l’objet d’une spécification très poussée. Un langage, aussi bon ou aussi mauvais soit-il, n’a jamais fait la qualité ni le succès d’un programme, comme le démontre nombre de réussites et d’échec industriels. Beaucoup plus que le langage de programmation utilisé, c’est le code déjà écrit et testé qui permet d’optimiser les coûts de production de grands logiciels. Le meilleur langage est celui que l’on connaît, le meilleur code, et le plus rapidement disponible- celui qui tourne déjà sans erreurs. Sur la base de ces hypothèses, C++ apparaît comme un langage très puissant, connu par beaucoup de programmeurs dans le monde, et soutenu par une masse de code existant et disponible probablement à nulle autre pareille. Vice-rectorat à la recherche / octobre 2005

7 02/04/2017 Avantages du langages Ironiquement, les principaux “+” (surcharge d'opérateurs, classes) de C++ sont des caractéristiques introduites dans des langages antérieurs à C lui-même, qui est à l'origine de C++ (Algol-68, Simula-67). On peut se fonder actuellement sur des bibliothèques de logiciels très vastes (communications, protocoles, fenêtrages, algorithmique, traitement d’images, etc...) offrant des interfaces écrites dans un même langage. Vice-rectorat à la recherche / octobre 2005

8 Du C au C++ Premier + Deuxième +
02/04/2017 Du C au C++ Compatibilité avec le langage C. Un compilateur C++ peut compiler un code C écrit selon la norme ANSI C. Typage fort Le langage C est un langage faiblement typé.Les compilateurs C sont “ laxistes ” et laissent beaucoup (trop) de liberté au programmeur. Le langage C++ introduit un typage fort beaucoup + strict. Les compilateurs font + de vérifications tout en produisant un code aussi efficace. Références Surdéfinition des fonctions (surcharges) Généricité Premier + Deuxième + Classes et objets Héritages simple et multiple Polymorphisme et liaison dynamique Vice-rectorat à la recherche / octobre 2005

9 Les commentaires /* commentaire traditionnel en C et C++ */ int main()
02/04/2017 Les commentaires /* commentaire traditionnel en C et C++ */ int main() { // commentaire de fin de ligne //... } /** commentaire spécial type Doxygen (ou Java) Vice-rectorat à la recherche / octobre 2005

10 Définition des variables
02/04/2017 Définition des variables En C++ on peut déclarer les variables ou fonctions n'importe où dans le code. La portée de telles variables va de l'endroit de la déclaration jusqu'à la fin du bloc courant. Exemple #include <iostream> int main() { int j = 0; for(int w=0; w<10; w++, j++) int i = w; cout << i << ' '; } int k = j; //permet une initialisation "dynamique"    return 0; Vice-rectorat à la recherche / octobre 2005

11 Visibilité des variables
02/04/2017 Visibilité des variables L'opérateur de résolution de portée :: permet d'accéder aux variables globales, interdites, plutôt qu'aux variables locales. #include <iostream> int i = 11; int main() { int i = 34; int i = 23; ::i = ::i + 1; cout << ::i << " " << i << endl; } return 0; Vice-rectorat à la recherche / octobre 2005

12 Déclaration et initialisation des variables
02/04/2017 Déclaration et initialisation des variables Il est possible, en C++ comme en C, d’affecter une valeur à une variable au moment de sa déclaration. Il y a cependant 2 syntaxes en C++ pour le faire. Syntaxe classique: int i =2; //comme dans le langage C Syntaxe propre au C++: int i(2); La nouvelle syntaxe de la déclaration-initialisation est: <type> <identificateur>(<valeur>); Où valeur est n’importe quel littéral ou expression du type indiqué. Exemples int i(18); float var(3.1415); char c(’a’); int j(i); float x(2.0*var); Vice-rectorat à la recherche / octobre 2005

13 02/04/2017 Le types bool Le C++ contient un type bool servant à représenter le résultat des opérations logiques. Une variable de type bool ne peut prendre que deux valeurs: true et false. Par exemple: bool b=true; b = 5<4; // b vaut false b = 5+4; // b vaut true Remarquez qu’une expression arithmétique convertie en un bool vaut true si et seulement si elle s’évalue à une valeur différente de 0. La fonction suivante détermine si un tableau d’entiers est en ordre croissant: bool croissant(int tab[], int n) { for (int i=1; i<n; i++) if (tab[i]<tab[i-1])return false; return true; } Vice-rectorat à la recherche / octobre 2005

14 02/04/2017 Le qualificatif const Il est possible en C++ de spécifier que certains objets ne doivent pas être modifiés. Cela est utile pour définir des constantes symboliques mais aussi pour indiquer que certains objets passés en paramètre de doivent pas être modifiés. On déclare une constante en ajoutant le mot clef const. Par exemple: const float pi=3.1416; // Cette valeur ne pourra plus être modifiée // par le programme, plus exactement toute tentative de modification // sera rejetée par le compilateur, qui signalera une erreur. const int tab[]={1,2,3,4,5} // tab[i] est une constante int n=0; const int* cp1=&n; // *cp1 ne peut pas être modifié int* const cp2=&n; // cp2 ne peut pas être modifié const int* const cp3=&n // cp3 et *cp3 ne peuvent pas être modifiés Vice-rectorat à la recherche / octobre 2005

15 02/04/2017 Le qualificatif const Remarquez qu'une constante doit être initialisée lors de sa déclaration. De façon générale, le mot clef const modifie un type afin de restreindre les possibilités d'utilisation d'un objet. Par exemple on peut exiger qu'une variable dont l'adresse est passée en paramètre ne soit pas modifiée. void f(const int* p) { // *p ne peut pas être modifié } void g(const int t[]) t[0]=0; // erreur Vice-rectorat à la recherche / octobre 2005

16 02/04/2017 Le type composé struct typedef n'est plus obligatoire pour renommer un type. Exemple struct FICHE { char *nom, *prenom; int age; }; FICHE adherent, *liste; Vice-rectorat à la recherche / octobre 2005

17 02/04/2017 Les fonctions inline Le C++ dispose du mot clé inline, qui permet de modifier la méthode d’implémentation des fonctions. Placé devant la déclaration d’une fonction, il propose au compilateur de ne pas instancier cette fonction. Cela signifie que l’on désire que le compilateur remplace l’appel de la fonction par le code correspondant. Si la fonction est grosse ou si elle est appelée souvent, le programme devient plus gros, puisque la fonction est réécrite à chaque fois qu’elle est appelée. En revanche, il devient nettement plus rapide, puisque les mécanismes d’appel de fonctions, de passage des paramètres et de la valeur de retour sont ainsi évités. De plus, le compilateur peut effectuer des optimisations additionnelles qu’il n’aurait pas pu faire si la fonction n’était pas inlinée. En pratique, on réservera cette technique pour les petites fonctions appelées dans du code devant être rapide (à l’intérieur des boucles par exemple), ou pour les fonctions permettant de lire des valeurs dans des variables. Vice-rectorat à la recherche / octobre 2005

18 02/04/2017 Les fonctions inline Cependant, il faut se méfier. Le mot clé inline est un indice indiquant au compilateur de faire des fonctions inline. Il n’y est pas obligé. La fonction peut donc très bien être implémentée classiquement. Pire, elle peut être implémentée des deux manières, selon les mécanismes d’optimisation du compilateur. De même, le compilateur peut également inliner les fonctions normales afin d’optimiser les performances du programme. De plus, il faut connaître les restrictions des fonctions inline : • elles ne peuvent pas être récursives ; • elles ne sont pas instanciées, donc on ne peut pas faire de pointeur sur une fonction inline. Vice-rectorat à la recherche / octobre 2005

19 02/04/2017 Les fonctions inline Si l’une de ces deux conditions n’est pas vérifiée pour une fonction, le compilateur l’implémentera classiquement (elle ne sera donc pas inline). Enfin, du fait que les fonctions inline sont insérées telles quelles aux endroits où elles sont appelées, il est nécessaire qu’elles soient complètement définies avant leur appel. Cela signifie que, contrairement aux fonctions classiques, il n’est pas possible de se contenter de les déclarer pour les appeler, et de fournir leur définition dans un fichier séparé. Dans ce cas en effet, le compilateur générerait des références externes sur ces fonctions, et n’insérerait pas leur code. Ces références ne seraient pas résolues à l’édition de lien, car il ne génère également pas les fonctions inline, puisqu’elles sont supposées être insérées sur place lorsqu’on les utilise. Vice-rectorat à la recherche / octobre 2005

20 Les fonctions inline Exemple inline int Max(int i, int j) {
02/04/2017 Les fonctions inline Exemple inline int Max(int i, int j) { if (i>j) return i; else return j; } Pour ce type de fonction, il est tout à fait justifié d’utiliser le mot clé inline. Vice-rectorat à la recherche / octobre 2005

21 Les fonctions statiques
02/04/2017 Les fonctions statiques Par défaut, lorsqu’une fonction est définie dans un fichier C/C++, elle peut être utilisée dans tout autre fichier pourvu qu’elle soit déclarée avant son utilisation. Dans ce cas, la fonction est dite externe. Il peut cependant être intéressant de définir des fonctions locales à un fichier, soit afin de résoudre des conflits de noms (entre deux fonctions de même nom et de même signature mais dans deux fichiers différents), soit parce que la fonction est uniquement d’intérêt local. Le C et le C++ fournissent donc le mot clé static qui, une fois placé devant la définition et les éventuelles déclarations d’une fonction, la rend unique et utilisable uniquement dans ce fichier. À part ce détail, les fonctions statiques s’utilisent exactement comme des fonctions classiques. Vice-rectorat à la recherche / octobre 2005

22 Les fonctions statiques
02/04/2017 Les fonctions statiques Exemple // Déclaration de fonction statique static int locale1(void); // Définition de fonction statique static int locale2(int i, float j) { return i*i+j; } Vice-rectorat à la recherche / octobre 2005

23 La surcharge des fonctions
02/04/2017 La surcharge des fonctions Contrairement au langage C, deux fonctions peuvent avoir le même nom, pourvu que leurs signatures soient différentes. On parle alors de surchage de fonctions. La surcharge est un mécanisme qui permet de donner différentes signatures d'arguments à une même fonction. Vous pouvez nommer de la même façon des fonctions de prototypes différents. L'intérêt est de pouvoir nommer de la même manière des fonctions réalisant la même opération à partir de paramètres différents. Vice-rectorat à la recherche / octobre 2005

24 La surcharge des fonctions
02/04/2017 La surcharge des fonctions Il est possible donc d'utiliser le même nom pour désigner deux fonctions différentes à la condition que leur liste d'opérandes ne soit pas identique: int mult(int x) { return 2*x; } int mult(int x, int y) return x*y; Vice-rectorat à la recherche / octobre 2005

25 La surcharge des fonctions
02/04/2017 La surcharge des fonctions Autre exemple int somme(int arg1, int arg2, int arg3) // fonction 1 { return arg1+arg2+arg3; } int somme(int arg1, int arg2) // fonction 2 return arg1+arg1; float somme(float arg1, float arg2) // fonction 3 int main int x1, x2; float y; x1 = somme(1,4,2); // appel de la fonction 1 x2 = somme(1,4); // appel de la fonction 2 y = somme(2,4); // appel de la fonction 3 Vice-rectorat à la recherche / octobre 2005

26 La surcharge des fonctions
02/04/2017 La surcharge des fonctions Le compilateur s'y retrouve parce que le nom « interne » de la fonction contient la liste des paramètres. À la compilation, en consultant la liste des paramètres effectifs, le compilateur établit quelle est la forme de la fonction à appeler. Il est impossible d'avoir des fonctions qui ne diffèrent que par leur type de retour. En effet, le compilateur ne peut pas les distinguer si on omet de récupérer la valeur retournée. Vice-rectorat à la recherche / octobre 2005

27 Fonctions avec arguments par défaut
02/04/2017 Fonctions avec arguments par défaut Le langage C++ permet de spécifier une valeur par défaut aux arguments de fonctions. De cette manière, quand vous utilisez la fonction, vous n'avez à spécifier ces arguments que lorsque leur valeur diffère du défaut. Les valeurs par défaut ne peuvent être spécifiés que lors de la déclaration de la fonction et ne doivent pas être rappelés lors de définition de la fonction. Vice-rectorat à la recherche / octobre 2005

28 Fonctions avec arguments par défaut
02/04/2017 Fonctions avec arguments par défaut Dans l’exemple de la fonction mult() par exemple, on aurait pu obtenir le même résultat en utilisant un argument par défaut: int mult(int x, int y=2) { return x*y } Lors d'un appel à la fonction mult, si le second paramètre est omis alors il est automatiquement remplacé par la valeur 2. Ainsi mult(3) retournera 6 et mult(3,5) retournera 15. Seul les derniers paramètres peuvent avoir une valeur de défaut. Par exemple la définition suivante est invalide. int mult(int x=2, int y) return x*y; Vice-rectorat à la recherche / octobre 2005

29 Fonctions avec arguments par défaut
02/04/2017 Fonctions avec arguments par défaut Dans le cas d’une fonction avec prototype et définition distincts, la spécification des arguments avec valeur par défaut ne doit être réalisée que lors du prototypage. Exemple void f(int x, int y=2, int z=3); //prototype void f(int x, int y, int z) { ... } // définition ... f(1) <=> f(1,2,3) f(0,1) <=> f(0,1,3) Vice-rectorat à la recherche / octobre 2005

30 02/04/2017 Les entrées/sorties Les fonctionnalités d'entrées / sorties en C++ sont orientées objet. Elles sont gérées par le biais d’un ensembles de type (classes) spécialisés, les flots (streams). L’idée de base des flots est de séparer l’aspect logique des entrées-sorties (i.e. leur intégration dans des programmes) de leur aspect physique (i.e. leur réalisation par le biais de périphériques particuliers). Ainsi, un flot représente un flux de données entre le programme et un dispositif d’entrée-sorties externe (écran, imprimante, ...) ou un fichier. La librairie standard <iostream> permet de faire des entrées-sorties par flots. Notons que pour obtenir de meilleures performances, un tampon mémoire, par lequel les données transitent, est par défaut associé à chaque flot. Vice-rectorat à la recherche / octobre 2005

31 Les entrées/sorties La famille des iostream Une stream en C++ :
02/04/2017 Les entrées/sorties La famille des iostream Une stream en C++ : séquence de caractères permettant de faire les opérations d'entrées/sorties. Une ostream gère les sorties inclut la définition de l'opérateur d’insertion <<. Une istream gère les entrées inclut la définition de l'opérateur d’extraction >>. Vice-rectorat à la recherche / octobre 2005

32 02/04/2017 Les entrées/sorties <iostream>est plus sûr du point de vue typage que <stdio.h> du C, est moins source d'erreurs, améliore les performances, est extensible, et enfin que certaines des classes qui le composent peuvent être sous-classées. Plus sûres du point de vue typage: avec <iostream.>, le type de l'objet sujet à une E/S est connu statiquement par le compilateur. <stdio.h> utilise lui les champs "%" pour connaître dynamiquement le type de l'objet. Moins sources d'erreurs: avec <iostream.>, il n'est pas nécessaire d'utiliser ces champs "%", qui sont redondants et qui doivent être consistants avec l'objet effectivement sujet à l'E/S. Enlever cette redondance élimine toute une catégorie d'erreurs possibles. Extensibles: les mécanismes C++ de <iostream.h> permetttent à l'utilisateur de définir de nouveaux types qui pourront être sujets à des E/S, et ce sans casser le code existant. Imaginez le chaos que ça créerait si chacun ajoutait ses propres champs, incompatibles, "%" à printf() et à scanf()?!). Vice-rectorat à la recherche / octobre 2005

33 02/04/2017 Les entrées/sorties Sous-classables: les mécanismes C++ de <iostream.h> sont construits sur des classes, comme par exemple ostream et istream. À la différence du FILE* de <stdio.h>, ce sont de vraies classes et elles sont de ce fait sous-classables. Cela signifie que vous pouvez avoir vos propres types utilisateur, qui ressemblent à des flots (streams) et qui agissent comme tels, mais qui font aussi toutes les choses étranges et merveilleuses que vous avez décidé. Vous accédez automatiquement à des tonnes de code d'E/S écrits par des utilisateurs que vous ne connaissez même pas, utilisateurs qui eux-mêmes n'ont rien besoin de connaître de votre classe de "flot étendu". Les principales conséquences dans l'utilisation des flots sont: vitesse d'exécution plus rapide vérification de type : pas d'affichage erroné on peut utiliser les flux avec les types utilisateurs Vice-rectorat à la recherche / octobre 2005

34 02/04/2017 Les entrées/sorties Les flots de sorties (de type std::ostream) sont std::cout et std::cerr pour le standard et l’erreur respectivement. Le flot d’entrée (de type std::istream) est std::cin. Comme l’indique le préfixe std::, tous ces objets sont dans le namespace std. • cin : flot lié à l’entrée standard, qui par défaut est le clavier • cout : flot lié à la sortie standard, qui par défaut est la console • cerr : flot lié à la sortie d’erreur standard, qui par défaut est la console Les opérations de sorties sont réalisées à l’aide de l’opérateur d’insertion « << », tandis que celle d’entrées le sont à l’aide de l’opérateur d’extraction, « >> ». Vice-rectorat à la recherche / octobre 2005

35 cout << expression;
02/04/2017 Les entrées/sorties Par exemple, l'écriture à l'écran de la valeur d’une expression se traduit par le code suivant : cout << expression; Cela sous entend la surcharge de l'opérateur << pour le type de donnée correspondant à expression. Ce travail a été réalisé pour la plupart des types de base du C++. Il vous appartiendra de le faire pour vos propres classes (surcharge des opérateurs << et >>). Vice-rectorat à la recherche / octobre 2005

36 Les entrées/sorties Exemples int n=2; double f=1.5; char c='z';
02/04/2017 Les entrées/sorties Exemples int n=2; double f=1.5; char c='z'; cout<<n; // afficher un entier sur la sortie standard cout<<f<<endl; // afficher un double et un changement de ligne cout<<"n = "<<n; // afficher: n = 2 cout<<c; // afficher un caractère cin >>c; // lire un caractère (saute les espaces) cin.get(c) // lire un caractère (ne saute pas les espaces) cin >>n>>f; // lire un entier puis un double cerr<<"Erreur"; // afficher un message sur l'erreur standard Vice-rectorat à la recherche / octobre 2005

37 Les entrées/sorties Syntaxe pour l’écriture sur la sortie standard
02/04/2017 Les entrées/sorties Syntaxe pour l’écriture sur la sortie standard cout << <expression1> << <expression2> << ... << <expressionn>; Les opérateurs << sont prévus pour être chaînés. Vous pouvez donc les cumuler sur la même ligne de code, par exemple: int i; int j; cout << i << " " << j << endl; La constante symbolique endl vous permet de changer de lignes indépendamment de l'architecture dans laquelle le programe évolue. Les chaînes de c a r a c t è r e s doivent être indiquées entre guillemets anglais «"», tandis que les caractères simples sont eux indiqués entre apostrophes «’». Les valeurs affichées ne sont, pas délimitées par défaut (pas d’espaces séparateurs). Les délimiteurs son t donc à indiquer explicitement, par exemple par ‘ ‘ ou" ". Vice-rectorat à la recherche / octobre 2005

38 Les entrées/sorties Syntaxe pour la lecture sur l’entrée standard
02/04/2017 Les entrées/sorties Syntaxe pour la lecture sur l’entrée standard cin << <var1> << <var2> << ... << <varn>; #include <iostream> int main() { int i; double x; cout << "Valeurs pour i et x: " << flush; cin >> i >> x; cout << "=> " << i << ", " << x << endl; return 0; } Le manipulateur flush permet d’assurer l’affichage de la ligne courante, en l’absence de saut de ligne (il ordonne le vidage du tampon d’affichage). Remarque. cerr n’a pas de tampon mémoire: toutes les données introduites sont immédiatement acheminées vers la sortie d’erreur standard. Il n’est donc pas nécessaire, pour ce flot, de demander explicitement le vidage du tampon mémoire au moyen de flush. Vice-rectorat à la recherche / octobre 2005

39 Les entrées/sorties Des méthodes des iostream
02/04/2017 Les entrées/sorties Des méthodes des iostream La istream : En plus d'utiliser l'opérateur surchargé >> … méthodes intéressantes get() ignore() getline(). La ostream : En plus d'utiliser l'opérateur surchargée << … méthodes intéressantes : precision() width() fill() setf() et unsetf() Vice-rectorat à la recherche / octobre 2005

40 Les entrées/sorties std::istream& get() Quelques surcharges :
02/04/2017 Les entrées/sorties std::istream& get() Quelques surcharges : int istream::get() Pour obtenir le code ASCII d'un caractère istream& istream::get(char& c) Pour obtenir un caractère istream& istream::get(char* strP, int dim, char delim = '\n') Pour obtenir une chaîne de caractères d'une dimension déterminée, ou jusqu'à un caractère de fin, ici par défaut à '\n' prend les espaces mais ne consomme pas le caractère de fin. Vice-rectorat à la recherche / octobre 2005

41 Les entrées/sorties std::istream& get()
02/04/2017 Les entrées/sorties std::istream& get() int istream:: get(), pour obtenir le code ASCII d'un caractère. cout << "Entrez un caractère "; int entier = cin.get(); cout << "Le code ASCII est : " << entier << endl; Résultat Entrez un caractère : A Le code ASCII est : 65 Vice-rectorat à la recherche / octobre 2005

42 Les entrées/sorties std::istream& get()
02/04/2017 Les entrées/sorties istream& istream::get(char& c), pour obtenir un caractère dans le paramètre c. std::istream& get() #include <iostream> using namespace std; int main() { char unChar; cout << "Entrez un caractere [. pour quitter]: "; cin.get(unChar); while (unChar != '.') if (cin) cout << "Le caractere est : " << unChar << endl << endl; } // --- On consomme la fin de ligne cin.get(); return 0; Vice-rectorat à la recherche / octobre 2005

43 Les entrées/sorties std::istream& get()
02/04/2017 Les entrées/sorties std::istream& get() istream& istream::get(char* strP, int dim, char delim = '\n'), pour obtenir une chaîne de caractères d'une dimension déterminée ou jusqu'à un caractère de fin, ici par défaut à '\n'. Prend les espaces mais ne consomme pas le caractère de fin. Si dimension dépassée les caractères supplémentaires resteront dans la stream jusqu'au délimiteur. Il faut gérer cette possibilité : vider la stream de ses caractères. Vice-rectorat à la recherche / octobre 2005

44 Les entrées/sorties std::istream& get() #include <iostream>
02/04/2017 Les entrées/sorties #include <iostream> using namespace std; int main() { char buffer[11]; cout << "Entrez une chaine [. pour quitter]: "; cin.get(buffer, 10); while (strcmp(buffer, ".") != 0) if (cin) cout << "La chaine de caractères est : " << buffer << endl; } // --- On consomme la fin de ligne car non récupéré // --- de la stream. cin.get(); return 0; std::istream& get() Vice-rectorat à la recherche / octobre 2005

45 Les entrées/sorties std::istream& get() Résultat:
02/04/2017 Les entrées/sorties std::istream& get() Résultat: Entrez une chaîne [. pour quitter] : Jean-Luc La chaîne de caractères est : Jean-Luc Entrez une chaîne [. pour quitter] : Jean-Luc Boutin La chaîne de caractères est : Jean-Luc B //Prend seulement 10 caractères Entrez une chaîne [. pour quitter] : La chaîne de caractères est : utin //Le 'o' est consommé par cin.get() //et "utin" est immédiatement affiché. Vice-rectorat à la recherche / octobre 2005

46 Les entrées/sorties std::istream& ignore()
02/04/2017 Les entrées/sorties std::istream& ignore() Pour enlever les caractères non désirés dans la stream, : istream::ignore(). Par défaut, ignore() sans paramètre est l'équivalent de get(). Permet de spécifier le nombre maximal de caractères à enlever ainsi que la condition de fin ou délimiteur, par défaut à '\n'. Choisir un nombre arbitrairement grand pour s'assurer de vider la stream avant de continuer. Vice-rectorat à la recherche / octobre 2005

47 Les entrées/sorties std::istream& ignore() #include <iostream>
02/04/2017 Les entrées/sorties #include <iostream> using namespace std; int main() { char buffer[11]; cout << "Entrez une chaine [. pour quitter]: "; cin.get(buffer, 10); while (strcmp(buffer, ".") != 0) if (cin) cout << "La chaine de caractères est : " << buffer << endl; } // --- On consomme tous les caractères laissés dans // --- la stream jusqu'à la fin de ligne. cin.ignore(100, '\n'); return 0; std::istream& ignore() Vice-rectorat à la recherche / octobre 2005

48 //par la méthode istream::ignore(100).
02/04/2017 Les entrées/sorties std::istream& ignore() Résultat: Entrez une chaîne [. pour quitter] : Jean-Luc La chaîne de caractères est : Jean-Luc Entrez une chaîne [. pour quitter] : Jean-Luc Boutin La chaîne de caractères est : Jean-Luc B Entrez une chaîne [. pour quitter] : //Les autres caractères ont été consommés //par la méthode istream::ignore(100). Vice-rectorat à la recherche / octobre 2005

49 Les entrées/sorties std::istream& getline()
02/04/2017 Les entrées/sorties std::istream& getline() permet de lire une ligne entière ou la dimension du buffer. istream& getline(char* strP, int dim, char c = '\n'); Permet donc de lire une ligne sans avoir à s'occuper de la fin de ligne. La fin de ligne est consommée par la méthode. Il faut disposer de suffisamment de mémoire pour lire la ligne : 256, 512 ou 1024 caractères ou plus selon les besoins. Vice-rectorat à la recherche / octobre 2005

50 Les entrées/sorties std::istream& getline() #include <iostream>
02/04/2017 Les entrées/sorties std::istream& getline() #include <iostream> using namespace std; int main() { char buffer[256]; cout << "Entrez le point [.] pour quitter : "; cin.getline(buffer, 255); while (cin && strcmp(buffer, ".") != 0) if (cin) cout << "La chaine de caractères est : " << buffer << endl; } return 0; Vice-rectorat à la recherche / octobre 2005

51 Les entrées/sorties std::istream& getline() Résultat:
02/04/2017 Les entrées/sorties std::istream& getline() Résultat: Entrez une chaîne [. pour quitter] : Voici une longue phrase sur une ligne... La chaîne de caractère est : Voici une autre longue phrase sur une ligne ... Vice-rectorat à la recherche / octobre 2005

52 Les entrées/sorties ostream::width()
02/04/2017 Les entrées/sorties ostream::width() Permet de spécifier la largeur du champ à afficher. Par défaut, l'alignement est à droite. L'application de la méthode width() ne tient que pour le prochain champ à afficher. Si on veut que cela s'applique à tous les prochains champs à afficher : appeler la méthode width() avant d'afficher chaque champ. Si la largeur du champ n'est pas suffisante pour afficher le champ, le C++ ne tient pas compte de la largeur la donnée est plus importante que sa présentation... Vice-rectorat à la recherche / octobre 2005

53 Les entrées/sorties ostream:: width() Exemples
02/04/2017 Les entrées/sorties ostream:: width() Exemples // --- Appel une seule fois avant d'afficher les champs cout.width(10); for (int i=0; i<3; i++) { cout << 123 << endl; } cout << endl; // --- Appel à chaque affichage d'un champ for (int j=0; j<3; j++) cout << 321 << endl; Résultat 123 321 Vice-rectorat à la recherche / octobre 2005

54 Les entrées/sorties ostream:: width() Exemples Résultat
02/04/2017 Les entrées/sorties ostream:: width() cout << " " << endl; cout.width(5); cout << 123; cout.width(7); cout << 543; cout.width(3); cout << 4; cout << 9876 << endl; // --- Il y aura décalage, à cause de la largeur du 1er champ. cout << ; Exemples Résultat [---][-----][-][---] Vice-rectorat à la recherche / octobre 2005

55 Les entrées/sorties ostream::precision()
02/04/2017 Les entrées/sorties ostream::precision() Permet de contrôler le nombre de chiffres significatifs visibles à l'affichage. Par défaut : 6 chiffres significatifs. On peut spécifier le nombre de chiffres significatifsdésirés. Un appel de precision() est valide jusqu'à ce que la précision soit changée. Vice-rectorat à la recherche / octobre 2005

56 Les entrées/sorties ostream::precision() int i; double valeurs[5];
02/04/2017 Les entrées/sorties int i; double valeurs[5]; valeurs[0] = ; for (i=1; i<5; i++) { valeurs[i] = valeurs[i-1] * 0.10; } cout << "Affichage avec la précision par défaut" << endl; for (i=0; i<5; i++) cout.width(10); cout << valeurs[i] << endl; cout << "Affichage avec précision(3)" << endl; cout.precision(3); ostream::precision() Résultat Affichage avec la précision par défaut 54.354 5.4354 Affichage avec précision(3) 54.4 5.44 0.544 0.0544 Vice-rectorat à la recherche / octobre 2005

57 Les entrées/sorties ostream::fill()
02/04/2017 Les entrées/sorties ostream::fill() Permet de spécifier le caractère de remplissage qui peut être ajouté dans les champs affichés. Par défaut : un espace. Pour changer temporairement le caractère de remplissage, fill() : retourne le caractère courant de remplissage prend en paramètre celui en remplacement : char ostream::fill(char fill) Si on conserve l'ancien caractère, on peut restaurer l'état de la stream après usage. Vice-rectorat à la recherche / octobre 2005

58 Les entrées/sorties ostream::fill() int i; double valeurs[5];
02/04/2017 Les entrées/sorties int i; double valeurs[5]; valeurs[0] = ; for (i=1; i<5; i++) { valeurs[i] = valeurs[i-1] * 0.10; } cout << "Remplissage de l'espace libre avec des *" << endl; char f = cout.fill('*'); for (i=0; i<5; i++) cout.width(10); cout << valeurs[i] << endl; cout << "Restauration du remplissage précédent" << endl; cout.fill(f); ostream::fill() Résultat: Remplissage de l'espace libre avec des * ******54.4 ******5.44 *****0.544 ****0.0544 *** Restauration du remplissage precedent 54.4 5.44 0.544 0.0544 Vice-rectorat à la recherche / octobre 2005

59 Les entrées/sorties ostream::setf() et ostream::unsetf()
02/04/2017 Les entrées/sorties ostream::setf() et ostream::unsetf() Objet de type ostream : maintient des états dans un entier où chaque bit représente quelque chose. On peut activer un état avec setf() ou le désactiver avec unsetf(). plusieurs états (format flags) Pouvant être contrôlés par ces deux méthodes. Exemple intéressant : comment conserver plusieurs renseignements dans un seul entier. Chaque bit de l'entier correspond à un état. En faisant un OR binaire sur l'entier, on arrive à activer ou désactiver le ou les états désirés. Vice-rectorat à la recherche / octobre 2005

60 Les entrées/sorties Quelques états intéressants ios::left :
02/04/2017 Les entrées/sorties Quelques états intéressants ios::left : alignement sur la gauche avec remplissage sur la droite. ios::right : alignement par défaut avec remplissage sur la gauche. ios::fixed : affichage des réels en format fixe. ios::scientific affichage des réels en format scientifique. ios::showpos affichage du signe positif Il existe d'autres états! Vice-rectorat à la recherche / octobre 2005

61 Les entrées/sorties Exemples
02/04/2017 Les entrées/sorties Exemples // Alignement à gauche, format scientifique, signe positif, // précision 8 chiffres après le point, champs de largeur 20 caractères. cout.setf(ios::left | ios::scientific | ios::showpos); cout.precision(8); cout.width(20); cout << << endl; cout << << endl; // --- Enlève le signe positif // --- Alignement à droite, format fixe, précision 8 chiffres total, // --- champs de largeur 20 caractères. cout.unsetf(ios::showpos); cout.setf(ios::right | ios::fixed); Résultat e+003 e+003 Vice-rectorat à la recherche / octobre 2005

62 02/04/2017 Les manipulateurs Un certain nombre de paramètres pour le format des sorties peuvent être explicitement spécifiés. Ces paramètres sont de deux formes: ➱ Soit des manipulateurs, appliqués à l’opérateur « << » ➱ Soit des options de configurations, appliqués directement au stream de sortie Manipulateurs Pour utiliser les manipulateurs, il faut au préalable importer les définitions du fichier iomanip au moyen de la directive d’inclusion: #include <iomanip> On utilise les manipulateurs très simplement, en les insérant directement dans le flot, à l’endroit désiré, exactement comme avec les données: cout << «donnée» << «manipulateur» << «donnée» << ... Vice-rectorat à la recherche / octobre 2005

63 Les sorties formatées Longueur de la représentation: setw(«taille»)
02/04/2017 Les sorties formatées Longueur de la représentation: setw(«taille») la donnée qui suit ce manipulateur est affiché sur (au moins) taille caractères, avec (par défaut) un cadrage à droite, fort pratique lors de la représentation en colonnes des nombres. cout << setw(10) << "un:" << setw(5) << 1 << endl; cout << setw(10) << "cent deux:" << setw(5) << 102 << endl; cout << setw(10) << "moins 18:" << setw(5) << -18 << endl; un: 1 cent deux: 102 moins 18: -18 Vice-rectorat à la recherche / octobre 2005

64 Les sorties formatées Caractère de remplissage: setfill(«char»)
02/04/2017 Les sorties formatées Caractère de remplissage: setfill(«char») définit le caractère utilisé pour pour réaliser le remplissage lors d’un alignement (par défaut le caractère espace): cout << setw(10) << "un:" << setfill(’.’) << setw(5)<< 1; cout << endl << setw(10) << "cent deux:" << setfill(’.’) << setw(5) << 102; cout << endl << setw(10) << "moins 18:" << setfill(’.’) << setw(5) << -18 un:….1 cent deux:..102 moins 18:..-18 Vice-rectorat à la recherche / octobre 2005

65 02/04/2017 Les sorties formatées Précision en virgule flottante: setprecision(int) définit le nombre de chiffres significatifs sur lequel se fera l’affichage des nombre en virgules flottantes (par défaut 6): for (int i(2); i<6; ++i) { cout << setprecision(i) << i << ’ ’ << << endl; } 2 3.1e+002 3 314 Vice-rectorat à la recherche / octobre 2005

66 02/04/2017 Les entrées/sorties Les appels sont réalisés de la droite vers la gauche. Les expressions que vous affichez sont présentées dans l'ordre que vous avez demandé mais elles ont été évaluées dans l'ordre inverse. De plus, setprecision(4) sera active pour les éventuelles impressions de réels. Comme avec les printf du C, il est donc possible de spécifier des formats d'affichage à la manière des fameux "%6.2f" dans le langage C. L'exemple suivant créé l'équivalent d'un printf("6.2f",r); #include <iostream> #include <iomanip> using namespace std; int main(int, char **) { double r= ; int i=5; cout << setw(6) << setprecision(4) << r << endl; cout << i << " " << i++ << endl; cout << i << endl; return 0; } 36.14 6 5 6 Vice-rectorat à la recherche / octobre 2005

67 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Le lien entre les fichiers du système d’exploitation et le programme se fait en C++ par le biais des streams. Un flot de données de type stream – orienté ou bidirectionnel – peut être associé à un fichier, et s’utilise de la même manière que les flots vers ou en provenance de la console (cin, cout, cerr). Vice-rectorat à la recherche / octobre 2005

68 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Pour pouvoir utiliser les streams liés aux fichiers, il faut importer, en début de programme, les prototypes et définitions contenus dans la librairie, au moyen de la directive d’inclusion: #include <fstream> Deux types (classes) sont alors disponibles: ➱ ifstream (input file stream) stream d’entrée associé à un fichier ouvert en mode lecture (similaire à cin) ➱ ofstream (output file stream) stream de sortie, associé à un fichier ouvert en mode écriture (similaire à cout). Vice-rectorat à la recherche / octobre 2005

69 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Le mécanisme général pour la mise en oeuvre d’entrée-sorties via les fichiers est: (1) Création d’un stream (d’entrée ou de sortie), par la déclaration d’une variable de type ifstream ou ofstream. Exemple ifstream entree; ofstream sortie; (2) Association de la variable avec un fichier physique, par l’appel de la fonction-méthode open, en respectant la syntaxe d’appel définie dans le paragraphe concernant les vecteurs. Exemple entree.open("input.txt"); qui associe le stream entree avec le fichier nommé «input.txt» (présent dans le répertoire courant). (3) Utilisation du stream: par des appels à des fonctions-méthodes, et l’utilisation des opérateurs d’insertion («>>») et d’extraction («<<») de données. (4) Fermeture du stream, au moyen de la fonction-méthode close Exemple entree.close(); Vice-rectorat à la recherche / octobre 2005

70 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Les opérations (1) et (2), à savoir la déclaration de la variable et son association avec un fichier, peuvent se réaliser en une seule étape. L’initialisation lors de la déclaration se fait alors en spécifiant entre parenthèses le nom du fichier à lier au stream: Exemple ifstream entree("input.txt"); On peut considérer que l’initialisation fait directement appel à la fonction open. La fonction open admet comme argument une chaîne de caractères de type "..." (en fait un char[]): il n’est donc pas possible d’utiliser directement une chaîne de type string (en effet, s’il y a conversion implicite des chaînes de la forme "..." vers les strings (promotion), l’inverse n’est pas vrai.) . Il faut dans ce cas demander la conversion en type char[] du string, en faisant appel à la fonction-méthode c_str: Exemple 1 string str("output.txt"); ifstream entree2; ofstream sortie(str.c_str()); entree2.open(str.c_str()); Vice-rectorat à la recherche / octobre 2005

71 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Exemple 2 ifstream de("fichier1"); // définition de la variable: de if (!de) { cerr<<"Impossible d'ouvrir fichier1 en lecture\n"; exit(1); } ofstream vers("fichier2"); // définition de la variable: vers if (!vers) cerr<<"Impossible d'ouvrir fichier2 en écriture\n"; char c; while(de.get(c)) //copie de fichier1 vers fichier2 vers<<c;; get(c) retourne faux si on est à la fin du fichier, sinon elle retourne vrai. Vice-rectorat à la recherche / octobre 2005

72 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte L’utilisation dans le programme des variables de type fstream pour effectuer des entrées-sorties se fait de la même manière que pour les streams cin et cout, c’est-à-dire à l’aide des opérateurs d’insertion «>>» et d’extraction «<<». ifstream entree("input.txt"); ofstream sortie("output.txt"); string mot; int n; entree >> mot >> n; sortie << "Le mot lu est: ’" << mot << "’ et le " << "nombre est: ’" << n << "’." << endl; Exemple Remarque. Une fonction utile pour tester si le lecture d’un fichier est Terminée est la fonction/méthode eof. if (entree.eof()) { cout << "Fin du fichier" << endl; } Vice-rectorat à la recherche / octobre 2005

73 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Le programme ci-dessous saisit une phrase via l’entrée standard (clavier), et l’écrit (un mot par ligne) dans un fichier texte nommé «phrase.txt». #include <iostream> #include <fstream> #include <string> int main() { string motSaisit; string nomFichier("phrase.txt"); ofstream sortie(nomFichier.c_str()); cout << "Entrez une phrase terminée par « .»" << endl; do cin >> motSaisit; sortie << endl << motSaisit; } while (motSaisit != "."); sortie.close(); return 0; } Vice-rectorat à la recherche / octobre 2005

74 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte Le programme ci-dessous relit le fichier créé par le programme précédant, et affiche la phrase à l’écran, et remettant les mots sur une même ligne. #include <iostream> #include <fstream> #include <string> int main() { string motSaisit; ifstream entree("phrase.txt"); while (!entree.eof()) entree >> motSaisit; cout << motSaisit << ’ ’; } cout << endl; entree.close(); return 0; Vice-rectorat à la recherche / octobre 2005

75 Entrée/sortie avec des fichiers texte
02/04/2017 Entrée/sortie avec des fichiers texte De même qu’il est conseillé de contrôler la conformité des valeurs entrées par un utilisateur, il est bon de vérifier que l’association d’un stream avec un fichier s’est correctement réalisée (i.e. que le fichier existe, est lisible, etc). Pour cela, on peut «évaluer le stream», après l’appel à la fonction open.Si tout c’est bien passé, le résultat de cette évaluation sera true, et il sera false en cas de problème. Exemple entree.open("fichier-inexistant"); if (!entree) cout << "Oops, le fichier n’est pas lisible!" << endl; else << cout << "Ok, le fichier existe et est lisible!" << endl; Plus précisément, un certain nombre de prédicats sont associés aux streams, et permettent d’en connaître l’état: bool good() le stream est dans un état correct, la prochaine opération (lecture/écriture) sera un succès. bool eof() la fin du stream à été atteinte. bool fail() la prochaine opération (lecture/écriture) échouera. Elle sert lors de l’«évaluation» d’un stream. bool bad() le stream est corrompu: des données ont été perdues (et la prochaine opération échouera). Vice-rectorat à la recherche / octobre 2005

76 02/04/2017 Strings et streams Il peut parfois être utile, en vue d’effectuer des traitements particuliers, de disposer d’une représentation sous forme de chaîne de caractères des différentes variables d’un programme. Une telle convertion de représentation est automatiquement réalisée lorsque l’on insère ces éléments dans un stream de sortie, tel que cout. Mais peut-on récupérer ce qui est transmis dans le flot ? À défaut de récupérer ce qui est effectivement transmis, on peut du moins en obtenir l’équivalent sous forme de string, en utilisant des strings hybrides, associés à des streams. Ces entités hybrides sont désignées « stringstream». Pour pouvoir utiliser les stringstream dans un programme, il faut importer les prototypes et définitions contenus dans la librairie, au moyen de la directive d’inclusion: #include <sstream> Vice-rectorat à la recherche / octobre 2005

77 Stringstream de sortie
02/04/2017 Stringstream de sortie Pour obtenir la représentation alphanumérique d’une variable, il faut utiliser un stringstream de sortie, dans lequel on insérera les données désirées (de la même manière qu’avec cout) avant d’en extraire l’équivalent sous forme de chaîne de caractère. Le type (la classe) matérialisant de tels éléments est désigné: ostringstream, et l’extraction de la représentation chaîne s’obtient au moyen de la méthode: string str(). #include <sstream> ... string composeMessage(const int errno, const string& description) { ostringstream ost; ost << "Erreur (n°" << errno << "): " << description; return ost.str(); } Exemple Vice-rectorat à la recherche / octobre 2005

78 Stringstream d’entrée
02/04/2017 Stringstream d’entrée Il est également possible de réaliser des entrées depuis un string (au lieu du clavier, avec cin): il suffit d’initialiser un stringstream d’entrée avec la chaîne désirée, et d’utiliser l’opérateur d’extraction sur le stream ainsi obtenu. Le type (la classe) utilisé est: istringstream. Exemple #include <sstream> ... // Extrait les mots d’un string, et les affiches à // raison de un par ligne void wordByWord(const string& str){ istringstream ist(str); string s; while (ist >> s) {cout << s << endl;} } // en utilisant la fonction précédante: wordByWord("Erreur (no5): Fichier non trouvé."); Erreur (n˚5): Fichier non trouvé. Vice-rectorat à la recherche / octobre 2005

79 Hiérarchie des classes représentant les flots
02/04/2017 Hiérarchie des classes représentant les flots Vice-rectorat à la recherche / octobre 2005


Télécharger ppt "Structures de données IFT-10541"

Présentations similaires


Annonces Google