Algorithmique et Programmation Cours 2024/2025 PDF
Document Details
Uploaded by GracefulCrocus6707
École Supérieure d'Éducation et de Formation d'El Jadida
Tags
Related
- Algorithmique et Programmation C (INPT) - 2024/2025 PDF
- Polycopié Algorithmique L1 PDF
- Algorithmique et Programmation en langage C PDF
- Module : Algorithmique & Programmation 2 - PDF
- Les Bases de Programmation en C - Université Sultan Moulay Slimane - PDF
- Cours de Programmation CFSS - Partie 1 & 2 PDF
Summary
Ce document est un cours d'algorithmique et de programmation, probablement en français. Il couvre les bases de la programmation, y compris des concepts comme le langage machine, l'assembleur et les langages évolués, ainsi que des sujets comme les structures de contrôle et les tableaux, et le langage C.
Full Transcript
Algorithmique et programmation Année universitaire 2024/2025 1 Plan du cours (1) 1. Introduction 2. Types, opérateurs et expressions 3. Les entrées-sorties (printf, scanf, …) 4. Les structures de contrôle 5. Les tableaux...
Algorithmique et programmation Année universitaire 2024/2025 1 Plan du cours (1) 1. Introduction 2. Types, opérateurs et expressions 3. Les entrées-sorties (printf, scanf, …) 4. Les structures de contrôle 5. Les tableaux 2 Plan du cours (2) 6. Les pointeurs 7. Les fonctions 8. Les chaînes de caractères 9. Les structures 3 Chapitre 1 Introduction 4 Langages informatiques ⚫ Un langage informatique est un outil permettant de donner des ordres (instructions) à la machine A chaque instruction correspond une action du processeur ⚫ Intérêt : écrire des programmes (suite consécutive d'instructions) déstinés à effectuer une tache donnée Exemple: un programme de gestion de comptes bancaires ⚫ Contrainte: être compréhensible par la machine 5 Langage machine ⚫ Langage binaire: l'information est exprimée et manipulée sous forme d'une suite de bits ⚫ Un bit (binary digit) = 0 ou 1 (2 états électriques) ⚫ Une combinaison de 8 bits= 1 Octet ➔ 28 =256 possibilités qui permettent de coder tous les caractères alphabétiques, numériques, et symboles tels que ?,*,&, … Le code ASCII (American Standard Code for Information Interchange) donne les correspondances entre les caractères alphanumériques et leurs représentation binaire, Ex. A= 01000001, ?=00111111 ⚫ Les opérations logiques et arithmétiques de base (addition, multiplication, … ) sont effectuées en binaire 6 L'assembleur ⚫ Problème: le langage machine est difficile à comprendre par l'humain ⚫ Idée: trouver un langage compréhensible par l'homme qui sera ensuite converti en langage machine Assembleur : exprimer les instructions élémentaires de façon symbolique ADD A, 4 LOAD B traducteur langage machine MOV A, OUT … +: déjà plus accessible que le langage machine -: dépend du type de la machine (n'est pas portable) -: pas assez efficace pour développer des applications complexes Apparition des langages évolués 7 Langages évolués ⚫ Intérêts multiples : proches du langage humain «anglais» (compréhensibles) permettent une plus grande portabilité (indépendants du matériel) Manipulation de données et d’expressions complexes (réels, objets, a*b/c, …) ⚫ Nécessitent un traducteur (compilateur/interpréteur) Code source Compilateur ou Langage machine en langage évolué interpréteur 8 Compilateur/interpréteur ⚫ Compilateur: traduire le programme entier une fois pour toutes Compilateur exécution exemple.c exemple fichier source fichier exécutable + plus rapide à l'exécution + sécurité du code source - il faut recompiler à chaque modification ⚫ Interpréteur: traduire au fur et à mesure les instructions du programme à chaque exécution Interprétation+exécution exemple.bas fichier source + exécution instantanée appréciable pour les débutants - exécution lente par rapport à la compilation 9 Langages de programmation: ⚫ Deux types de langages: Langages procéduraux Langages orientés objets ⚫ Exemples de langages: Fortran, Cobol, Pascal, C, … C++, Java, … 10 Historique du C ⚫ Le langage C a été conçu en 1972 dans «Bell Laboratories » par Dennis Ritchie avec l'objectif d'écrire un système d'exploitation (UNIX). ⚫ En 1978, une première définition rigoureuse du langage C (standard K&R-C) a été réalisée par Kernighan et Ritchie en publiant le livre «The C Programming Language ». ⚫ Le succès du C et l'apparition de compilateurs avec des extensions particulières ont conduit à sa normalisation. ⚫ En 1983, l'organisme ANSI (American National Standards Institute) chargeait une commission de mettre au point une définition explicite et portable pour le langage C. Le résultat est le standard ANSI-C. 11 Caractéristiques du C ⚫ Universel : n'est pas orienté vers un domaine d'application particulier (applications scientifiques, de gestion, …) ⚫ Près de la machine : offre des opérateurs qui sont proches de ceux du langage machine (manipulations de bits, d'adresses, …) ⚫ Modulaire: peut être découpé en modules qui peuvent être compilés séparément ⚫ Portable: en respectant le standard ANSI-C, il est possible d'utiliser le même programme sur plusieurs systèmes (hardware, système d'exploitation ) Remarque : Une programmation efficace et compréhensible en C n'est pas facilement accessible à des débutants 12 Programme source, objet et exécutable ⚫ Un programme écrit en langage C forme un texte qu'on nomme programme ou code source, qui peut être formé de plusieurs fichiers sources ⚫ Chaque fichier source est traduit par le compilateur pour obtenir un fichier ou module objet (formé d'instructions machine) ⚫ Ce fichier objet n'est pas exécutable tel quel car il lui manque les instructions exécutables des fonctions standards appelées dans le fichier source (printf, scanf, …) et éventuellement d'autres fichiers objets ⚫ L’éditeur de liens réunit les différents modules objets et les fonctions de la bibliothèque standard afin de former un programme exécutable ⚫ Remarque : la compilation est précédée par une phase de prétraitement (inclusion de fichiers en-tête) réalisé par le préprocesseur 13 Compilateurs C ⚫ Pour pouvoir écrire des programmes en C, vous avez besoin d'un compilateur C sur votre machine ⚫ Il existe plusieurs compilateurs respectant le standard ANSI-C. Une bonne liste est disponible sur : https://cpp.developpez.com/telecharger/index/categor ie/30/Outils-C-Cplusplus ⚫ Nous allons utiliser l'environnement de développement Code::Blocks avec le système d'exploitation Windows ⚫ Vous pouvez télécharger Code::Blocks librement, sur le site https://www.codeblocks.org 14 Exemple d’une fenêtre Code::Blocks 15 Composantes d’un programme C Directives du préprocesseur inclusion des fichiers d'en-tête (fichiers avec extension.h) définitions des constantes avec #define déclaration des variables globales définition des fonctions (En C, le programme principal et les sous- programmes sont définis comme fonctions ) Les commentaires : texte ignoré par le compilateur, destiné à améliorer la compréhension du code exemple : #include main() { printf( "notre premier programme C \n"); } 16 Remarques sur ce premier programme ⚫ #include informe le compilateur d'inclure le fichier stdio.h qui contient les fonctions d'entrées-sorties dont la fonction printf ⚫ La fonction main est la fonction principale des programmes en C: Elle se trouve obligatoirement dans tous les programmes. L'exécution d'un programme entraîne automatiquement l'appel de la fonction main. ⚫ L'appel de printf avec l'argument "notre premier programme C\n" permet d'afficher : notre premier programme C et \n ordonne le passage à la ligne suivante ⚫ En C, toute instruction simple est terminée par un point-virgule ; ⚫ Un commentaire en C est compris entre // et la fin de la ligne ou bien entre 17 Chapitre 2 Variables, types, opérateurs et expressions 18 Les variables ⚫ Les variables servent à stocker les valeurs des données utilisées pendant l'exécution d'un programme ⚫ Les variables doivent être déclarées avant d'être utilisées, elles doivent être caractérisées par : un nom (Identificateur) un type (entier, réel, …) (Les types de variables en C seront discutés par la suite) 19 Les identificateurs Le choix d'un identificateur (nom d’une variable ou d’une fonction) est soumis à quelques règles : ⚫ doit être constitué uniquement de lettres, de chiffres et du caractère souligné _ (Eviter les caractères de ponctuation et les espaces) correct: PRIX_HT, prixHT incorrect: PRIX-HT, prix HT, prix.HT ⚫ doit commencer par une lettre (y compris le caractère souligné) correct : A1, A1 incorrect: 1A ⚫ doit être différent des mots réservés du langage : auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while Remarque : C distingue les majuscules et les minuscules. NOMBRE et nombre sont des identificateurs différents 20 Les types de base ⚫ Le type d'une variable détermine l'ensemble des valeurs qu'elle peut prendre et le nombre d'octets à lui réserver en mémoire ⚫ En langage C, il n’y a que deux types de base les entiers et les réels avec différentes variantes pour chaque type Remarques: ⚫ Un type de base est un type pour lequel une variable peut prendre une seule valeur à un instant donné contrairement aux types agrégés ⚫ Le type caractère apparaît en C comme cas particulier du type entier (un caractère est un nombre entier, il s'identifie à son code ASCII) ⚫ En C il n'existe pas de type spécial pour chaînes de caractères. Les moyens de traiter les chaînes de caractères seront présentés aux chapitres suivants ⚫ Le type booléen n'existe pas. Un booléen est représenté par un entier (un entier non nul équivaut à vrai et la valeur zéro équivaut à faux) 21 Types Entier 4 variantes d'entiers : ⚫ char : caractères (entier sur 1 octet : - 128 à 127) ⚫ short ou short int : entier court (entier sur 2 octets : - 32768 à 32767) ⚫ int : entier standard (entier sur 2 ou 4 octets ) ⚫ long ou long int : entier long (4 octets : - 2147483648 à 2147483648) Si on ajoute le préfixe unsigned à la définition d'un type de variables entières, alors la plage des valeurs change: ⚫ unsigned char : 0 à 255 ⚫ unsigned short : 0 à 65535 ⚫ unsigned int : dépend du codage (sur 2 ou 4 octets) ⚫ unsigned long : 0 à 4294967295 Remarque : Une variable du type char peut subir les mêmes opérations que les variables du type short, int ou long 22 Types Réel 3 variantes de réels : ⚫ float : réel simple précision codé sur 4 octets de -3.4*1038 à 3.4*1038 ⚫ double : réel double précision codé sur 8 octets de -1.7*10308 à 1.7*10308 ⚫ long double : réel très grande précision codé sur 10 octets de -3.4*104932 à 3.4*104932 23 Déclaration des variables ⚫ Les déclarations introduisent les variables qui seront utilisées, fixent leur type et parfois aussi leur valeur de départ (initialisation) ⚫ Syntaxe de déclaration en C ,,...,; ⚫ Exemple: int i, j,k; float x, y ; double z=1.5; // déclaration et initialisation short compteur; char c=`A`; 24 Déclaration des constantes ⚫ Une constante conserve sa valeur pendant toute l'exécution d'un programme ⚫ En C, on associe une valeur à une constante en utilisant : la directive #define : #define nom_constante valeur Ici la constante ne possède pas de type. exemple: #define Pi 3.141592 le mot clé const : const type nom = expression ; Dans cette instruction la constante est typée exemple : const float Pi =3.141592 (Rq: L'intérêt des constantes est de donner un nom parlant à une valeur, par exemple NB_LIGNES, aussi ça facilite la modification du code) 25 Constantes entières On distingue 3 formes de constantes entières : ⚫ forme décimale : c'est l'écriture usuelle. Ex : 372, 200 ⚫ forme octale (base 8) : on commence par un 0 suivi de chiffres octaux. Ex : 0477 ⚫ forme hexadécimale (base 16) : on commence par 0x (ou 0X) suivis de chiffres hexadécimaux (0-9 a-f). Ex : 0x5a2b, 0Xa9f 26 Remarques sur les constantes entières ⚫ Le compilateur attribue automatiquement un type aux constantes entières. Il attribue en général le type le plus économique parmi (int, unsigned int, long int, unsigned long int) ⚫ On peut forcer la machine à utiliser un type de notre choix en ajoutant les suffixes suivants: u ou U pour unsigned int, Ex : 100U, 0xAu l ou L pour long, Ex : 15l, 0127L ul ou UL pour unsigned long, Ex : 1236UL, 035ul 27 Constantes réelles On distingue 2 notations : ⚫ notation décimale Ex : 123.4,.27, 5. ⚫ notation exponentielle Ex : 1234e-1 ou 1234E-1 Remarques : ⚫ Les constantes réelles sont par défaut de type double ⚫ On peut forcer la machine à utiliser un type de notre choix en ajoutant les suffixes suivants: f ou F pour le type float, Ex: 1.25f l ou L pour le type long double, EX: 1.0L 28 Les constantes caractères ⚫ Se sont des constantes qui désignent un seul caractère, elles sont toujours indiquées entre des apostrophes, Ex : ‘a’, ‘A’,’?’. ⚫ La valeur d'uneconstante caractère est le code ASCII du caractère ⚫ Les caractères constants peuvent apparaître dans des opérations arithmétiques ou logiques ⚫ Les constantes caractères sont de type int 29 Expressions et opérateurs ⚫ Une expression peut être une valeur, une variable ou une opération constituée par des valeurs, des constantes et des variables reliées entre eux par des opérateurs exemples: 1, b, a*2, a+ 3*b-c, … ⚫ Un opérateur est un symbole qui permet de manipuler une ou plusieurs variables pour produire un résultat. On distingue : les opérateurs binaires qui nécessitent deux opérandes (ex : a + b) les opérateurs unaires qui nécessitent un seul opérande ( ex: a++) l'opérateur conditionnel ?: , le seul qui nécessite trois opérandes ⚫ Une expression fournit une seule valeur, elle est évaluée en respectant des règles de priorité et d'associativité 30 Opérateurs en C ⚫ Le langage C est riche en opérateurs. Outre les opérateurs standards, il comporte des opérateurs originaux d'affectation, d'incrémentation et de manipulation de bits ⚫ On distingue les opérateurs suivants en C : les opérateurs arithmétiques : +, -, *, /, % les opérateurs d’affectation : =, +=, -=,*=,/=,… les opérateurs logiques : &&, ||, ! les opérateurs de comparaison : ==, !=, , = les opérateurs d’incrémentation et de décrémentation : ++, -- les opérateurs sur les bits : , &, |, ~, ^ d’autres opérateurs particuliers : ?:, sizeof, cast 31 Opérateurs arithmétiques ⚫ binaires : + - * / et % (modulo) et unaire : - ⚫ Les opérandes peuvent être des entiers ou des réels sauf pour % qui agit uniquement sur des entiers ⚫ Lorsque les types des deux opérandes sont différents il y'a conversion implicite dans le type le plus fort ⚫ L'opérateur / retourne un quotient entier si les deux opérandes sont des entiers (5 / 2 ➔ 2). Il retourne un quotient réel si l'un au moins des opérandes est un réel (5.0 / 2 ➔ 2.5) 32 Conversions implicites ⚫ Les types short et char sont systématiquement convertis en int indépendemment des autres opérandes ⚫ La conversion se fait en général selon une hiérarchie qui n'altère pas les valeurs int → long → float → double → long double ⚫ Exemple1 : n * x + p (int n,p; float x) exécution prioritaire de n * x : conversion de n en float exécution de l'addition : conversion de p en float ⚫ Exemple2 : p1 * p2 + p3 * x (char p1, short p2, p3 ; float x) p1, p2 et p3 d'abord convertis en int p3 converti en float avant multiplication 33 Exemple de conversion Exemple : n * p + x (int n ; long p ; float x) n * p + x long conversion de n en long * multiplication par p long n * p de type long float conversion de n * p en float + addition float résultat de type float 34 Opérateur d’affectation simple = ⚫ L'opérateur = affecte une valeur ou une expression à une variable Exemple: double x,y,z; x=2.5; y=0.7; z=x*y-3; ⚫ Le terme à gauche de l‟affectation est appelé lvalue (left value) ⚫ L'affectation est interprétée comme une expression. La valeur de l'expression est la valeur affectée ⚫ On peut enchainer des affectations, l'évaluation se fait de droite à gauche exemple : i = j = k= 5 (est équivalente à k = 5, j=k et ensuite i=j) ⚫ La valeur affectée est toujours convertie dans le type de la lvalue, même si ce type est plus faible (ex : conversion de float en int, avec perte d'information) 35 Opérateurs relationnels ⚫ Opérateurs < : inférieur à : supérieur à >= : supérieur ou égal à == : égal à != : différent de ⚫ Le résultat de la comparaison n'est pas une valeur booléenne, mais 0 si le résultat est faux et 1 si le résultat est vrai ⚫ Les expressions relationnelles peuvent donc intervenir dans des expressions arithmétiques ⚫ Exemple: a=2, b=7, c=4 b==3 ➔ 0 (faux) a!=b ➔ 1(vrai) 4*(a=b)➔ 4 36 Opérateurs logiques ⚫ && : ET logique || : OU logique ! : négation logique ⚫ && retourne vrai si les deux opérandes sont vrais (valent 1) et 0 sinon ⚫ || retourne vrai si l‟une des opérandes est vrai (vaut 1) et 0 sinon ⚫ Les valeurs numériques sont acceptées : toute valeur non nulle correspond à vraie et 0 correspond à faux Exemple : 5 && 11 ➔ 1 !13.7 ➔ 0 37 Évaluation de && et || ⚫ Le 2ème opérande est évalué uniquement en cas de nécessité a && b : b évalué uniquement si a vaut vrai (si a vaut faux, évaluation de b inutile car a && b vaut faux) a b : b évalué uniquement si a vaut faux (si a vaut vrai, évaluation de b inutile car a b vaut vrai) ⚫ Exemples if ((d != 0) && (n / d == 2)) : pas de division si d vaut 0 if ((n >=0) && (sqrt(n) < p)) : racine non calculée si n < 0 ⚫ L'intérêt est d'accélérer l'évaluation et d'éviter les traitements inappropriés 38 Incrémentation et décrémentation ⚫ Les opérateurs ++ et -- sont des opérateurs unaires permettant respectivement d'ajouter et de retrancher 1 au contenu de leur opérande ⚫ Cette opération est effectuée après ou avant l'évaluation de l'expression suivant que l'opérateur suit ou précède son opérande k = i++ (post-incrémentation) affecte d'abord la valeur de i à k et incrémente après (k = i++ ; k = i ; i = i+1 ; ) k = ++i (pré-incrémentation) incrémente d'abord et après affecte la valeur incrémentée à k (k = ++i ; i = i+1 ; k = i ; ) ⚫ Exemple : i = 5 ; n = ++i - 5 ; i vaut 6 et n vaut 1 i = 5 ; n = i++ - 5 ; i vaut 6 et n vaut 0 ⚫ Remarque : idem pour l‟opérateur de décrémentation -- 39 Opérateurs de manipulations de bits ⚫ opérateurs arithmétiques bit à bit : & : ET logique | : OU logique ^ : OU exclusif ~ : négation ⚫ Les opérandes sont de type entier. Les opérations s'effectuent bit à bit suivant la logique binaire b1 b2 ~b1 b1&b2 b1 | b2 b1^b2 1 1 0 1 1 0 1 0 0 0 1 1 0 1 1 0 1 1 0 0 1 0 0 0 ⚫ Ex : 14= 1110 , 9=1001➔ 14 & 9= 1000=8, 14 | 9 =1111=15 40 Opérateurs de décalage de bits ⚫ Il existe deux opérateurs de décalage : >> : décalage à droite >3 s'écrit: p>>=3 43 Opérateur de forçage de type (cast) ⚫ Il est possible d'effectuer des conversions explicites ou de forcer le type d'une expression Syntaxe : () Exemple : int n, p ; (double) (n / p); convertit l'entier n / p en double ⚫ Remarque : la conversion (ou casting) se fait après calcul (double) (n/p) (double) n / p (double) (n) / (double) (p) float n = 4.6, p = 1.5 ; (int) n / (int) p = 4 / 1 = 4 (int) n / p = 4 / 1.5 = 2.66 n / (int) p = 4.6 / 1 = 4.6 n / p = 4.6 / 1.5 = 3.06 44 Opérateur conditionnel ? : ⚫ Syntaxe: exp1 ? exp2 : exp3 exp1 est évaluée, si sa valeur est non nulle c'estexp2 qui est exécutée, sinon exp3 ⚫ Exemple1 : max = a > b ? a : b Si a>b alors on affecte à max le contenu de exp2 càd a sinon on lui affecte b ⚫ Exemple2 : a>b ? i++ : i--; Si a>b on incrémente i sinon on décrémente i 45 Opérateur séquentiel , ⚫ Utilité : regrouper plusieurs sous-expressions ou calculs en une seule expression ⚫ Les calculs sont évalués en séquence de gauche à droite ⚫ La valeur de l'expression est celle de la dernière sous-expression ⚫ Exemples i++ , i + j; // on évalue i++ ensuite i+j (on utilise la valeur de i incrémentée) i++ , j = i + k , a + b; // la valeur de l'expression est celle de a+b for (i=1 , k=0 ; … ; …) { } 46 Opérateur SIZEOF ⚫ Syntaxe : sizeof () ou sizeof () fournit la taille en octets d'un type ou d'une variable ⚫ Exemples int n; printf ("%d \n",sizeof(int)); // affiche 4 printf ("%d \n",sizeof(n)); // affiche 4 47 Priorité et associativité des opérateurs ⚫ Une expression est évaluée en respectant des règles de priorité et d'associativité des opérateurs Ex: * est plus prioritaire que +, ainsi 2 + 3 * 7 vaut 23 et non 35 ⚫ Le tableau de la page suivante donne la priorité de tous les opérateurs. La priorité est décroissante de haut en bas dans le tableau. ⚫ Les opérateurs dans une même ligne ont le même niveau de priorité. Dans ce cas on applique les règles d'associativité selon le sens de la flèche. Par exemple: 13%3*4 vaut 4 et non 1 ⚫ Remarque: en cas de doute il vaut mieux utiliser les parenthèses pour indiquer les opérations à effectuer en priorité. Ex: (2 + 3) * 7 vaut 35 48 Priorités de tous les opérateurs 49 Chapitre 3 Entrées-sorties 50 Les instructions de lecture et d’écriture ⚫ Il s'agit des instructions permettant à la machine de dialoguer avec l'utilisateur Dans un sens la lecture permet à l'utilisateur d'entrer des valeurs au clavier pour qu'elles soient utilisées par le programme Dans l'autre sens, l’écriture permet au programme de communiquer des valeurs à l'utilisateur en les affichant à l'écran (ou en les écrivant dans un fichier) ⚫ La bibliothèque standard contient un ensemble de fonctions qui assurent la lecture et l'écriture des données. Dans ce chapitre, nous allons en discuter les plus importantes: printf() écriture formatée de données scanf() lecture formatée de données 51 Ecriture formatée de données: printf () ⚫ la fonction printf est utilisée pour afficher à l'écrandu texte, des valeurs de variables ou des résultats d'expressions. ⚫ Syntaxe : printf("format", expr1, expr2, …); expr1,… : sont les variables et les expressions dont les valeurs sont à représenter Format : est une chaîne de caractères qui peut contenir du texte des séquences d'échappement ('\n', '\t', …) des spécificateurs de format : un ou deux caractères précédés du symbole %, indiquant le format d'affichage Rq : Le nombre de spécificateurs de format doit être égale au nombre d'expressions! 52 Spécificateurs de format SYMBOLE TYPE AFFICHAGE COMME %d ou %i int entier relatif %u unsinged int entier naturel non signé %c char caractère %o int entier sous forme octale %x ou %X int entier sous forme hexadécimale %f float, double réel en notation décimale %e ou %E float, double réel en notation exponentielle %s char* chaîne de caractères 53 Séquences d’échappement ⚫ l'affichage du texte peut être contrôlé à l'aide des séquences d'échappement : \n : nouvelle ligne \t : tabulation horizontale \a : signal sonore \b : retour arrière \r : retour chariot \v : tabulation verticale \f : saut de page \\ : back slash ( \ ) \’ : apostrophe \" : guillemet 54 Exemples de printf() #include main() { int i=1 , j=2, N=15; printf("la somme de %d et %d est %d \n", i, j, i+j); printf(" N= %x \n" , N); char c='A' ; printf(" le code Ascii de %c est %d \n", c, c); } Ce programme va afficher : la somme de 1 et 2 est 3 N=f le code Ascii de A est 65 Remarque : Pour pouvoir traiter correctement les arguments du type long, il faut utiliser les spécificateurs %ld, %li, %lu, %lo, %lx 55 Exemples de printf() #include main() { double x=10.5, y=2.5; printf("%f divisé par %f égal à %f \n", x, y, x/y); printf("%e divisé par %e égal à %e\n", x, y, x/y); } Ce programme va afficher : 10.500000 divisé par 2.500000 égal à 4.200000 1.050000e+001 divisé par 2.500000e+000 égal à 4.200000e+000 Remarque : Pour pouvoir traiter correctement les arguments du type long double, il faut utiliser les spécificateurs %lf et %le 56 Remarques sur l’affichage ⚫ Par défaut, les entiers sont affichés sans espaces avant ou après ⚫ Pour agir sur l'affichage ➔ un nombre est placé après % et précise le nombre de caractères minimum à utiliser ⚫ Exemples : printf("%4d" , n ); n = 20 ➔ ~~20 (~ : espace) n=56123 ➔ 56123 printf("%4X", 123); ➔ ~~7B printf("%4x", 123); ➔ ~~7b 57 Remarques sur l’affichage ⚫ Pour les réels, on peut préciser la largeur minimale de la valeur à afficher et le nombre de chiffres après le point décimal. ⚫ La précision par défaut est fixée à six décimales. Les positions décimales sont arrondies à la valeur la plus proche. ⚫ Exemples : printf("%f", 100.123); ➔ 100.123000 printf("%12f", 100.123); ➔ ~~100.123000 printf("%.2f", 100.123); ➔ 100.12 printf("%5.0f", 100.123); ➔ ~~100 printf("%10.3f", 100.123); ➔ ~~~100.123 printf("%.4f", 1.23456); ➔ 1.2345 58 Lecture formatée de données: scanf () ⚫ la fonction scanf permet de lire des données à partir du clavier ⚫ Syntaxe : scanf("format", AdrVar1, AdrVar2, …); Format : le format de lecture de données, est le même que pour printf adrVar1, adrVar2, … : adresses des variables auxquelles les données seront attribuées. L'adresse d‟unevariable est indiquée par le nom de la variable précédé du signe & 59 Exemples de scanf() #include main() { int i , j; scanf("%d%d", &i, &j); printf("i=%d et j=%d", i, j); } ce programme permet de lire deux entiers entrés au clavier et les afficher à l‟écran. Remarque : pour lire une donnée du type long, il faut utiliser les spécificateurs %ld, %li, %lu, %lo, %lx. 60 Exemples de scanf() #include main() { float x; double y; scanf("%f %lf", &x, &y); printf("x=%f et y=%f", x,y); } ce programme permet de lire un réel simple et un autre double du clavier et les afficher à l‟écran Remarque : pour lire une donnée du type double, il faut utiliser %le ou %lf et pour lire une donnée du type long double, il faut utiliser %Le ou %Lf 61 Chapitre 4 Structures de contrôle 62 Structures de contrôle ⚫ Les structures de contrôle définissent la façon avec laquelle les instructions sont effectuées. Elles conditionnent l'exécution d'instructions à la valeur d'une expression ⚫ On distingue : Les structures alternatives (tests) : permettent d'effectuer des choix càd de se comporter différemment suivant les circonstances (valeur d'une expression). En C, on dispose des instructions : if…else et switch. Les structures répétitives (boucles) : permettent de répéter plusieurs fois un ensemble donné d'instructions. Cette famille dispose des instructions : while, do…while et for. 63 L’instruction if…else ⚫ Syntaxe : If (expression) bloc-instruction1 else bloc-instruction2 bloc-instruction peut être une seule instruction terminée par un point- virgule ou une suite d'instructions délimitées par des accolades { } expression est évaluée, si elle est vraie (valeur différente de 0), alors bloc-instruction1 est exécuté. Si elle est fausse (valeur 0) alors bloc- instruction2 est exécuté ⚫ La partie else est facultative. S'il n'y a pas de traitement à réaliser quand la condition est fausse, on utilisera simplement la forme : If (expression) bloc-instruction1 64 if…else : exemples float a, b, max; if (a > b) max = a; else max = b; int a; if ((a%2)==0) printf(" %d est paire" ,a); else printf(" %d est impaire ",a); 65 Imbrication des instructions if ⚫ On peut imbriquer plusieurs instructions if…else ⚫ Ceci peut conduire à des confusions, par exemple : if (N>0) if (A>B) MAX=A; else MAX=B; (interprétation 1 : si N=0 alors MAX prend la valeur B) if (N>0) if (A>B) MAX=A; else MAX=B; (interprétation 2 : si N=0 MAX ne change pas) ⚫ En C un else est toujours associé au dernier if qui ne possède pas une partie else (c'est l'interprétation 2 qui est juste) 66 Imbrication des instructions if ⚫ Conseil : pour éviter toute ambiguïté ou pour forcer une certaine interprétation dans l'imbrication des if, il vaut mieux utiliser les accolades ⚫ if(a0) { if (A>B) MAX=A; } else MAX=B; 67 L’instruction d’aiguillage switch : ⚫ Permet de choisir des instructions à exécuter selon la valeur d'une expression qui doit être de type entier ⚫ la syntaxe est : switch (expression) { case expression_constante1 : instructions_1; break; case expression_constante2 : instructions_2; break; … case expression_constante n : instructions_n; break; default : instructions; } ⚫ expression_constantei doit être une expression constante entière ⚫ Instructions_i peut être une instruction simple ou composée ⚫ break et default sont optionnels et peuvent ne pas figurer 68 Fonctionnement de switch ⚫ expression est évaluée ⚫ si sa valeur est égale à une expression_constante i, on se branche à ce cas et on exécute les instructions_i qui lui correspondent On exécute aussi les instructions des cas suivants jusqu'à la fin du bloc ou jusqu'à une instruction break (qui fait sortir de la structureswitch) ⚫ si la valeur de l'expression n'est égale à aucune des expressions constantes Si default existe, alors on exécute les instructions qui le suivent Sinon aucune instruction n'est exécutée 69 Switch : exemple main( ) { char c; switch (c) { case 'r': printf("red\n"); break ; case 'g': printf("green\n"); break ; case 'b': printf("blue\n"); break ; case 'w': printf("white\n"); break ; case 'o': printf("orange\n"); break ; case 'y': printf("yellow\n"); break ; default : printf("black\n"); } } 70 Les boucles while et do.. while while (condition) do { { instructions instructions } } while (condition); ⚫ la condition (dite condition de contrôle de la boucle) est évaluée à chaque itération. Les instructions (corps de la boucle) sont exécutés tant que la condition est vraie, on sort de la boucle dès que la condition devient fausse ⚫ dans la boucle while le test de continuation s'effectue avant d'entamer le corps de boucle qui, de ce fait, peut ne jamais s'exécuter ⚫ par contre, dans la boucle do-while ce test est effectué après le corps de boucle, lequel sera alors exécuté au moins une fois 71 Boucle while : exemple Un programme qui détermine le premier nombre entier N tel que la somme de 1 à N dépasse strictement 100 main( ) { int i, som; i =0; som= 0; while (som 20); } 73 La boucle for for (expr1 ; expr2 ; expr3) { instructions } ⚫ L'expression expr1 est évaluée une seule fois au début de l'exécution de la boucle. Elle effectue l'initialisation des données de la boucle ⚫ L'expression expr2 est évaluée et testée avant chaque passage dans la boucle. Elle constitue le test de continuation de la boucle. ⚫ L'expression expr3 est évaluée après chaque passage. Elle est utilisée pour réinitialiser les données de la boucle 74 Boucle for : remarques for (expr1 ; expr2 ; expr3) équivaut à : { expr1; instructions while(expr2) } { instructions expr3; } ⚫ En pratique, expr1 et expr3 contiennent souvent plusieurs initialisations ou réinitialisations, séparées par des virgules 75 Boucle for : exemple Calcul de x à la puissance n où x est un réel non nul et n un entier positif ou nul main ( ) { float x, puiss; int n, i; printf (" Entrez respectivement les valeurs de x et n \n"); scanf ("%f %d" , &x, &n); for (puiss =1, i=1; i à 10 est égal à : %d", nbre); } 85 Tableaux à plusieurs dimensions On peut définir un tableau à n dimensions de la façon suivante: ⚫ Type Nom_du_Tableau[D1][D2]…[Dn]; où Di est le nombre d'éléments dans la dimension i ⚫ Exemple : pour stocker les notes de 20 étudiants en 5 modules dans deux examens, on peut déclarer un tableau : float notes; (notes[i][j][k] est la note de l'examen k dans le module j pour l'étudiant i) 86 Tableaux à deux dimensions (Matrices) ⚫ Syntaxe : Type nom_du_Tableau[nombre ligne][nombre colonne]; ⚫ Ex: short A; On peut représenter le tableau A de la manière suivante : A A A A A A ⚫ Un tableau à deux dimensions A[n][m] est à interpréter comme un tableau unidimensionnel de dimension n dont chaque composante A[i] est un tableau unidimensionnel de dimension m. ⚫ Un tableau à deux dimensions A[n][m] contient n* m composantes. Ainsi lors de la déclaration, on lui réserve un espace mémoire dont la taille (en octets) est égal à : n*m* taille du type 87 Initialisation à la déclaration d’une Matrice ⚫ L'initialisation lors de la déclaration se fait en indiquant la liste des valeurs respectives entre accolades ligne par ligne ⚫ Exemple : float A = {{-1.5, 2.1, 3.4, 0}, {8e-3, 7e-5,1, 2.7 }, {3.1, 0, 2.5E4, -1.3E2}}; A=-1.5 , A=2.1, A=3.4, A=0 A=8e-3 , A=7e-5, A=1, A=2.7 A=3.1 , A=0, A=2.5E4, A=-1.3E2 ⚫ On peut ne pas indiquer toutes les valeurs: Les composantes manquantes seront initialisées par zéro ⚫ Comme pour les tableaux unidimensionnels, Il est défendu d'indiquer trop de valeurs pour une matrice 88 Matrices : saisie et affichage ⚫ Saisie des éléments d'une matrice d'entiers A[n][m] : for(i=0;i pour accéder aux champs nom variable ->nom champ (ex: p2->age ) ⚫ Remarque : Il est possible d’utiliser un point même dans le cas d’un pointeur, par exemple (*p2).age (les parenthèses sont ici indispensables) 145 Accès aux champs d’une structure : Exemple Saisie et affichage d’une structure ⚫ Soit la structure article définie par : struct article { int numero; //un numéro qui identifie l’article char nom; int qte stock; // quantité disponible en stock float prix; }; ⚫ Soit la déclaration de variables : struct article art, *pt_art; Saisissez les champs de la structure art, puis affichez son contenu 146 Exemple de Saisie et d’affichage d’une structure printf ("Entrez respectivement les champs de l’article \n "); scanf(" %d %s %d %f" , &art.numero, art.nom, &art.qte stock,&art.prix); printf (" Cet article a pour : \n "); printf (" \t numéro : %d \n ", art.numero); printf (" \t nom : %s \n ", art.nom); printf (" \t quantité en stock : %d \n ", art.qtestock); printf (" \t prix : %f \n ", art.prix); Refaites la saisie et l’affichage en utilisant le pointeur pt_art 147 Exemple de Saisie et d’affichage via un pointeur Remarque : il faut d’abord initialiser le pointeur pt_art printf ("Entrez respectivement les champs de l’article \n "); scanf(" %d %s %d %f" , &pt_art->numero, pt_art->nom, & pt_art->qte_stock, & pt_art->prix); printf (" Cet article a pour : \n "); printf (" \t numéro : %d \n ", pt_art->numero); printf (" \t nom : %s \n ", pt_art->nom); printf (" \t quantité en stock : %d \n ", pt_art.->qte_ stock); printf (" \t prix : %f \n ", pt_art->prix); 148 Composition des structures ⚫ Les structures peuvent être composées de champs de n’importequel type connu: types de base, pointeur, tableau ou structure. ⚫ Exemple de structure comportant un tableau et une structure : struct Etudiant { int code; char Nom; struct date date naissance; float notes; // notes de l’étudiant dans 8 modules } E1,E2; ⚫ on peut écrire E1.date naissance.annee pour accéder au champ annee de E1.date_naissance qui est de type date ⚫ E2.notes représente la note du module 4 de l’étudiant E2 149 Manipulation des structures ⚫ Les structures sont manipulées en général champ par champ. Toutefois, la norme ANSI permet d’affecter une structure à uneautre structure de même type, par exemple : struct Etudiant E1,E2; E2=E1; est une instruction valide qui recopie tous les champs de E1 dans les champs de E2 ⚫ Rq: Il n’est pas possible de comparer deux structures. Les instructions if(E1==E2) ou if(E1!=E2) ne sont pas permises ⚫ L’opérateur & permet de récupérer l’adresse d’une variable structure (ex : struct Personne p1, *p2; p2=&p1) ⚫ L’opérateur sizeof permet de récupérer la taille d’un type structure ou d’une variable structure (ex : sizeof (struct Personne) ou sizeof (p1) ) 150 Structures et fonctions Une structure peut être utilisée comme argument d’une fonction et transmise par valeur (ou par adresse via un pointeur) Exemple de transmission par valeur Exemple de transmission par adresse struct couple { struct couple { int a; int a; float b;}; float b;}; void zero (struct couple s) void zero (struct couple *s) { s.a=0; s.b=0; { s->a=0; s->b=0; printf(" %d %f \n ", s.a, s.b); printf(" %d %f \n ", s->a, s->b); } } main() main() { struct couple x; x.a=1;x.b=2.3; { struct couple x; printf("avant: %d %f \n ", x.a, x.b); x.a=1;x.b=2.3; zero(x); printf("avant: %d %f \n ", x.a, x.b); printf("après: %d %f \n ", x.a, x.b); zero(&x); } printf("après: %d %f \n ", x.a, x.b); } 151 Structures et fonctions (2) Une structure peut être retournée par l’instruction return d’une fonction Exemple struct couple { int a; main() float b;}; { struct couple x,y; struct couple oppose(struct couple s) x.a=1;x.b=2.3; {struct couple z; printf("x: %d %f \n ",x.a,x.b); z.a=-s.a; z.b=-s.b; y=oppose(x); return z; printf("y: %d %f \n ",y.a,y.b); } } 152 Structures et fonctions : exercice Pour la structure article suivante : ⚫ Ecrivez une fonction, nommée SaisieArticle, qui saisit les champs d’une variable struct article article passé en paramètre { ⚫ Ecrivez une fonction, nommée AfficheArticle, qui affiche le contenu des champs d’une int numero; variable article passé en paramètre char nom; int qte_stock; ⚫ Ecrivez une fonction nommée SaisieTabArticle, qui remplit un tableau T de n float prix; articles. T et n sont des paramètres de la fonction. }; ⚫ Ecrivez une fonction AfficheTabStock, qui affiche les articles de T ayant une quantité en stock >= à une valeur q. T, n et q sont des paramètres de la fonction ⚫ Ecrivez un programme qui fait appel aux fonctions SaisieTabArticle et AfficheTabStock 153 Structures et fonctions : exercice (2) struct article void AfficheArticle (struct article art) {int numero; {printf (" Cet article a pour : \n "); char nom; printf (" \t numéro : %d \n ", art.numero); int qte_stock; printf (" \t nom : %s \n ", art.nom); float prix; printf (" \t stock : %d \n ", art. qte_stock); }; printf (" \t prix : %f \n ", art.prix); } void SaisieArticle (struct article * art) {printf (" numero ? \n"); void SaisieTabArticle(struct articleT[ ], int n) scanf (" %d",&art->numero); {int i; printf (" nom ? \n "); for(i=0;inom); {printf (" saisie de l’article %d \n " ,i+1); printf (" quantité en stock ? \n ") ; SaisieArticle (&T[i]); scanf (" %d" , &art->qte_stock); } printf (" prix ?\n "); } scanf (" %f" ,&art->prix); } 154 Structures et fonctions : exercice (3) void AfficheTabStock(struct article T, int n, int q) { int i; printf (" Les articles ayant un stock >=%d sont : \n " ,q); for(i=0;i=q) AfficheArticle(T[i]); } main( ) { struct articleT; SaisieTabArticle(T, 10); AfficheTabStock(T, 10, 2); } 155 Définition de types synonymes: typedef ⚫ En C, on peut définir des types nouveaux synonymes de types existants (simples, pointeur, tableau, structure,…) en utilisant le mot clé typedef. Ces nouveaux types peuvent être utilisées ensuite comme les types prédéfinis ⚫ Exemple d’un type synonyme d’un type simple : typedef int entier; définit un nouveau type appelé entier synonyme du type prédéfini int entier i=4,T ; le type entier est utilisé ici pour déclarer des variables Remarque : l’intérêt de typedef pour les types de base est limité puisqu’il remplace simplement un nom par un autre ⚫ Exemple d’un type synonyme d’un type pointeur : typedef int * ptr_ entier; ptr entier p1,p2; p1 et p2 sont des pointeurs sur des int typedef char* chaine; chaine ch; 156 Exemples de typedef ⚫ Type synonyme d’un type tableau : typedef float tableau; tableau T; T est un tableau de 10 réels typedef int matrice; matrice A; A est une matrice d’entiers de 4 lignes et 5 colonnes ⚫ Type synonyme d’un type structure : typedef struct { int jour; int mois; int annee; } date; - date est le nom du nouveau type et non d’une variable - On peut utiliser directement ce type, par exemple: date d, *p; - Ceci permet simplement d’éviter l’emploi du mot clé struct dans les déclarations de variables 157 Structures récursives ⚫ Une structure est dite récursive si elle contient des pointeurs vers elle même, par exemple : struct Individu struct noeud { char *Nom; { int val; int Age; struct noeud *suivant; struct Individu *Pere, *Mere; }; }; ⚫ Ce genre de structures est fondamental en programmation car il permet d'implémenter la plupart des structures de données employées en informatique (seront étudiées en cours de Structures de données) 158