Deust Maintenance Aéronautique

Slides:



Advertisements
Présentations similaires
Premier programme en C :
Advertisements

La boucle for : init7.c et init71.c
Les fonctions A quoi ça sert ?
Algorithmique Résume.
C.
Tests et itérations Programmes séquentiels ne résolvent pas tous les problèmes exemple simple : calcul des racines d'un polynôme de d° 2 dans R Algorithme.
Structures et unions types énumérés Qu'est-ce qu'une structure
Tableaux Certains problèmes nécessitent beaucoup de variables du même type. Exemple : relevé de températures matin et soir dans 10 villes pour 10 jours.
Chap. 1 Structures séquentielles : listes linéaires
FLSI602 Génie Informatique et Réseaux
5. Les structures répétitives
8. Les tableaux P. Costamagna – ISEN N1.
Introduction à la programmation (420-PK2-SL) cours 15 Gestion des applications Technologie de linformation (LEA.BW)
Les bases de l’Algorithmique
Principes de programmation (suite)
Langage C Révision.
Structures de données linéaires
Partie 1 Etude de l'existant
Récursivité.
Points importants de la semaine Les boucles. Les types arithmétiques. Les opérateurs.
Algorithmique et Programmation
Algorithmique et structure de données
Les éléments de base de l’algorithmique
RESUMES Module II1 SOMMAIRE CYCLE 1 : Saisir – Afficher – Données
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Test et débogage Tests unitaires. Gestion d’erreurs. Notion d’état, de pré-condition et de post-condition. Assertion. Traces de programme. Débogueur et.
Les Fonctions. Définir une fonction Sections de code indépendantes que lon peut appeler à nimporte quel moment et dans nimporte quel ordre. Bout de code.
Chapitre XI Gestion des erreurs et exceptions. 2 La gestion des erreurs et exceptions De nombreux problèmes peuvent survenir pendant lexécution dun programme:
IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
Procédures et fonctions
Les Opérateurs Ils régissent toutes les opérations ou transformations sur les valeurs des variables. Opérateur d'affectation Opérateurs arithmétiques Opérateurs.
Plan cours La notion de pointeur et d’adresse mémoire.
Animateur : Med HAIJOUBI
Les adresses des fonctions
SIF-1053 Architecture des ordinateurs
Un survol du language C.
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
Introduction au langage C Fonctions et Procédures
Sémantique des instructions pour le langage Z minimal Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI)
B.Shishedjiev - Affectation1 Expressions et affectation Comment produire des nouvelles valeurs.
Les variables fichiers. Le type fichier On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; –Nom physique.
Introduction au langage C Les entrées-sorties
Introduction au langage C : Structures de contrôle 1 ère année Génie Informatique Dr Daouda Traoré Université de Ségou
1. Spoon Christophe Delagarde, septembre 1998 I.U.T., Université de la Méditerrainée 2.
Conception de Programmes - IUT de Paris - 1ère année Quelques éléments du langage C++ Les références La surcharge de fonctions Les fonctions «
Programmation en C.
Module algorithmique et programmation
8PRO107 Éléments de programmation Les adresses et les pointeurs.
8PRO107 Éléments de programmation Les tableaux. Étude de cas 1 Description du problème : Lire une liste d’entiers et l’afficher d’abord dans le même ordre.
Scripts et fonctions Instructions de contrôle
PRO-1027 Programmation Scientifique en C
Chapitre 4 La représentation des nombres.
Algorithmique Tableaux de données
Philippe Gandy - 8 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Objets et Actions Élémentaires.
Philippe Gandy - 15 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Philippe Gandy – 10 novembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Algorithmique Boucles et Itérations
Introduction au langage C
Algorithmique et programmation
Introduction à l’Informatique chap 3 Licence SPI Mme Delmotte.
C++ BY AURÉLIEN MODULO MARION. PLAN DES TROIS PRÉSENTATIONS C++ avancé C++ orienté objet Bases de C++
1 Tableur Excel. 2 Introduction Un tableur est un logiciel permettant de manipuler des données numériques et d'effectuer automatiquement des calculs sur.
ALGORITHME ET PROGRAMMATION RÉVISION Informatique et Sciences du Numérique.
Informatique 1A Langage C 6 ème séance 1. Objectifs de la séance 6  Allocation dynamique de mémoire  Application à la création de tableaux 2.
M. BENJELLOUN : 2005 Le but final est de programmer un jeu où l'ordinateur choisira un nombre aléatoire entre 0 et 100 que vous devez deviner.
Transcription de la présentation:

Deust Maintenance Aéronautique 2009-2010 Langage C 1ère année : IN21 - Informatique 2ème année : II41 – Informatique industrielle Par Christophe MONTAGNE

Plan du cours 1ère année 2ème année Généralités Règles d’écriture Variables Affectation Opérations mathématiques Lecture / Ecriture Tests Boucles Tableaux Fonctions 2ème année Compléments 1ère année Expressions Allocation de mémoire Lecture / écriture de fichier Pointeurs Structures Projet multi-fichiers Algorithmes utiles C++ : Classes

Glossaire et symboles Incrémenter : augmenter de 1 un entier Décrémenter : diminuer de 1 un entier Mot-clé : mot faisant partie de la syntaxe du C (automatiquement mis en gras dans les éditeurs) Indentation : décalage du code ; termine une instruction , est un séparateur { } délimite des blocs d’instructions ( ) délimite des expressions / encadre les arguments de fonction

1ère année

L’ordinateur Ecran Carte mère Processeur Mémoire vive (RAM) Cartes (graphique, son, réseau, …) Alimentation Lecteur/graveur CD/DVD Disque Dur Souris Clavier Unité Centrale ; Périphériques

Définition et architecture (1) « Un ordinateur est un machine servant à traiter des données. » Périphériques d’entrées Périphériques de sorties BUS Processeur Mémoire

Définition et architecture (2) Le processeur : traite les données en exécutant un programme. La mémoire : stocke les données et les programmes. Les périphériques d’entrée : permettent d’acquérir des données de l’extérieur (ex : clavier, souris). Les périphériques de sortie : permettent de restituer des données à l’extérieure (ex : écran, imprimante). Les bus : sont le média de communication.

Les logiciels Un logiciel est un programme qui permet à un ordinateur d’assurer une tâche ou une fonction en particulier : Jeux Bureautique (traitement de texte, tableur, calculatrice…) Multimédia (vidéo, musique…) Navigateurs Internet … Un logiciel peut contenir de très nombreuses instructions (jusqu’à plusieurs millions).

L’OS Les Systèmes d’Exploitation (ou Operating System) sont une catégorie particulière de logiciel. Programme central de l’ordinateur Responsable de la liaison entre les ressources matérielles d’un ordinateur et les applications informatiques de l’utilisateur (traitement de texte, jeu vidéo…) Exemples : Windows, Linux

Du problème à la solution Cahier des charges Analyse Algorithme(s) Programmation Bibliothèques de fonctions Programme(s) Code fonction i … Code fonction j Compilation Code objet / machine Programme exécutable (logiciel) Édition de liens

L’algorithmique L’algorithmique permet de : Réfléchir au problème posé Proposer une solution : Compréhensible par un non-informaticien Sans contraintes de syntaxe Structurée et concise Éviter les erreurs de raisonnement* La programmation consiste à écrire un algorithme dans le langage de programmation de son choix (Basic, C, C++, Java, …). * : En programmation, les deux erreurs principales sont l’erreur de « raisonnement » et l’erreur de syntaxe.

Ecrire un programme Un programme C se constitue : D’une fonction principale De plusieurs fonctions secondaires Une fonction est une suite d’instructions qui manipulent des variables contenant différents types de données. Les instructions sont exécutés séquentiellement (les unes après les autres) mais certaines sont répétables.

Les commentaires (1) Un commentaire est une portion du programme qui n’est pas exécutée. On l’utilise pour : Insérer des informations générales : nom du programmeur date de la dernière modification présentation de la tâche accomplie par le programme … Insérer des explications sur une instruction ou un bloc d’instructions : Quelle est sa fonction ? Pourquoi en a-t-on besoin ? Neutraliser une instruction ou un bloc d’instructions (phases de déboguage ou de test)

Les commentaires (2) Syntaxe sur plusieurs lignes : /* */ /* 1 - voici un commentaire sur plusieurs lignes */ Syntaxe en fin de ligne : // // 2 - commentaire isolée sur une ligne return 0; // 3 - commentaire en fin de ligne Très utile pour les autres programmeurs relisant votre code ou pour vous-même.

L’indentation L’indentation est un décalage vers la droite du code (via une tabulation). On l’utilise pour rendre le code plus clair et plus lisible. On l’utilise : dans les fonctions, dans les tests, dans les boucles. Après une accolade ouvrante { : indentation / décalage vers la droite Accolade fermante } : fin de l’indentation / décalage vers la gauche

type nom_de_la_variable ; Les variables Une variable sert à stocker une information (donnée sous la forme d’une valeur). Une variable est définie par : Son nom qui permet l’accès à la donnée stockée Son type qui décide du type de donnée à stocker Syntaxe de la déclaration d’une variable : type nom_de_la_variable ;

Les nombres entiers int Les variables En résumé, il existe 3 types de données de base : Les nombres entiers int ex : -2, -1, 0, 1, 2 Les nombres réels float ex : 3.1415 Les caractères char ex : ‘A’, ‘b’, ‘0’, ‘é’, ‘!’

Les variables Choix du nom : Un nom de variable commence par une lettre. Un nom de variable peut se composer : de chiffres (09) de lettres minuscules (az) de lettres majuscules (AZ) du symbole ‘_’ Les lettres accentuées, les espaces et les symboles divers sont interdits. On privilégie les noms significatifs : pi au lieu de p Exemples : pi, nombre_d_habitants, TauxTVA, A, R2D2, b Rq : ce sont les mêmes règles pour les noms des fonctions.

Les variables Déclaration de plusieurs variables de même type : type nom_de_la_variable_1, nom_de_la_variable_2 ; Déclaration et affectation d’une valeur : type nom_de_la_variable = valeur ; Exemples : int g ; // déclaration simple float PrixHT, TauxTVA, PrixTTC ; // déclaration multiple float pi = 3.141593 ; // déclaration et initialisation La virgule est un séparateur.

Les valeurs Un nombre réel s’écrit avec un point et non avec une virgule (écriture anglo-saxonne). On écrit les caractères entre apostrophes : ' ' Il existe des caractères spéciaux : \n : fin de ligne (newline) \t : tabulation horizontale \\ : blackslah \? : point d’interrogation \' : apostrophe \" : guillemet On déclare une variable g qui peut contenir n’importe quel nombre entier et trois variables qui peuvent contenir n’importe quel nombre réel.

Mathématique vs C (1) En mathématique : La variable est une inconnue recouvrant plusieurs valeurs. y = 3 x + 2  les variables x et y répondant à cette équation sont une infinité ax2 + bx + c = 0  la variable x répondant à cette équation a 0, 1 ou 2 valeurs En C : La variable est connue et a une et une seule valeur à un moment donné.

nom_de_variable = valeur ; L’affectation L’affectation consiste à donner une valeur (à droite) à une variable (à gauche). L’opérateur d’affectation s’écrit : = Syntaxes : nom_de_variable = valeur ; Plusieurs possibilités existent : Affectation d’une valeur : pi = 3.1415 ; c = 'A' ; Affectation de la valeur d’une autre variable : a = b ; Affectation de la valeur d’une expression : a = b + 2 ; a = a + 1 ; Affectation de la valeur retournée par une fonction : c = carre(2) ;

L’affectation La valeur affectée doit être du même type que la variable. Risque : une perte de données. Exemples : int i ; i = 423.97 ; // Valeur affectée en pratique : 423 float j ; j = 32 ; // Valeur affectée en pratique : 32.0 C’est pour ça que les guillemets sont utilisés pour délimiter une chaîne et les apostrophes pour délimiter un caractère.

Mathématique vs C (2) En mathématique : Le symbole = indique l’égalité entre 2 termes. En C : Le symbole = sert à affecter une valeur à une variable. Exemple 1 : Soit A = B et B = A : En mathématique, les deux propositions sont équivalentes. En C, ce n’est pas le cas car ça revient à affecter la valeur de B à A et à affecter la valeur de A à B : ce sont deux choses bien différentes. Exemple 2 : Soit A = A + 1 : En mathématique, c’est une équation sans solution. En C, c’est une opération courante consistant à incrémenter la variable. Rq : En C, l’égalité entre 2 termes nécessite d’utiliser l’opérateur de comparaison d’égalité == .

Lecture séquentielle En C, l’ensemble des instructions forme une séquence lue / exécutée de manière séquentielle, c’est-à-dire qu’une instruction est traitée après l’autre.  L’ordre d’écriture des instructions est donc primordiale ! Exemple 1 : int A ; A = 34 ; A = 12 ; Exemple 2 : Valeur de A à la fin de cette séquence : 12 34 On notera également que dans ces deux exemples, l’écriture de la première affectation est inutile.

[terme_1] [opérateur] [terme_2] Opérateurs Un opérateur est un signe (symbole) qui relie deux valeurs pour produire un résultat : opération mathématique, opération logique, comparaison … Syntaxe usuelle* : [terme_1] [opérateur] [terme_2] Les types des valeurs liées par un opérateur doivent être identiques. * : il existe des exceptions

Opérations mathématiques Opérateurs numériques ou mathématiques : Addition : + Soustraction : – Multiplication : * Division : / Reste de la division entière : % (modulo) Priorités classiques : 3 + 5 * 10 donne 53 Rôle des parenthèses classique : 3 + ( 5 * 10 ) donne 53 mais ( 3 + 5 ) * 10 donne 80

Opérations mathématiques Règle : Si toutes les valeurs et/ou variables d’une opération sont de type entier alors le résultat est de type entier et doit être affecté (stocké) dans une variable de type entier. Dans le cas de la division « entière » : int x ; x = 17 / 5 ; // x vaut 3 x = 4 / 5 ; // x vaut 0 Règle : même chose avec le type réel. Dans le cas de la division « réelle » : float x ; x = 17.0 / 5.0 ; // x vaut 3.4 x = 4.0 / 5.0 ; // x vaut 0.8

Opérations mathématiques Pourquoi ne pas utiliser uniquement le type float ? Pour économiser la mémoire : une variable de type float est plus gourmande qu’une variable de type int.

La conversion de type (cast) C’est une conversion de type ponctuel. Syntaxe : (type) valeur Exemple d’utilisation : Soit les variables : int nb_gateau ; // nombre de gâteaux int nb_enfant ; // nombre d’enfants float parts ; // portions à manger On veut calculer le nombre de parts en divisant le nombre de gâteaux par le nombre d’enfants. Solution : parts = (float) nb_gateau / (float) nb_enfant ; Or, si les variables nécessaires à l’opération sont logiquement déclarées comme des entiers (0.6 enfant ou 0.7 gâteau n’étant pas imaginable), le nombre de parts peut être un réel (1 gâteau ou 3 gâteaux pour 2 enfants).

Opérations mathématiques Modulo % : Puisque le résultat d’une division entre deux entiers est un entier, il existe une cinquième opération mathématique qui permet de calculer le reste d’une telle division  le modulo est une opération entre deux entiers uniquement. int quotient, reste ; quotient = 17 / 5 ; reste = 17 % 5 ; Numérateur ou dividende Dénominateur ou diviseur 17 5 Variable Valeur quotient 3 reste 2 2 3 Reste Quotient

Opérateurs ++ et -- Incrémentation (++) et décrémentation (--) Forme préfixée (++i , --i) : la variable i est incrémentée/décrémentée avant que sa valeur ne soit estimée. Ex : n = 5; x = ++n; // x vaut 6 Forme postfixée (i++ , i--) : la variable i est incrémentée/décrémenté après que sa valeur ne soit estimée. Ex : n = 5; x = n++; // x vaut 5 Formes équivalentes : i++;  i=i+1;  i+=1; i--;  i=i-1;  i-=1;

Ecriture des résultats Lecture / Ecriture Lecture des consignes Consignes Utilisateur Programme Ecriture des résultats Résultats

scanf ( " %d " , &nb_gateau ) ; Lecture / Ecriture Lecture des données fournies par l’utilisateur : scanf ( ) Données saisies au clavier Nécessite de déclarer le fichier d’en-tête : stdio.h Exemple : saisie d’un entier scanf ( " %d " , &nb_gateau ) ; séparateur fin de l’instruction lettre qui dépend du type de donnée à saisir : - d pour les entiers - f pour les réels - c pour les caractères symbole % obligatoire nom de la variable qui va stocker la donnée saisie symbole & obligatoire " %d " & nb_gateau délimiteurs obligatoires

Lecture / Ecriture Saisie d’un réel : scanf( " %f " , &tauxTVA ) ; Saisie d’un caractère : scanf( " %c " , &reponseQCM ) ; Saisie de plusieurs données de même types : scanf ( " %d %d " , &nb_gateau , &nb_enfant ) ; Saisie de plusieurs données de types différents : scanf ( " %d %f " , &nb_produit , &prixTTC ) ; Dès que le programme rencontre une instruction comportant un scanf(), l’exécution s’interrompt et attend la frappe d’une valeur au clavier.

Lecture / Ecriture Ecriture de résultats du programme ou d’autres informations : printf ( ) Affichage à l’écran Nécessite de déclarer le fichier d’en-tête : stdio.h Exemple : affichage d’un réel printf ( " %f " , PrixTTC ) ; séparateur fin de l’instruction lettre qui dépend du type de donnée à afficher : - d pour les entiers - f pour les réels - c pour les caractères symbole % obligatoire nom de la variable dont on veut afficher la valeur " %f " PrixTTC délimiteurs obligatoires

Lecture / Ecriture On a souvent besoin d’afficher des « libellés » sous la forme de textes qui informent l’utilisateur de ce que fait ou veut le programme : on utilise printf pour faire cela. Exemple : printf ( " Entrez votre age : " ) ; scanf (" %d ", &age ); Pour afficher plusieurs libellés ou valeurs de variables en une seule instruction : Ex : printf( " Votre age est : %s \n " , age ); printf( " Vous pesez %f et mesurez %f " , poids , taille );

La fonction principale La fonction principale (et les instructions qu’elle contient) s’exécute toujours en premier. Syntaxe : int main (int argc, char *argv[ ]) { /* on écrit le programme ici */ return 0; } Autre syntaxe : int main (void) { … }

Les tests Définition Au lieu de lire séquentiellement les instructions du début jusqu’à la fin, le test conditionnel offre une alternative (on pourra parler de structure alternative), un choix entre plusieurs jeux d’instructions en fonction de une ou plusieurs conditions. 2 mots-clés : if et else

Les tests Syntaxes : if ( condition1 ) { [liste d’instructions 1] } else if ( condition2 ) [liste d’instructions 2] … else [liste d’instructions n] Syntaxes : if ( condition ) { [liste d’instructions] } if ( condition ) { [liste d’instructions 1] } else [liste d’instructions 2]

Les tests Si la condition est vérifiée (valeur différente de 0), le programme exécute la liste d’instructions qui suit. Si la condition n’est pas vérifiée (valeur de l’expression nulle) : Structure en if … : on sort du test Structure en if … else … : on exécute la seconde liste d’instructions Structure en if … else if … : on teste la nouvelle condition La condition s’exprime le plus souvent sous la forme d’une expression utilisant : des opérateurs de comparaison des opérateurs logiques

Les tests Opérateurs de comparaison Opérateurs logiques Egalité : == Différence : != Supérieur : > Supérieur ou égal : >= Inférieur : < Inférieur ou égal : <= Opérateurs logiques ET : && OU : || Négation : ! (ou opérateur unaire)

Les tests Exemple : int main (int argc, char *argv[]) { float note_orale, note_ecrite, moyenne ; printf ("Entrez la note de l’oral : ") ; scanf ("%f",&note_orale) ; printf ("Entrez la note de l’écrit : ") ; scanf ("%f",&note_ecrite) ; moyenne = ( 2.0 * note_ecrite + note_orale ) / 3.0 ; if ( moyenne >= 10.0 ) printf ("Reçu !") ; } else printf ("Recalé !") ; return 0 ; Est-ce que la valeur de la variable moyenne est supérieure ou égale à 10 ?

Les tests Une comparaison se fait toujours entre deux termes. Si on souhaite savoir si la valeur d’une variable est comprise entre deux valeurs min et max : On n’écrira pas : if ( 5 < x < 8 ) …  On écrira : if ( (5<x) && (x<8) ) …  Un tel test implique 2 conditions reliées par l’opérateur logique && (ET). On parle alors de condition composée. Plus généralement, dès que plusieurs conditions sont nécessaires pour exécuter une liste d’instructions, on lie ces conditions par les opérateurs logiques ET et OU.

if ((5<x)&&(x<8)) if ((5<x)||(x<8)) Les tests Dans une condition composée, toutes les règles de la logique booléenne sont valables, notamment les tables de vérité : Attention aux cas particuliers : Conditions toujours fausses : if ( (x<10) && (x>15) ) … Conditions toujours vraies : if ( 10 < 15 ) … 5 < x x < 8 if ((5<x)&&(x<8)) FAUX VRAI 5 < x x < 8 if ((5<x)||(x<8)) FAUX VRAI 5 < x if ( !(5<x) ) FAUX VRAI

Les tests 3 tests successifs (perte de temps possible) Soit : int Temp; printf("Entrez la température de l’eau :"); scanf("%d",&Temp); if ( Temp <= 0 ) { printf("C’est de la glace !"); } if ( (Temp > 0) && (Temp < 100) ) printf("C’est du liquide !"); if ( (Temp >= 100) ) printf("C’est de la vapeur !"); 3 tests successifs (perte de temps possible) 3 conditions similaires dont 1 composée

Les tests 2 tests imbriqués (gain de temps possible) On peut réécrire le code précédent en imbriquant les tests : int Temp ; printf("Entrez la température de l’eau :"); scanf("%d",&Temp); if ( Temp <= 0 ) { printf("C’est de la glace !"); } else if ( Temp < 100 ) printf("C’est du liquide !"); printf("C’est de la vapeur !"); 2 tests imbriqués (gain de temps possible) 2 conditions simples

Les tests On peut également utiliser else if : int Temp; printf("Entrez la température de l’eau :"); scanf("%d",&Temp); if ( Temp <= 0 ) { printf("C’est de la glace !"); } else if ( Temp < 100 ) printf("C’est du liquide !"); else printf("C’est de la vapeur !");

Les boucles

Les boucles Également appelées structures répétitives, ou structures itératives, les boucles permettent de répéter l’exécution d’une instruction ou d’un bloc d’instructions sans avoir à les réécrire. 3 types de boucles existent : « Pour » (for) « Tant que » (while) « Faire tant que » (do while)

Les boucles Syntaxe et exemple de la boucle for : for ( expr1 ; expr2 ; expr3 ) { … } for ( cpt = 1 ; cpt<=500 ; cpt ++ ) { printf("Je ne dois pas lancer d’avion en papier en classe.\n"); } expr1 : initialisation de la boucle expr2 : comparaison déterminant l’arrêt de la boucle (condition) expr3 : évolution du compteur (ici un incrémentation simple) Traduction : Pour un compteur allant de 1 à 500 (par pas de +1), écrire le message.

Les boucles Syntaxe et exemple de la boucle while : while ( condition ) { … } char choix ; printf("Voulez vous un café ? (O/N)") ; scanf("%c",&choix) ; while ( (choix != 'O') && (choix != 'N') ) { printf("Réponse non valide ; recommencez :"); } condition : condition nécessaire à la répétition (tant que la condition est vraie, on répète les instructions) Traduction : Tant que le choix de l’utilisateur est différent de ‘O’ et différent de ‘N’, refaire sa saisie.

Les boucles Il est obligatoire que les variables utilisées dans la condition de la boucle « tant que » aient une valeur initiale. Sinon le test ne peut pas se faire. char choix ; printf("Voulez vous un café ? (O/N)") ; scanf("%c",&choix) ; while ( (choix != 'O') && (choix != 'N') ) { printf("Réponse non valide ; recommencez :"); }

Les boucles Remarque : pour éviter d’écrire 2 fois l’instruction de saisie de la variable choix, on peut lui affecter arbitrairement une valeur permettant à la condition d’être vraie (ici n’importe quelle lettre autre que ‘O’ ou ‘N’ ). char choix = 'C' ; while ( (choix != 'O') && (choix != 'N') ) { printf("Voulez vous un café ? (O/N)") ; scanf("%c",&choix) ; } Ce changement de stratégie pour l’initialisation de la variable choix a entraîné une modification du jeu d’instructions.

Les boucles Syntaxe et exemple de la boucle do while : Variante de la boucle while permettant d’exécuter au moins une fois les instructions de la boucle avant de tester la condition. printf("Voulez vous un café ? (O/N)") ; do { scanf("%c",&choix) ; } while ( (choix != 'O') && (choix != 'N') ) ; Traduction : Faire la saisie du choix de l’utilisateur tant que son choix est différent de ‘O’ et différent de ‘N’.

Les boucles char choix='X' ; while ( (choix!='O') && (choix!= 'N') ) { scanf("%c",&Rep) ; } scanf("%c",&choix) ; while ( (choix!='O') && (choix!= 'N') ) { } do { scanf("%c",&choix) ; } while ( (choix!='O') && (choix!= 'N') ); On peut ne pas exécuter la boucle. On exécute au moins une fois la boucle.

Les boucles Les deux erreurs à ne pas faire : Une condition toujours fausse qui empêche d’entrer dans la boucle : la boucle ne sert donc jamais ! choix = 'O'; while ( ( choix != 'O' ) && ( choix != 'N' ) ) { … } Une condition toujours vraie qui empêche de sortir de la boucle : on a une boucle infinie. { … choix = 'X'; }

Les tableaux Utilité des tableaux : Exemple 1 : une variable pour chaque information utile float N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11,N12,m; printf("Entrez 12 valeurs :"); scanf("%f%f%f%f%f%f%f%f%f%f%f%f ",&N1,&N2,&N3,&N4,&N5,&N6,&N7,&N8,&N9,&N10,&N11,&N12); m = (N1+N2+N3+N4+N5+N6+N7+N8+N9+N10+N11+N12)/12.0; Exemple 2 : on ne conserve aucune information utile int i; float val, m=0.0; for(i=0;i<12;i++) { scanf("%f ",&val); m = m + val; } m = m / 12.0;

Les tableaux Il faut une solution qui : ne nécessite pas autant de variables que de valeurs à saisir ; permette de stocker toutes les valeurs saisies. Cette solution est le tableau de valeurs : une seule variable pouvant contenir plusieurs valeurs ; chaque valeur est accessible via un indice de position. Exemple : int i; float val[12],m=0.0; printf("Entrez les 12 valeurs :"); for(i=0;i<12;i++) { scanf("%f ",&val[i]); m = m + val[i]; } m = m / 12.0;

Les tableaux Définitions : Un ensemble de valeurs portant le même nom de variable et repérées par un indice, s’appelle un tableau, ou encore une variable indicée. La déclaration d’un tableau est similaire à celle d’une variable avec la taille précisée entre crochets en plus (à répéter autant de fois que de dimensions). En dehors de la déclaration du tableau, le nombre entier qui sert à repérer chaque valeur s’appelle l’indice. Chaque fois que l’on doit désigner un élément du tableau, on fait figurer le nom du tableau, suivi de l’indice de l’élément entre crochets.

type nom_du_tableau [taille1] ( [taille2] … ) ; Les tableaux Déclaration : type nom_du_tableau [taille1] ( [taille2] … ) ; Ex1 : float note[12]; // tableau de 12 notes Ex2 : int matrice[3][4]; // tableau de 3 lignes et 4 colonnes Ex3 : int image[256][256][3]; /* image de 256 lignes, 256 colonnes et 3 niveaux de couleurs */ Un tableau peut être de n’importe quel type : tableau d’entiers, de réels, de caractères… Attention : En C, on accède au premier élément d’un tableau par l’indice 0 et au dernier par l’indice taille-1 : note[0], note[1], … , note[11].

Les tableaux Un tableau est facile à manipuler grâce aux boucles. int main () { float note[12] ; float moyenne, somme ; int i ; for (i=0;i<12;i++) printf("Entrez la note no%d", i+1) ; scanf("%f", &note[ i ] ) ; } somme = 0.0 ; somme = somme + note[ i ] ; moyenne = somme / 12.0 ; printf("La moyenne est : %f ", moyenne) ; return 0;

Les tableaux Erreurs à ne pas faire : Utiliser un mauvais indice. Avec float note[12], les seuls indices valables sont : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 et 11 (tous positifs ou nul, entiers, et inférieurs à la taille du tableau). Confondre l’indice d’un élément d’un tableau et la valeur de cet élément : note[3] ne vaut pas forcément 3.

Les fonctions prédéfinies En C, divers traitements courants dont le développeur peut avoir besoin sont prédéfinies. Les avoir à disposition évite de devoir les reprogrammer systématiquement. Ces traitements font l’objet de fonctions déclarées dans des fichiers d’en-tête. Tout programme faisant appel à ces fonctions doit débuter par la déclaration des fichiers d’en-tête. Exemple : #include<stdio.h>  printf(), scanf() Plus de détails dans des livres ou sur des sites internet. Exemple : http://www.cplusplus.com/reference/clibrary/

Les fonctions prédéfinies Quelques fonctions de math.h Attention aux types des arguments d’entrée et des valeurs retournées. cos(), sin(), tan(), acos(), asin(), atan() : fonctions trigonométriques (en radians) exp(), log(), log10() : fonctions exponentielles et logarithmiques floor(), ceil() : arrondi à l’entier inférieur, supérieur fabs() : valeur absolue pow(x,y) : renvoie x à la puissance y sqrt() : racine carrée …

Les fonctions Certains traitements propres à l’application développée peuvent également faire l’objet d’une écriture sous forme de fonction. C’est le cas pour : Des traitements régulièrement utilisés Des traitements que l’on souhaite distinguer de la fonction principale ( confort d’écriture et lisibilité du programme) Terminologie : dans la littérature, on parle de fonction quand il y a renvoi de donnée et de procédure autrement.

parenthèses obligatoires même si pas d’arguments Les fonctions parenthèses obligatoires même si pas d’arguments Syntaxe : type nom_de_la_fonction ( [liste des arguments] ) { … } facultatif : type et nom des arguments d’entrée, séparés par des virgules doit respecter les mêmes règles d’écriture que les noms de variable type de la valeur retournée par la fonction ou void (pas de valeur retournée)

Les fonctions Exemples : Fonction calculant la distance euclidienne entre 2 points : float euclide ( float x1, float y1, float x2, float y2 ) { return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) ); } Fonction retournant une réponse universelle : int f ( ) return 42;

Les fonctions Si la fonction renvoie une valeur, sa dernière instruction est de la forme : return expression ; La liste des arguments d’entrée sert également de déclaration de variable : int fct ( int p ) { int p; … double déclaration  erreur !

Les fonctions Exemples d’appel de fonction : res = euclide(a,b,c,d); printf("%d" , f() ); res2 = f() + 3 + euclide(0,0,1,1); Le passage d’arguments est automatique : … res = euclide(a,b,c,d); // dans main() float euclide (float x1, float y1, float x2, float y2) { … } La valeur de a est passée dans x1, …

Fonctions récursives Programmation récursive : le programme qui se rappelait lui-même ! long fact (int N) { if ( N == 0 ) { return 1; } else { return fact(N-1) * N; } }

Structure d’un programme en C [déclaration des fichiers d’en-tête] [déclaration des constantes symboliques] [déclaration des prototypes des fonctions secondaires] int main (int argc, char *argv[ ]) { [déclaration des variables] [séquence d’instructions] return 0; } [écriture des fonctions secondaires]

Ecrire un programme en C Exemple : #include<stdio.h> int main (int argc, char *argv[ ]) { int n; printf("Entrez une valeur non nulle : "); scanf("%d",&n); printf("L’inverse de %d est %f.",n,1/(float)n); return 0; } déclaration du fichier d’en-tête permettant d’utiliser printf() et scanf() début de la fonction « principale » déclaration d’une variable n en entier message à l’utilisateur (s’affiche à l’écran) saisie de la valeur entrée au clavier et stockage dans n fin de la fonction « principale » message affichant les valeurs de n et de 1/n

Liens utiles Site sur l’algorithmique : http://www.pise.info/algo/codage.htm Un cours de langage C : http://gsc11.cemif.univ-evry.fr/~otmane/Poly_UEL_RAN_Informatique.pdf Site sur différents algorithmes de tri : http://www.dailly.info/algorithmes-de-tri/index.php Un peu d’histoire : http://histoire.info.online.fr/ Matériel : le site http://rueducommerce.fr propose régulièrement plusieurs guides mis à jour dans sa rubrique « Actus » : disque dur, carte mère, PC, mémoire, carte graphique, …

2ème année

Lecture séquentielle Programmation structurée (langages modernes) Programmation non structurée (basic) … Si condition Alors instructions 1 Sinon instructions 2 FinSi 1000 Si condition Alors Aller En 1200 1100 instruction 1 1110 etc. 1120 etc. 1190 Aller en 1400 1200 instruction 2 1210 etc. 1220 etc. 1400 suite de l’algorithme

Types Quatre types de base existent : Autres types : char : caractère (1 octet) issue du jeu de caractères de la machine utilisée (ex : table ascii) int : nombre entier (16 ou 32 bits*) float : nombre réel (à virgule flottante) simple précision double : nombre réel (à virgule flottante) double précision Autres types : long int ou long : entier « étendu » (32 bits*) short int ou short : entier « court » (16 bits*) long double : nombre à virgule flottante en précision étendue signed char [ou tout type entier] : type signé unsigned char [ou tout type entier] : type non signé (0) * : en fonction de la machine (une seule règle : long  int  short)

Types : plage de valeurs Min Max signed char -127 +127 unsigned char +255 short -32767 +32767 unsigned short +65535 long -2147483647 +2147483647 unsigned long +4294967295 float « 1E-37 » « 1E+37 »

Caractères spéciaux Aussi appelés séquences d’échappement (utilisable soit en tant que caractère soit dans une chaîne de caractères) : \a : caractère d’alerte \b : retour en arrière (backspace) \f : saut de page (formfeed) \n : fin de ligne (newline) \r : retour chariot (carriage return) \t : tabulation horizontale \v : tabulation verticale \\ : blackslah \? : point d’interrogation \' : apostrophe \" : guillemet \ooo : nombre octal (ooo est une suite de 1 à 3 chiffres octaux) \xhh : nombre hexadécimal (hh est une suite de 1 à 2 chiffres hexadécimal) \0 : caractère nul (sert en fin de chaîne)

Valeurs : notion de constante Les constantes sont les valeurs manipulées ; elles sont typées. 1234 : int …l ou …l : long 0… : entier octal 0x… ou 0X… : entier hexadécimale …u ou …U : unsigned …ul ou … UL : unsigned long 123.4 ou 1e-2 : double ‘X’ : char (la valeur d’une constante de type caractère est égale à la valeur du caractère d’après le jeu de caractères de la machine) "Je suis une chaîne" : constante de type chaîne ou tableau de caractères (les guillemets ne font pas partie de la chaîne) "" : chaîne vide Attention : "X"  'X'

Expressions constantes Expression constante ou constante symbolique : expression ne comportant que des constantes expression pouvant être évalué à la compilation par convention, on utilise des majuscules se déclare après les fichiers d’en-tête syntaxe et exemples : #define MAXLIGNE 1000 #define BIS 1

Constante énumérée C’est une liste de valeurs entières constantes. Le premier nom de la liste vaut 0, le suivant 1, … sauf si des valeurs explicites sont précisées. Syntaxe : enum nom{terme1[=valeur],terme2[=valeur][…]}; Exemples : enum logique { NON, OUI }; // NON vaut 0 et OUI vaut 1 enum echaps { SONNERIE = '\a', ARRIERE = '\b', TAB = '\t', LIGNE = '\n', TABV = '\v', RETOUR = '\a' }; enum mois { JAN = 1, FEV, MAR, AVR, MAI, JUN, JUL, AOU, SEP, OCT, NOV, DEC };

Expressions Une expression est un « ensemble de valeurs, reliées par des opérateurs, et équivalent à une seule valeur ». Les opérateurs pouvant apparaître dans une expression sont variés : numériques (arithmétiques), de comparaison, logiques… Une expression peut contenir des parenthèses. Exemples : 5 + 4 123 - 45 + 844 a - 12 + 5 + b Pour la 4ème expression : uniquement si Toto et Riri sont des nombres entiers. Voir également le transparent 12 (avec notamment une belle exception).

Expressions Chaque expression a une valeur : 5 + 4 vaut 9 123 - 45 + 844 vaut 922 a - 12 + 5 + b vaut … une valeur dépendant des valeurs des variables a et b. Quand on affecte une expression à une variable, la valeur stockée dans la variable sera donc celle de l’expression : A = 123 - 45 + 844 1. On calcule la valeur de l’expression (922). 2. On affecte cette valeur à la variable A. On trouve des expressions dans les affectations, les tests, les passages de fonctions, les boucles…

Variables globales Variables publiques/globales et privées/locales : Une variable locale n’a d’existence qu’au sein de la fonction où elle est déclarée : dès qu’on sort de la fonction, la variable n’existe plus. Une variable globale a une existence permanente : dès qu’elle est déclarée, elle est accessible dans toute fonction. Une variable est globale si elle est déclarée hors de toute fonction. La syntaxe ne change pas : seule l’endroit de la déclaration détermine si une variable est locale (dedans) ou globale (dehors).

Opérations mathématiques Les opérations entre entiers et réels sont tolérées. La valeur résultat sera toujours de type réel. Attention au type de la variable stockant le résultat : x = 3 * 4.2 ; si x est de type float, 12.6 est stockée mais si x est de type int, 12 est stockée Attention à la priorité des opérations : x = 2 / 3 + 5.0 ; la division est prioritaire ; 2/3 vaut 0 ; on a donc 0+5.0 qui vaut 5.0

Opérateurs bit à bit Opérateurs de traitement des bits & : ET bit à bit | : OU inclusif bit à bit ^ : OU exclusif bit à bit << : décalage à gauche >> : décalage à droite ~ : complément à un (opérateur unaire) Utilisables uniquement avec des opérandes entiers.

if (a>b) { z=a; } else { z=b;} Opérateur ternaire L’expression conditionnelle (opérateur ternaire ? : ) : Syntaxe : expr1 ? expr2 : expr3 ; Permet de remplacer une instruction de test (si test avec une instruction d’affectation). Exemple : if (a>b) { z=a; } else { z=b;}  z = ( a > b ) ? a : b ;

Opérateurs d’affectation Ils simplifient l’écriture d’une opération mathématique (ou bit à bit) quand l’un des deux termes de l’opération est une variable qui va servir à stocker le résultat. += -= /= *= %= <<= >>= &= ^= |= Syntaxe : terme1 [opérateur]= terme2 ; Equivalent à : terme1 = terme1 [opérateur] terme2 Exemples : i = i + 2 ;  i += 2 ; x *= y + 1 ;  x = x * (y+1) ; (et non x = x * y +1 ;)

int printf ( char * format, arg1, arg2, …) Lecture / Ecriture Prototype : int printf ( char * format, arg1, arg2, …) printf convertit, met en forme et imprime ses arguments sur la sortie standard sous le contrôle de format. format peut contenir : Des caractères ordinaires qui sont copiés tels quels sur le flot de sortie. Des spécifications de conversion, dont chacune provoque la conversion et l’impression de l’un des arguments suivants.

Lecture / Ecriture Conversions pour printf : d, i : entier décimal o : entier octal non signé (non précédé de 0) u : entier non signé décimal X, x : entier hexadécimal non signé (non précédé de 0x ou 0X), en utilisant abcdef ou ABCDEF pour 10, …, 15 c : caractère s : chaîne de caractères f : nombre à virgule flottante e, E : nombre à virgule flottante (spécial) g, G : nombre à virgule flottante (spécial) p : pointeur % : le caractère %

int scanf ( char * format, arg1, arg2, …) Lecture / Ecriture Prototype : int scanf ( char * format, arg1, arg2, …) scanf lit des caractères et les interprète selon les spécifications incluses dans format et stocke les résultats dans les arguments suivants. Les arguments sont tous des pointeurs et précisent l’endroit où sont stockées les entrées converties. format peut contenir : Des espaces et tabulations qui sont ignorées. Des caractères ordinaires (sauf %) dont chacun est supposé s’identifier au caractère suivant du flot d’entrée. Des spécifications de conversion composées d’un % et d’un caractère de conversion.

Lecture / Ecriture Conversions pour scanf : d : entier décimal i : entier décimal, octal (si précédé de 0), hexadécimal (si précédé de 0x ou 0X) o : entier octal (précédé ou non de 0) u : entier non signé décimal x : entier hexadécimal (précédé ou non de 0x ou 0X) c : caractère s : chaîne de caractères e, f, g : nombre à virgule flottante % : le caractère %

Lecture / Ecriture Remarque : int jour, annee; char nommois[20]; scanf("%d %s %d", &jour, nommois, &annee); Pas de & car un nom de tableau est un pointeur

La fonction principale Syntaxes tolérées : main( ) { } OU main(void) { } int main( ) { } OU int main(void) { } void main( ) { } OU void main(void) { } * * : exception faite de ces 2 syntaxes, la fonction main se finit toujours par une instruction « return x ; ».

Les tests Dans le cas d’une comparaison entre caractères, le programme compare l’ordre alphabétique des caractères dans la table ASCII. Pour comparer deux chaînes, on doit passer par la fonction strcmp ( ) (fichier d’en-tête : string.h ) qui retourne 0 si les deux chaînes sont identiques. Ex : if ( strcmp(s1,s2)==0 ) …

Les tests Les opérateurs de comparaison sont moins prioritaires que les opérateurs mathématiques. Ainsi : i<lim-1 aura la même valeur que i<(lim-1). Toute comparaison ou expression logique vaut 1 si elle est vérifiée et 0 si elle est fausse. La négation ! donne 0 si son opérande est non nul et 1 s’il est nul. Les expressions reliées par des opérateurs logiques sont évalués de gauche à droite ; l’évaluation s’interrompt si la fausseté du résultat est établie. Rq : (!correct) est équivalent à (correct==0).

Utile si des conditions composées très complexes Les tests Utilisation de variables intermédiaires : int Temp, A, B ; printf("Entrez la température de l’eau :") ; scanf("%d",&Temp) ; A = ( Temp <= 0 ) ; B = ( Temp < 100 ); if ( A ) { printf("C’est de la glace") ; } else if ( B ) printf("C’est du liquide") ; else printf("C’est de la vapeur") ; Utile si des conditions composées très complexes

Les tests Rôle des parenthèses : { int A, B, C, D, E ; int X ; scanf("%d",&X) ; A = X > 12 ; B = X > 2 ; C = X < 6 ; D = (A && B) || C ; E = A && (B || C) ; printf("%d,%d", D, E) ; } Dans une condition composée employant à la fois des opérateurs ET et OU, la présence de parenthèses possède une influence sur le résultat, tout comme dans le cas d’une expression numérique comportant des multiplications et additions. Si X vaut 3 : D sera VRAI E sera FAUX

Les tests ET ou OU ? Si il fait trop chaud ET il ne pleut pas Alors Ouvrir la fenêtre Sinon Fermer la fenêtre Finsi Si il ne fait pas trop chaud OU il pleut Alors Toute structure de test requérant une condition composée faisant intervenir l’opérateur ET peut être exprimée de manière équivalente avec un opérateur OU, et réciproquement.

Les tests  ET ou OU ? (suite) Cette équivalence suit la règle suivante : En fait, c’est la règle de «  De Morgan » : if ( A && B ) { [Instructions 1] } else { [Instructions 2] }  if ( !A || !B )

Les tests Au final, quand on fait un test, il faut choisir entre alléger la structure (imbriquée ou non), alléger les conditions (composées ou non) et alléger le nombre de variables booléennes. if ( Condition1 && Condition2 ) { [Instructions 1] } else { [Instructions 2] } if ( Condition1 ) if ( Condition2 ) A = Condition1; B = Condition2; if ( A && B ) Condition complexe Structure lourde 2 variables en plus

L’interrupteur (ou switch) L’interrupteur est une prise de décision à choix multiples qui regarde si la valeur d’une expression fait partie d’une liste connue de « valeurs constantes entières », et effectue les traitements associés à la valeur correspondante. Syntaxe : switch (expression) { case expression-constante : instructions default : }

L’interrupteur (ou switch) Le cas par défaut (default) permet d’exécuter des instructions si aucun autre cas n’est utilisé. Il est facultatif et il peut donc ne rien se passer lors de l’emploi de l’interrupteur). Les case sont des « étiquettes » (on peut y accéder directement). Une fois un cas traité, il convient de quitter explicitement le switch soit par un break, soit par un return … sinon on poursuit sur les cas suivants. L’expression doit avoir une valeur entière ! Un interrupteur peut toujours être réécrit sous la forme d’un test (if).

L’interrupteur (ou switch) Exemple : int note; printf("Entrez une note :"); scanf("%d",&note); switch(note) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: printf("Recalé"); break; case 10: case 11: printf("Passable"); break; case 12: case 13: printf("Assez bien"); break; case 14: case 15: printf("Bien"); break; case 16: case 17: case 18: case 19: case 20: printf("Très bien"); break; case default: printf("Erreur !"); break; }

L’interrupteur (ou switch) Autre exemple : char choix; printf("Choisissez une opération (+,-,/ ou * :"); scanf("%c",&choix); switch(choix) { case ‘+’: r = addition(a,b); break; case ‘-’: r = soustraction(a,b); break; case ‘/’: r = division(a,b); break; case ‘*’: r = multiplication (a,b); break; case default: printf("Erreur !"); break; }

Les boucles Les labels dépendent de la variante utilisée (lecture ou affectation arbitraire) : char choix=‘X’; printf("Voulez vous un café ? (O/N)"); while (choix!=‘O’ && choix!=‘N’) { scanf("%c",&choix); if (choix != ‘O’ && choix != ‘N’ ) { printf("Saisie Erronée."); printf("Recommencez."); } } char choix ; printf("Voulez vous un café ? (O/N)"); scanf("%c",&choix); while (choix!=‘O’ && choix!=‘N’) { printf("Vous devez répondre par O ou N."); printf("Recommencez."); } printf("Saisie acceptée.");

Les boucles Le compteur doit être de type entier. Si on souhaite un pas différent, on le précise : for ( compteur = 10 ; compteur >= 1 ; compteur -- ) { … } for ( compteur = 1 ; compteur <= 10 ; compteur += 2 ) Si le pas est négatif alors la valeur initiale doit être supérieure à la valeur finale (et vice versa). Les 3 expressions du for sont facultatifs. Ainsi for ( ; ; ) { … } est valide : c’est une boucle infinie.

Les boucles Imbrication de boucles (while ou for) : int cpt1, cpt2 ; for (cpt1=1 ; cpt1<=24 ; cpt1++ ) { printf("%d heure(s) ",cpt1) ; for (cpt2=1 ; cpt2<=60 ; cpt2 ++) printf("%d minute(s)\n",cpt2) ; }

Les boucles Succession de boucles (while ou for) : int cpt1, cpt2 ; for (cpt1=1;cpt1<=19;cpt1++) { printf("Match aller"); } for(cpt2=1;cpt2<=19;cpt2++) printf("Match retour");

Les boucles Erreur à ne pas faire (while ou for) : agir plusieurs fois sur la variable permettant d’entrer ou sortir de la boucle. int compteur ; for (compteur=1 ; compteur<=15 ; compteur++) { compteur = compteur * 2 ; printf("Passage numéro : %d\n", compteur) ; }

Les boucles Interchangeabilité de for et while : for ( cpt = 1 ; cpt<=500 ; cpt ++ ) { printf("Je ne dois pas lancer d’avion en papier en classe.\n"); } cpt = 1 ; while (cpt<=500) cpt++ ; for ( expr1 ; expr2 ; expr3 ) { [Liste d’instructions] } expr1 ; while (expr2) { [Liste d’instructions] expr3 ; }

Les tableaux Déclaration : La déclaration d’un tableau peut aussi se faire à l’aide de constantes symboliques. #define NB_JOURS 365 #define NB_HEURES 24 int main() { int i, j, stat_appel_pompier[NB_JOURS][NB_HEURES]; for (i=0;i<NB_JOURS;i++) for (j=0;j<NB_HEURES;j++) printf("jour %d, heure %d : combien d’appels ?",i,j); scanf("%d",&stat_appel_pompier [ i ][ j ]); } // …

Les tableaux Remarque : Il n’est pas obligatoire d’utiliser tout un tableau. … int i, notes [40], n; printf("Combien d’étudiants dans le groupe de TP (<40) ?"); scanf("%d",&n); for (i=0;i<n;i++) { printf("Entrez la note :"); scanf("%d",&notes[i]); }

Les tableaux dynamiques Il arrive qu’on ne connaisse pas à l’avance la taille d’un tableau. Première solution : faire un tableau gigantesque (voir transparent précédent) … Deuxième solution : déclarer le tableau sans préciser la taille puis, une fois sa dimension connue, le dimensionner  principe de l’allocation dynamique de mémoire Attention à ne pas utiliser un tableau non dimensionné !

Les tableaux dynamiques Rq : sizeof(argument) est un opérateur qui retourne la taille de l’argument (en fait le nombre d’octets nécessaires). Exemple : int main( ) { int * tab, n, i; printf("Entrez un nombre : "); scanf("%d",&n); tab = (int *) malloc (n*sizeof(int)); for (i=0;i<n;i++) tab[i] = i*i; printf("%d\n",tab[i]); } tab = realloc (tab,2*n*sizeof(int)); for (i=0;i<2*n;i++) free(tab); return 0;

Les tableaux dynamiques Fichier d’en-tête : stdlib.h ou malloc.h Allocation de la mémoire : void *malloc( size_t size ); Réallocation de mémoire : void *realloc( void *memblock, size_t size ); Libération de la mémoire : void free( void *memblock );

Les tableaux dynamiques En C++ : Allocation via l’opérateur new Tableau d’entiers 1D : int * tab; tab = new int [n]; Tableau d’entiers 2D : int ** tab; tab = new int * [h]; for (i=0;i<h;i++) { tab[i] = new int [l]; } Libération via l’opérateur delete Tableau 1D : delete tab; Tableau 2D : for (i=0;i<h;i++) { delete [ ] tab[i]; }

Les fonctions prédéfinies Quelques fonctions de string.h strcpy(s1,s2) : copie la chaîne s2 dans la chaîne s1 strcat(s1,s2) : concatène la chaîne s2 à la chaîne s1 strcmp(s1,s2) : compare les deux chaînes et retourne 0 si elles sont identiques strlen(s1) : retourne la taille de la chaîne s1 … Une fonction de conio.h getch() : saisi d’un caractère « à la volée »

Les fonctions prédéfinies Quelques fonctions de stdio.h scanf(), printf() : lecture et écriture standard (clavier, écran) fscanf(), fprintf() : lecture et écriture pas forcément standard (ex : fichier) fopen(), fclose() : ouverture et fermeture de fichier getchar() : saisi d’un caractère gets() : saisi d’une chaîne …

Les fonctions prédéfinies Quelques fonctions de stdlib.h atoi(), atof() : conversion de chaîne en entier ou réel rand(), srand() : fonctions « aléatoire » free(), malloc(), realloc(), calloc() : fonctions de gestion dynamique de la mémoire exit() : interruption du programme qsort() : tri d’éléments …

Les fonctions Passage de tableau : Dimension du tableau passé en argument complémentaire Passage de tableau : float moyenne ( float tab[ ] , int n ) { float result = 0.0 ; int i ; for ( i = 0 ; i < n ; i ++ ) result += tab[ i ] / n ; } return result ; Dans main ( ) : … m = moyenne(mon_tableau, k); … Où mon_tableau est un tableau contenant k valeurs.

Les fonctions Passage de tableau : Pour un tableau de dimension supérieure à 1, il faut préciser, dans la liste des arguments, la taille des dimensions supplémentaires : float fct ( float tab[ ][2], int n1, int n2 ) { … } float fct ( float tab[ ][2][4], int n1, int n2, int n3 ) { … } Avec cette méthode de passage, les modifications apportées au tableau dans la fonction se répercutent dans le tableau de la fonction main.

Entrée/Sortie de fichiers Pour lire ou écrire dans un fichier, différentes fonctions sont utilisables : fopen() : ouverture de fichier fprintf() : écriture dans un fichier fscanf() : lecture d’un fichier fclose() : fermeture de fichier feof() : détection de la fin de fichier …

Entrée/Sortie de fichiers Fichier d’en-tête : stdio.h Déclaration d’un pointeur « Fichier » : FILE * nom; Rq : Bien respecter les majuscules du mot FILE.

Entrée/Sortie de fichiers fopen( ) : Prototype : FILE *fopen( const char *filename, const char *mode ); filename : nom du fichier à ouvrir mode : permission d’accès "r" : en lecture ; si le fichier n’existe pas ou ne peut pas être trouvé, l’ouverture échoue. "r+" : en lecture et en écriture ; le fichier doit exister sinon l’ouverture échoue. "w" : ouvre un fichier vide en écriture ; si le fichier existe déjà, son contenu est détruit. "w+" : ouvre un fichier vide en lecture et en écriture ; si le fichier existe déjà, son contenu est détruit. "a" : ouvre en écriture à la fin du fichier (appending = concaténation) ; si le fichier n’existe pas, il est créé. "a+" : ouvre en lecture et concaténation ; si le fichier n’existe pas, il est créé.

Entrée/Sortie de fichiers fprintf( ) : Prototype : int fprintf( FILE *stream, const char *format [, argument ]... ); stream : nom de la variable fichier format : cf. fonction printf() fscanf( ) : int fscanf( FILE *stream, const char *format [, argument ]... ); format : cf. fonction scanf()

Entrée/Sortie de fichiers Exemple : int main() { int a,b,c; FILE * f1, * f2; if ((f1=fopen("Debug/test.dat","r"))==NULL) printf("Echec à l'ouverture de f1\n"); } else printf("Fichier f1 ouvert\n"); if ((f2=fopen("Debug/test2.dat","w"))==NULL) printf("Echec à l'ouverture de f2\n"); printf("Fichier f2 ouvert\n"); while(!feof(f1)) fscanf(f1,"%d %d %d",&a,&b,&c); fprintf(f2,"%d %d %d\n",a*2,b-1,c+4); fclose(f2); fclose(f1); return 0;

Entrée/Sortie de fichiers J’ouvre le 1er fichier ; si cela échoue, la valeur NULL est retournée par fopen(). Idem avec le second fichier. Tant que la fin du fichier « f1 » n’est pas atteinte, je lis dans le fichier « f1 » 3 entiers successifs et j’écris dans le fichier « f2 » 3 entiers calculés à partir de ceux acquis.

Les pointeurs X Mémoire : 20 Adresse : … 58 59 5A 5B 5C … Adressage direct et indirect : Adressage direct : En C, des variables sont utilisées pour stocker les informations. La valeur d'une variable se trouve à un endroit spécifique dans la mémoire interne de l'ordinateur. Le nom de la variable permet alors d'accéder directement à cette valeur. Adressage direct = Accès au contenu d'une variable par le nom de la variable Exemple : int X; X = 20; X Mémoire : 20 Adresse : … 58 59 5A 5B 5C …

Les pointeurs X P Mémoire : 5A 20 Adresse : … 0B 0C 0D … 58 59 5A 5B Adressage indirect : Si on ne veut pas ou si on ne peut pas utiliser le nom d'une variable X, on peut copier l'adresse de cette variable dans une variable spéciale P, appelée pointeur. Par la suite, on accède à l'information de la variable X en passant par le pointeur P. Adressage indirect = Accès au contenu d'une variable en passant par un pointeur qui contient l'adresse de la variable Exemple : X P Mémoire : 5A 20 Adresse : … 0B 0C 0D … 58 59 5A 5B 5C …

Les pointeurs Pointeur : C’est une variable « spéciale » qui peut contenir l'adresse d'une autre variable. En C, chaque pointeur est limité à un type de données. Si un pointeur P contient l'adresse d'une variable X, on dit que : « P pointe sur X » Attention : Les pointeurs et les noms de variables ont le même rôle : ils donnent accès à un emplacement dans la mémoire interne de l'ordinateur. Mais : Un pointeur est une variable qui peut « pointer » sur différentes adresses (c.-à-d. contenir différentes adresses). Le nom d'une variable reste toujours lié à la même adresse (par contre, à cette adresse, différentes valeurs peuvent être contenues).

&nom_variable fournit l'adresse de la variable nom_variable Les pointeurs Les opérateurs de base : & et * Opérateur & « adresse de » : &nom_variable fournit l'adresse de la variable nom_variable L'opérateur & est notamment utilisé par la fonction scanf qui a besoin de l'adresse de ses arguments pour pouvoir leur attribuer les valeurs saisies. Soit P un pointeur non initialisé et X une variable (du même type) contenant une valeur (quelconque). L'instruction P = &X; affecte l'adresse de la variable X à la variable P.

Les pointeurs Opérateur * « contenu de » : *nom_pointeur désigne le contenu de l'adresse référencée par le pointeur nom_pointeur. Sert aussi à la déclaration d'un pointeur : type *nom_pointeur déclare un pointeur nom_pointeur qui peut recevoir des adresses de variables du type type. Une déclaration comme int *P_num; peut être interprétée comme suit : « *P_num est du type int » « P_num est un pointeur sur int » « P_num peut contenir l'adresse d'une variable du type int »

Les pointeurs Exemple : P X Y Mémoire : ? 20 40 Adresse : … 0B 0C 0D … int X=20, Y=40, *P; /* P pointeur non initialisé pouvant contenir une adresse d’une variable de type int comme X ou Y */ P X Y Mémoire : ? 20 40 Adresse : … 0B 0C 0D … 5A 5B 5C … FA …

Les pointeurs P X 5B 20 5B Y 20 P X Y Mémoire : 5B 100 20 Adresse : … P = &X; // P pointe sur X Y = *P; // le contenu de X (référencé par *P) est affecté à Y *P = 100; // le contenu de X (référencé par *P) est mis à 100 5B 20 5B Y 20 P X Y Mémoire : 5B 100 20 Adresse : … 0B 0C 0D … 5A 5B 5C … FA …

Les pointeurs Autre exemple : int X; printf("Entrez un nombre : "); scanf("%d", &X); printf("vous avez entré %d\n",X); est équivalent à : int X, *P ; P=&X ; printf("Entrez une valeur : "); scanf("%d",P); Ou directement : int X, *P=&X; Ou : printf("vous avez entré %d\n",*P);

printf("%d",*P)  printf("%d",X) Les pointeurs Les opérations élémentaires sur pointeurs : Priorité de * et & : Les opérateurs * et & ont la même priorité que les autres opérateurs unaires (la négation !, l'incrémentation ++, la décrémentation --). Dans une même expression, les opérateurs unaires *, &, !, ++, -- sont évalués de droite à gauche. Si un pointeur P pointe sur une variable X, alors *P peut être utilisé partout où on peut écrire X. Par exemple, après l'instruction P=&X; les expressions suivantes sont équivalentes : Y = *P+1  Y = X+1 *P = *P+10  X = X+10 *P += 2  X += 2 ++*P  ++X (*P)++  X++ printf("%d",*P)  printf("%d",X)

Les pointeurs Adressage des composantes d'un tableau : Le nom d'un tableau représente l'adresse de son premier élément. En d'autre termes : &tableau[0] et tableau sont une seule et même adresse. En simplifiant, on peut retenir que le nom d'un tableau est un pointeur constant sur le premier élément du tableau. Exemple : int T[20], *P; P T Mémoire : ? Adresse : 0C … 50 51 52 … 5F 60 61 62 63

Les pointeurs P T Mémoire : 50 Adresse : 0C … 50 51 52 … 5F 60 61 62 Exemple (suite) : P = T;  P = &T[0]; Si P pointe sur une composante quelconque d'un tableau, alors P+1 pointe sur la composante suivante. Plus généralement, P+i pointe sur la ième composante derrière P et P-i pointe sur la ième composante devant P. Ainsi, après P=T; (le pointeur P pointe sur T[0]) : *(P+1) désigne le contenu de T[1] *(P+2) désigne le contenu de T[2] ... *(P+i) désigne le contenu de T[i] P T Mémoire : 50 Adresse : 0C … 50 51 52 … 5F 60 61 62 63

Les pointeurs Pointeurs et chaînes de caractères : Un pointeur sur int peut contenir l'adresse d'une variable ou d'une composante d'un tableau (ex : int X, *p; p=&X; ). Un pointeur sur char peut également pointer sur un caractère isolé ou sur les éléments d'un tableau de caractères (ex : char X, *c; c=&X; ). Un pointeur sur char peut en plus contenir l'adresse d'une chaîne de caractères constante et il peut même être initialisé avec une telle adresse (ex : char *c = "salut !"; ).

Les pointeurs Exemple : char *c; c = "Salut !"; Il est possible de lire cette chaîne constante (pour l'afficher), mais il n'est pas recommandé de la modifier parce que le résultat d’une telle opération n'est pas prévisible en ANSI-C. C ? Mémoire : 5B ‘S’ ‘a’ ‘l’ ‘u’ ‘t’ ‘ ’ ‘!’ ‘\0’ … Adresse : 0C … 5B 5C 5D 5E 5F 60 61 62 63

Les pointeurs Un pointeur sur char peut être initialisé lors de la déclaration si on lui affecte l'adresse d'une chaîne de caractères constante (ex : char *C = "Salut !";) mais cela reste très différent d’une initialisation d’un tableau de caractères. char T[ ] = "Salut !"; /* un tableau */ char *C = "Salut !"; /* un pointeur */ T est un tableau qui a exactement la grandeur pour contenir la chaîne de caractères et la terminaison '\0'. Les caractères de la chaîne peuvent être changés, mais le nom T va toujours pointer sur la même adresse en mémoire. C est un pointeur qui est initialisé de façon à ce qu'il pointe sur une chaîne de caractères constante stockée quelque part en mémoire. Le pointeur peut être modifié et pointer sur autre chose. La chaîne constante peut être lue, copiée ou affichée, mais pas modifiée.

Les pointeurs char *c="Salut !"; char T[ ]="Salut !"; ou char T[10]="Salut !"; C ? Mémoire : 5B ‘S’ ‘a’ ‘l’ ‘u’ ‘t’ ‘ ’ ‘!’ ‘\0’ … Adresse : 0C … 5B 5C 5D 5E 5F 60 61 62 63 T Mémoire : ‘S’ ‘a’ ‘l’ ‘u’ ‘t’ ‘ ’ ‘!’ ‘\0’ Adresse : … 5B 5C 5D 5E 5F 60 61 62 …

type personnalisé Il est possible de définir des nouveaux types à l’aide du mot-clé typedef. On le fera ainsi pour utiliser des structures qui sont des éléments plus complexes que les types de base. Exemple : typedef struct { float x1, y1; float x2, y2; } vecteur ; Soit la déclaration suivante : vecteur v On accède aux « sous-variables » par : v.x1, v.x2, v.y1, v.y2

type personnalisé #include<stdio.h> #include<math.h> typedef struct { float x1, y1, x2, y2; } vecteur; float euclide(vecteur u); int main(int argc, int*argv[]) { vecteur v; float l; printf("Entrez les coordonnées du vecteur :\n"); scanf("%f%f%f%f",&v.x1,&v.y1,&v.x2,&v.y2); l = euclide(v); printf("La norme du vecteur est %f.",l); return 0; } float euclide(vecteur u) return sqrt((u.x1-u.x2)*(u.x1-u.x2)+(u.y1-u.y2)*(u.y1-u.y2));

Les projets multi-fichiers Dans le cas de gros projets, il est possible de structurer un programme sur plusieurs fichiers. Par exemple : Un fichier contenant la fonction main Un fichier contenant les fonctions secondaires Un fichier d’en-tête

Les projets multi-fichiers main.c #include<stdio.h> #include"fct_sec.h" int main(int argc, int*argv[]) { vecteur v; float l; printf("Entrez les coordonnées du vecteur :\n"); scanf("%f",&v.x1,&v.y1,&v.x2,&v.y2); l = euclide(v); printf("La norme du vecteur est %f.",l); return 0; }

Les projets multi-fichiers fct_sec.h fct_sec.c #ifndef ENTETE #define ENTETE typedef struct { float x1, y1; float x2, y2; } vecteur; float euclide(vecteur u); #endif #include"fct_sec.h" #include<math.h> float euclide(vecteur u) { return sqrt((u.x1-u.x2)*(u.x1-u.x2)+(u.y1-u.y2)*(u.y1-u.y2)); }

Algorithmes utiles Trier un tableau de données : « Tri par insertion » 1. Recherche du plus petit élément et permutation avec le premier élément du tableau. 2. Recherche du deuxième plus petit élément et permutation avec le second élément du tableau. 3. Recherche du troisième plus petit élément et permutation avec le troisième élément du tableau, et ainsi de suite. 45 122 12 3 21 78 64 53 89 28 84 46 3 122 12 45 21 78 64 53 89 28 84 46 3 12 122 45 21 78 64 53 89 28 84 46

Algorithmes utiles Recherche du min Permutation Au final, on a de deux boucles imbriquées : Boucle principale : on prend comme point de départ le premier élément, puis le second, etc., jusqu’à l’avant dernier. Boucle secondaire : à partir de ce point de départ mobile, on recherche jusqu’à la fin du tableau quel est le plus petit élément. Une fois trouvé, on l’échange avec le point de départ. for (i=0;i<=10;i++) { posmini = i; for (j=i+1;j<=11;j++) { if ( t [ j ] < t [ posmini ] { posmini = j; } temp = t [ posmini ]; t [ posmini ] = t [ i ]; t [ i ] = temp; Recherche du min Permutation

Algorithmes utiles Rechercher une donnée dans un tableau : le « flag » int Tab[20], N, i; printf("Entrez la valeur à rechercher"); scanf("%d",&N); for (i=0;i<20;i++) { if (N == Tab[i]) { printf("N fait partie du tableau"); } else { printf("N ne fait pas partie du tableau"); } }  20 messages !

Algorithmes utiles Solution utilisant un « flag » : int Tab[20]; int N, i, trouve; printf("Entrez la valeur à rechercher"); scanf("%d",&N); trouve = 0; for (i=0;i<20;i++) { if ( N == Tab[ i ] ) trouve = 1; } if ( trouve ) printf("N fait partie du tableau"); else printf("N ne fait pas partie du tableau");

Algorithmes utiles Il suffit que N soit égal à une seule valeur de Tab pour qu'elle fasse partie du tableau. En revanche, il faut qu'elle soit différente de toutes les valeurs de Tab pour qu'elle n'en fasse pas partie. Le « flag » est donc un drapeau qui se lève (VRAI) dès qu’on rencontre la valeur recherchée mais qui ne s’abaisse jamais. Par défaut ce drapeau est abaissé (FAUX).

Algorithmes utiles Tri de tableau + « flag » = « Tri à bulles » Un tableau trié est un tableau dont chaque élément est plus petit que le suivant. Comparons un élément à celui qui le suit : s’il est plus grand alors on les permute. Et on recommence tant que des permutations sont possibles. Les éléments les plus grand finissent ainsi par remonter vers les dernières places. L’emploi du « flag » se définit ainsi : Il suffit que deux éléments soient mal classés pour qu’un tableau ne soit pas trié. En revanche, il faut que tous les éléments soient bien rangés pour que le tableau soit trié.

Algorithmes utiles Pour entrer dans la boucle int permutation; … permutation = 1; while ( permutation ) { permutation = 0; for (i=0;i<=10;i++) if ( tab[i] > tab[i+1] ) temp = tab[i]; tab[i] = tab[i+1]; tab[i+1] = temp; } Pour entrer dans la boucle Parcours du tableau de données A un moment, il peut y avoir permutation : on restera dans la boucle

FIN