• Aucun résultat trouvé

Introduction à la programmation structurée

N/A
N/A
Protected

Academic year: 2022

Partager "Introduction à la programmation structurée"

Copied!
96
0
0

Texte intégral

(1)

INTRODUCTION A LA PROGRAMMATION STRUCTURE

Jean Marie Dembele

(2)

Avant-propos

L’Université virtuelle africaine (UVA) est fière de participer à l’accès croissant à l’éducation dans les pays africains grâce à la production de matériaux d’apprentissage de qualité.

Nous sommes également fiers de contribuer à la connaissance globale car nos ressources éducatives ouvertes sont principalement accessibles depuis le continent africain.

Ce module a été développé dans le cadre d’un programme de diplôme et d’études en informatique appliquée, en collaboration avec 18 institutions partenaires africaines de 16 pays. Au total, 156 modules ont été développés ou traduits pour assurer la disponibilité en anglais, en français et en portugais. Ces modules ont également été mis à disposition en tant que ressources éducatives ouvertes (OER) sur oer.avu.org.

Au nom de l’Université virtuelle africaine et de notre patron, nos institutions partenaires, la Banque africaine de développement, je vous invite à utiliser ce module dans votre institution, pour votre propre éducation, à le partager aussi largement que possible et à participer activement à l’AVU Communautés de pratique de votre intérêt. Nous nous sommes engagés à être en première ligne de développement et de partage de ressources éducatives ouvertes.

L’université virtuelle africaine (UVA) est une organisation intergouvernementale panafricain créée par une charte qui a pour mandat d’augmenter considérablement l’accès à une éducation et à une formation supérieures de qualité grâce à l’utilisation innovante des technologies de communication d’information. Une charte établissant l’UVA en tant

qu’organisation intergouvernementale a été signée à ce jour par dix-neuf (19) gouvernements africains - Kenya, Sénégal, Mauritanie, Mali, Côte d’Ivoire, Tanzanie, Mozambique,

République démocratique du Congo, Bénin, Ghana, République de Guinée, Burkina Faso, Niger, Soudan du Sud, Soudan, Gambie, Guinée-Bissau, Éthiopie et Cap-Vert.

Les institutions suivantes ont participé au Programme des sciences informatiques appliquées:

(1) Université d’Abomey Calavi au Bénin; (2) Université de Ougagadougou au Burkina Faso;

(3) Université Lumière de Bujumbura au Burundi; (4) Université de Douala au Cameroun;

(5) Université de Nouakchott en Mauritanie; (6) Université Gaston Berger au Sénégal; (7) Université des Sciences, Techniques et Technologies de Bamako au Mali (8) Institut de gestion et d’administration publique du Ghana; (9) Université Kwame Nkrumah de Science et Technologie au Ghana; (10) L’Université Kenyatta au Kenya; (11) Egerton University au Kenya;

(12) Université d’Addis-Abeba en Ethiopie (13) Université du Rwanda; (14) Université de Dar es-Salaam en Tanzanie; (15) Université Abdou Moumouni de Niamey au Niger; (16) Université Cheikh Anta Diop au Sénégal; (17) Université Pedagógica au Mozambique; Et (18) L’Université de Gambie en Gambie.

Bakary Diallo Le Recteur

(3)

Crédits de production

Auteur

Jean Marie Dembele

Pair Réviseur

Pelagie Houngue

UVA – Coordination Académique

Dr. Marilena Cabral

Coordinateur global Sciences Informatiques Apliquées

Prof Tim Mwololo Waema

Coordinateur du module

Jules Degila

Concepteurs pédagogiques

Elizabeth Mbasu Benta Ochola Diana Tuel

Equipe Média

Sidney McGregor Michal Abigael Koyier

Barry Savala Mercy Tabi Ojwang

Edwin Kiprono Josiah Mutsogu

Kelvin Muriithi Kefa Murimi

Victor Oluoch Otieno Gerisson Mulongo

(4)

Droits d’auteur

Ce document est publié dans les conditions de la Creative Commons Http://fr.wikipedia.org/wiki/Creative_Commons

Attribution http://creativecommons.org/licenses/by/2.5/

Le gabarit est copyright African Virtual University sous licence Creative Commons Attribution- ShareAlike 4.0 International License. CC-BY, SA

Supporté par

Projet Multinational II de l’UVA financé par la Banque africaine de développement.

(5)

Avant-propos 2

Crédits de production 3

Droits d’auteur 4

Aperçu du cours 6

Bienvenue à Introduction à la programmation structurée 6

Prérequis 6

Matériaux 6

Objectifs du cours 6

Unités 6

Unité 0: Evaluation diagnostique 6 Unité 1 : Types, opérateurs et expressions, lecture et écriture 7 Unité 2: Instructions de contrôle, fonctions 7 Unité 3: Tableaux, pointeurs et chaînes de caractères, structures, unions et énumérations 7 Unité 4: Fichiers, tests de programme et débogage 7 Évaluation 7

Unité 0. Évaluation diagnostique 12

Introduction à l’unité 12

Objectifs de l’unité 12

Évaluation de l’unité 12

Unité 1. Types, opérateurs et expressions, lecture et écriture 14

Introduction à l’unité 14

Objectifs de l’unité 14

Activités d’apprentissage 14

Activité 1 – Revue des types de base en C 14 Conclusion 20

Activité 2 – Découverte des opérateurs et des expressions en C 20 Conclusion 24

(6)

Activité 3 – Manipulation des opérations de lecture et écriture 25 Évaluation 25 Conclusion 27 Évaluation 28

Unité 2. Instructions de contrôle, fonctions 31

Introduction à l’unité 31 Objectifs de l’unité 31 Activités d’apprentissage 32

Activité 1 – Les instructions de contrôle 32

Conclusion 37

Activité 2 – Les fonctions en C 40

Conclusion 49 Évaluation 51

Unité 3. Tableaux, pointeurs et chaînes de caractères, structures, unions

et énumérations 53

Introduction à l’unité 53 Objectifs de l’unité 53 Activités d’apprentissage 54

Activité 1 – Tableaux et pointeurs 54

Conclusion 61 Activité 2 – Correspondances entre pointeurs et tableaux, chaines de

caractères. 63

Conclusion 67 Conclusion 73 Évaluation 76

Unité 4. Fichiers, tests de programme, débogage 79

Introduction à l’unité 79 Objectifs de l’unité 79 Activités d’apprentissage 80

Activité 1 – Fichiers 80

(7)

Conclusion 87

Évaluation 88

Évaluation 89

Évaluation 91

Références du cours 92

(8)

Aperçu du cours

Bienvenue à Introduction à la programmation structurée

Ce module concerne l’acquisition des concepts de type de données, de variables, d’opérateurs et expressions dans une programmation structurée avec le langage C. Il explique aussi les notions d’entrée/sortie, de structures de contrôle, de sous programmes, de tableaux, de pointeurs et d’allocation dynamique de la mémoire ainsi que des notions de tests de programme et de débogage.

Prérequis

rincipes de la programmation

Matériaux

Les matériaux nécessaires pour compléter ce cours comprennent:

Ordinateur

Compilateur C/C++;

IDEl

Objectifs du cours

Après avoir fini le module, vous devriez être capable de décomposer n’importe quel problème en étapes algorithmiques et de le traduire dans un code source puis de le compiler pour obtenir un exécutable. Ce sujet est très important car il introduit l’apprenant à la programmation structurée, qui lui donne les bases pour tout autre paradigme de programmation.

Unités

Unité 0: Evaluation diagnostique

Cette unité vous permettra de vérifier les connaissances que vous devez avoir avant de commencer le cours.

(9)

Unité 1 : Types, opérateurs et expressions, lecture et écriture

Cette unité présente les notions de typage en C et les opérateurs et expressions. Elle

introduit aussi les fonctions élémentaires d’entrées sorties, notamment de lecture et d’écriture ainsi que leurs formats, sur les entrées et sorties standards.

Unité 2: Instructions de contrôle, fonctions

Dans cette unité, vous découvrirez la syntaxe des différentes instructions de contrôle existant en C ainsi que la notion de fonctions et de structure d’un programme en C avec différents modules.

Unité 3: Tableaux, pointeurs et chaînes de caractères, structures, unions et énumérations

Les tableaux de différents types de base, ainsi que les pointeurs et chaînes de caractères seront introduits dans cette unité. Les types composés à partir de type simples seront également détaillés

Unité 4: Fichiers, tests de programme et débogage

Le traitement de fichiers, et de manière générale, celui des entrées sorties sera fait dans cette unité qui se terminera par des tests de programme et des techniques de débogage.

Évaluation

Les évaluations formatives (vérification de progrès) sont incluses dans chaque unité.

Les évaluations sommatives (tests et travaux finaux) sont fournies à la fin de chaque module et traitent des connaissances et compétences du module.

Les évaluations sommatives sont gérées à la discrétion de l’établissement qui offre le cours.

Le plan d’évaluation proposé est le suivant:

1 Devoir sur table 25%

2 Projet en équipe 25%

3 Examen sur table 50%

(10)

Plan

Unité

Sujets et Activités Durée

estimée

Types, opérateurs et expressions, lecture et écriture

Revue des types de base en C:

Retenir la structure générale du programme, Découvrir et utiliser les types de base du langage C,

Déclarer et utiliser des variables de types de base,

Conversions implicite et explicite de types, Constantes de types de base).

Découverte des opérateurs et des expressions:

Se familiariser avec les opérateurs Tableau des priorités des opérateurs

Expressions

Manipulation des opérations de lecture et écriture

Lecture et Ecriture

Autres fonctions et macros usuelles

25h

(11)

Instructions de contrôle, fonctions

Les instructions de contrôle:

Découvrir les instructions alternatives Découvrir les instructions répétitives

Terminer avec les instructions de branchement Les instructions de branchement dans les boucles

Les fonctions en C:

Définir une fonction en langage C Variables locales, globales, statiques et temporaires

Distinguer le passage par adresse du passage par valeur

Utiliser les arguments de la fonction main() Ecrire un programme modulaire

Régles de compilation

35h

(12)

Tableaux, pointeurs et chaines de caractères, structures, unions et énumérations

Tableaux et pointeurs:

Définir des tableaux et pointeurs (définitions et initialisations des tableaux, les tableaux de caractères, les tableaux à plusieurs dimensions, définitions et initialisations des pointeurs, arithmétiques des pointeurs)

Comprendre l’allocation dynamique (

Correspondances entre pointeurs et tableaux, chaines de caractères:

Bien cerner l’équivalence entre tableau et pointeur (tableau à une dimension, tableau à deux dimensions)

Manipulations de chaines (les fonctions usuelles) Strutures, Unions, Enumerations:

Définir une structure (définition avec ou sans nom, utilisation des champs de la structure, les structures et les pointeurs, passage par adresse des structures, redéfinition de type, opérations sur les structures,

Définir une union Définir une énumération

35h

(13)

Fichiers, tests de

programme et débogag

e

Fichiers:

Définir un fichier Ouverture d’un fichier Mode d’accès aux fichiers Fermeture de fichiers

Généralisation : entrées sorties formatées Impression et lecture de caractères Les entrées-sorties binaires

Positionnement dans le fichier Tests de programmes et débogage:

Détection des erreurs Débogage

Couverture et profilage de code Makefiles

Analyseurs de code

25h

Lectures et autres ressources

Les lectures et autres ressources dans ce cours sont indiquées ci-dessous.

• D.M., Ritchie, B.W., Kernighan., 1988. The C Programming Language Second Edition. Prentice Hall Inc., Englewood Cliffs, New Jersey.

• S.P. Harbison, G.L. Steele Jr, C A Reference Manual 2nd Ed, Tartan Laboratories, Prentice-Hall Software series, 1987.

• Peter Van Der Linden, Expert C Programming, Deep C Secrets, Prentice Hall, 1994.

• BRAQUELAIRE Jean-Pierre, Méthodologie de la programmation en C, Masson, 1998.

• CHARBONNEL Jacquelin, Langage C – les finesses d’un langage redoutable, Armand Colin, 1992.

• FEUER R. Alan, Langage C – problèmes et exercices, Masson, 1991.

• Claude Delannoy, Programmer en langage C, Cours et Exercices Corrigés,

(14)

Unité 0. Évaluation diagnostique

Introduction à l’unité

Cette unité vous permettra de vérifier les connaissances que vous devez avoir avant de commencer le cours. Vous pouvez faire l’évaluation de l’unité avant de faire des activités d’apprentissage pour aider à rafraîchir vos connaissances en informatique..

Objectifs de l’unité

À la fin de cette unité, vous devriez être capable de:

Vérifier et raffermir vos connaissances de base en informatique

Évaluation de l’unité

Vérifiez votre compréhension!

Devoir sur table 0 Directives

Répondre aux questions posées, l’évaluation dure 1h.

Système de notation

Le barème est indiqué à la suite des questions

Évaluation

Question de culture générale (20 pts) Qu’est ce que l’informatique?

Rappeler les grandes dates de l’évolution de l’ordinateur.

Que stipule la loi de Moore ?

Citer 04 langages de programmation découverts à partir de votre recherche personnelle Donner l’architecture générale d’un ordinateur (sous forme de schéma) et le rôle des différents composants

(15)

Donner sous forme d’organigrammes, les différentes instructions de contrôle que vous connaissez

Quelles sont les différences entre arguments formels et arguments effectifs dans l’écriture de fonctions

Expliquer la notion de passage par adresse

Donner la structure générale d’un programme qui comporte une fonction ou plusieurs fonctions

Lectures et autres ressources

Les lectures et ressources de cette unité sont se trouvent au niveau des lectures et autres ressources du cours.

(16)

Unité 1. Types, opérateurs et expressions, lecture et écriture

Introduction à l’unité

Cette unité présente les notions de typage en C et les opérateurs et expressions. Elle

introduit aussi les fonctions élémentaires d’entrées sorties, notamment de lecture et d’écriture ainsi que leurs formats, sur les entrées et sorties standards.

Objectifs de l’unité

À la fin de cette unité, vous devriez être capable de:

Définir une variable de type de base dans un programme informatique

Utiliser une variable (éléments du monde réel) de type de base dans une opération.

Constituer une expression correcte (phrase du langage) en C.

Effectuer des opérations d’entrée et de sortie (de lecture et d’écriture sur le clavier et l’écran) Ecrire votre premier programme en C.

TERMES DES

Variable: symbole dénommé par un identificateur et qui comporte une valeur et un type

Expression: élément de syntaxe qui combine un ensemble d’opérateurs et d’opérandes et qui a une valeur

Programme: ensemble d’opérations destinées à être exécutées par la machine

Activités d’apprentissage

Activité 1 – Revue des types de base en C

(17)

Introduction

Cette activité présente les types de base du langage C. Elle vous permettra de bien connaître les types du langage C et de définir des variables et des constantes de types simples.

Détails de l’activité

Retenir la structure générale du programme

Avant de passer au détail de cette activité, nous proposons de présenter d’abord la structure générale d’un programme en C avec la figure suivante :

• Mise en page : le format du texte est libre et la mise en page n’a pas de signification pour le compilateur (cette dernière est juste importante pour la lisibilité du programme).

• Identificateurs : ils se composent à partir de l’alphabet «a-z, A-Z, 0-9, _ » et commence par une lettre ou le souligné « _ »). Les identificateurs commençant par deux caractères soulignés, ou un caractère souligné suivi d’une majuscule sont réservés au compilateur, et ne doivent pas être utilisés dans un programme « ordinaire ».

• Sensible à la casse des lettres : minuscules différentes des majuscules. Par exemple les deux variables test et TEST désignent deux éléments différents.

• Commentaires : // sur une ligne /* sur plusieurs lignes

*/

• Mots clés

type : char const double float int long short signed unsigned

(18)

classes d’allocation : auto extern register static constructeurs : enum struct typedef union

instructions de contrôle : do for while case default else if switch break

continue goto return

• Type d’instructions:

Une instruction est soit une instruction simple (expression, appels de fonctions, instructions de contrôle) soit une instruction composée.

Une instruction simple est toujours terminée par un ; Les instructions composées sont contenues entre deux accolades : { }

Découvrir et utiliser les types de base du langage C

• void : type vide surtout utilisé pour préciser les fonctions sans argument ou sans retour.

• char : type représentant l‘ensemble des caractères par leurs codes ASCII (un entier sur huit bits compris entre -128 et +127). Il existe un type permettant de supporter des alphabets comprenant plus de 255 signes appelé wchar_t. et défini dans <stddef.h>.

• int : représente des entiers; 2 ou 4 octets ( selon les machines)

• float : représente des réels à virgule flottante; 4 octets

• double : réels à virgule flottante en double précision; 8 octets

• long double : type plus récent qui permet de représenter des nombres avec parties décimales sur une très grande précision, si la machine le permet

• Les modificateurs: précisent le signe du type; positif (unsigned) ou positif et négatif (signed) ou la taille (long ou short). Ces derniers peuvent être utilisés seuls ou avec int, donnant la possibilité d’avoir : short int (short) ou long int (long).

signed char (8 bits) -128 à 127

unsigned char 0 à 255 short (16 bits) -32767 à 32767

(19)

int (cas 16 bits) -32767 à 32767 unsigned int 0 à 65535

long (32 bits) -2147483647 à 2147483647

unsigned long 0 à 4294967295

Déclarer et utiliser des variables de types de base

Faire précéder le nom du type et suivre avec celui des variables :

Type var1, var2, ..., varN;

Exemple; int x, y;

char ch;

float val;

Une variable peut être initialisée lors de sa déclaration

int a = 0;

int b = 16 * 15;

char ch = ‘c’;

Portée des variables Une variable est dite locale, si elle est définie à l’intérieur d’une fonction (ou bloc) et globale si elle est définie en-dehors.

Conversions implicite et explicite de types

Lorsque des variables de différents types sont impliquées dans une opération, il peut se produire une conversion pour que l’opération se réalise (ce qui n’est pas le cas pour tous les langages de programmation). Il y’a deux sortes de conversion : la conversion implicite et la conversion explicite.

Conversion implicite de type : effectuée par le compilateur pour une perte minimum d’information. (voir les règles ISO 89)

(20)

si l’un des deux op. est du type long double alors calculer avec long double;

sinon, si l’un des deux op. est du type double alors calculer avec double ; sinon, si l’un des deux op. est du type float alors calculer avec float ; sinon, appliquer la règle de promotion en entier, puis :

(a) si l’un des deux op. est du type unsigned long int alors calculer avec ce type ; (b) si l’un des deux op. est du type long int alors calculer avec ce type;

(c) si l’un des deux op. est du type unsigned int alors calculer avec ce type ; (d) si l’un des deux op. est du type int alors calculer avec ce type.

Conversion explicite de type : celle qui est effectuée par le programmeur avec l’opérateur de cast

(type) expression ex : (int) c;

(int)2.35 → 2 (float) 2 → 2.0

Attention, ces deux instructions ne sont pas forcément égales i = f + d; et i = (int) f + (int) d ; Constantes de types de base

Constantes de type entier : construites à partir de chiffres et naturellement exprimées en base dix. Elles peuvent aussi être exprimées en base huit (octal) lorsque le premier caractère est un 0 ou en base seize (hexadécimal) lorsque les deux premiers caractères sont 0X ou 0x. Elles peuvent être suffixées par ‘l’, ‘L’, ou ‘u’, ‘U’ pour faire référence à des types long ou unsigned.

sans précision de type : 0342 (oct.), 0X0FF (hex.), 123 (déc.), -280 (décimal).

longue: 120L, 0364l, 0x1faL

(21)

longue non signée :120ul, 0364UL, 0x1faul,

Constantes de type réel : ont le type double par défaut et peuvent être suffixées par ‘f’,‘F’ ou

‘l’,’L’ pour faire référence à une valeur float ou long double.

Notation avec point décimal : 121.34, notation exponentielle : 12134e-2 notation exponentielle : +12134E-2

notation de type float : 121.34f notation de type long double : 121.34l

Constantes de type caractère : se notent en écrivant le caractère entre apostrophes. ‘A’ ‘2’

‘« ’. Les seuls caractères imprimables qu’on ne peut pas représenter de cette façon sont l’antislash et l’apostrophe, qui sont respectivement désignés par \\ et \’.

Les caractères non imprimables peuvent être désignés par ‘\code-octal’ où code-octal est le code en octal du caractère. Ceux qui sont plus fréquents disposent aussi d’une notation plus simple :

\n nouvelle ligne

\t tabulation horizontale

\f saut de page

\v tabulation verticale

\a signal d’alerte

\b retour arrière \r retour chariot

Constantes de type chaine de caractères : Une chaîne de caractères est une suite de caractères entourés par des guillemets (elle se termine en mémoire par le caractère ‘\0’).

Exemple

«Voici est une chaîne de caractères!»

Elles peuvent contenir des caractères non imprimables, désignés par les représentations déjà

(22)

«Apres ceci allez à la ligne \n nous sommes a la ligne suivante»

A l’intérieur d’une chaîne de caractères, le caractère « doit être désigné par \». Enfin, le caractère \ suivi d’un passage à la ligne est ignoré. Cela permet de faire tenir de longues chaînes de caractères sur plusieurs lignes.

«Une longue longue longue longue longue longue longue longue longue longue \ chaîne de caractères»

Conclusion

Voilà, tous les types de base sont présentés, les autres suivront avec les chapitres suivants.

Une petite évaluation vous permettra de revenir sur la déclaration.

Évaluation

• Déclarer des variables de type de base (entier, réel, caractère, …)

• Reprendre l’exercice en utilisant des modificateurs de type…

• En utilisant les caractères non imprimables, présenter une constante chaine de caractères mise en forme (avec des paragraphes, des tabulations, …)

Activité 2 – Découverte des opérateurs et des expressions en C

Introduction

Une fois les types vus, passons maintenant aux opérations possibles sur ce type. Cette activité permet de voir les opérateurs et les conversions de type qu’il faut bien comprendre lorsque l’on met des opérandes de types différents dans une même opération.

Détails de l’activité

Se familiariser avec les opérateurs. En langage C, les opérateurs peuvent être classés suivant le nombre d’opérandes. On parlera d’opérateurs unaires, binaires et ternaires.

Opérateurs unaires

Opérateur d’incrémentation et de décrémentation

et ++ permettent de décrémenter et d’incrémenter des variables de type entier (ou pointeur).

(23)

val -- est équivalent à val = val - 1 val++ est équivalent à val = val + 1

Dans le cas où l’opération est post-fixée à une autre (ex affectation), la valeur de la variable avant l’opération est utilisée pour l’affectation et ensuite l’opération est appliquée, i.e.:

Post-incrémentation y=val++; ⇔ {y=val; val = val + 1; }

Lorsque l’opération est préfixée à une autre (ex affectation), elle est appliquée avant que l’affectation ne soit réalisée.

Pre-incrémentation y=++val; ⇔ {val = val + 1; y=val;}

Opérateur de taille

L’opérateur sizeof donne la taille en octets de la variable dont le nom suit. Il peut aussi donner la taille d’un type, le type doit être entre parenthèses.

sizeof(t) = taille du tableau t; sizeof(t) / sizeof(t[0]) = nombre d’éléments de t

Opérateur de négation logique

La négation logique sert à inverser une condition en la faisant passer de vrai à faux et réciproquement. En C, une expression est fausse si la valeur qu’elle retourne est égale à 0, elle est vraie sinon. !0 vaut 1.

Complément à un

L’opérateur ~ donne le complément à un de l’expression entière qui le suit.

ex val 10101100 ~ val 01010011 Opérateurs binaires

Opérateurs arithmétiques (+, - , / , * , %)

le type de l’opération est déterminé par le type des valeurs sur lesquelles portent l’opération (voir la conversion implicite de type)

Opérateurs de masquage (&, | , ^)

ex 0011 0011 0011

(24)

0101 0101 0101

= 0001 = 0111 = 0110

Opérateurs de décalage (<< , >>)

Manipulent les valeurs contenues dans les variables de type entier en poussant les bits vers la gauche ou la droite. Le décalage vers la droite peut être signé si l’expression est signée mais le résultat dépend de l’implantation (éviter le décalage à droite sur une valeur négative).

Exemple expr1 b1b2b3b4 expr = expr1 << 1 b2b3b40

Opérateurs logiques (&&, ||)

Les expressions dans lesquelles figurent ces opérateurs sont évaluées de gauche à droite, et l’évaluation cesse dès que la véracité ou la fausseté du résultat est établie (expressions avec court circuit).

Ex: pour savoir si j est comprise entre12 et 143 il faut écrire : j >= 12 && j <= 143

Ex: pour savoir si un caractère car contient un ‘a’ en minuscule ou en majuscule:

car == ‘a’ || car == ‘A’

Opérateurs d’affectation et de succession

L’affectation est une expression comme les autres, ce qui nous permet de faire des affectations multiples comme : a = b = c = 1 qui vaut a=(b=(c=1))

dans expr1=exp2, exp1 est une lvalue et expr2 une rvalue

La virgule (ou succession) sert à séparer deux expressions qui sont évaluées successivement.

La valeur associée à cette expression sera la dernière valeur calculée.

i = (j=5, k=100) associe à i la valeur 100.

Opérateurs d’affectations étendues

Certains opérateurs peuvent être superposés avec celui de l’affection pour obtenir une affectation étendue. Le tableau suivant en donne un résumé :

(25)

Opérateur ternaire

Il en existe qu’un seul dont la syntaxe est la suivante : expr1 ? expr2 : expr3

expr1 est d’abord évaluée

Si sa valeur ≠ 0, expr2 est évaluée et définit la valeur de l’expression conditionnelle. expr3 n’est pas évaluée.

Sinon expr3 est évaluée et définit la valeur de l’expression conditionnelle, expr2 pas évaluée.

Ainsi l’expression max = a >= b ? a : b permet de mémoriser dans la variable max la valeur maximum des deux valeurs contenues dans les variables a et b.

Tableau des priorités des opérateurs

Le tableau suivant donne la priorité des opérateurs en langage C. Il faut le lire de haut en bas et de la gauche vers la droite pour connaître les opérateurs prioritaires (sauf si ils sont séparés par des parenthèses ouvrantes et fermantes).

(26)

Expressions

Une expression est une suite syntaxiquement correcte d’opérateurs et d’opérandes. Elle retourne donc une valeur (l’instruction, elle, détermine une action à faire). Toute expression possède au moins 2 attributs : un type et une valeur.

Exemple : Si i est un entier de valeur 10, alors 2*i+3 a pour type entier et pour valeur 23.

Lvalue (cas des variables en général): représentent un emplacement mémoire. La valeur de l’expression est alors définie comme le contenu de cet emplacement. Une lvalue possède 3 attributs : adresse, type, valeur. Ex: a, b, t[i];

Rvalue (cas des valeurs en général) : ont un type et une valeur, mais pas d’adresses (disponible). Ex : 2*a+3, 12;

On peut aussi tomber sur des expressions avec effet de bord, qui modifie des éléments. Ex:

a++ (retourne a et remplace a par a+1), y = 2 (retourne 2 et donne à y la valeur 2).

Conclusion

Vous voici familiers aux types et opérateurs, il ne reste qu’à voir les entrées sorties élémentaires pour écrire un premier programme simple en C.

(27)

Évaluation

Dans les expressions suivantes, enlever les parenthèses superflues :

a = (x+5) a = (x=y) + 2 a = (x==y) (a<b) && (c<d) (i++) * (n+p)

Soient les déclarations suivantes : char c = ‘a’ ; short int p = 10 ; Quels sont le type et la valeur des expressions suivantes :

p + 3 c + 1 p + c 3 * p + 5 * c

Soient les déclarations suivantes : char c = ‘\x05’ ; int n = 5 ; long p = 1000 ; float x = 1.25 ; double z = 5.5 ;

Quels sont le type et la valeur des expressions suivantes :

n + c + p 2 * x + c (char) n + c (float) z + n / 2

Activité 3 – Manipulation des opérations de lecture et écriture

Introduction

Cette dernière activité présente les premières fonctions de la librairie d’entrées sorties pour lire à partir du clavier et écrire sur l’écran. Cela permettra de réaliser les premiers programmes en C.

Détails de l’activité Lecture et Ecriture

Une librairie incontournable pour les entrées sorties élémentaires (lecture et écriture) est la suivante : stdio.h

Pour inclure cette librairie et accéder à ces fonctions, on utilise la syntaxe suivante :

#include <stdio.h>

(28)

Pour l’affichage: printf

Permet d’envoyer vers le fichier courant de sortie (notamment l’écran), des informations formatées. Syntaxe : printf(<format>, v1, v2, …, vn); ou printf(chaine);

<format> - est une chaîne de caractères contenant du texte et des spécificateurs de format (%

suivi d’un caractère de conversion).

ex: printf(“i vaut : %d”, i); printf(“x = %d\t y = %f\n”, x, y); printf(“Bonjour à tous!”);

Pour la saisie: scanf

Permet de recevoir des informations, selon un format précisé depuis le fichier courant des entrées. Syntaxe : scanf(<format>, &v1, &v2, …, &vn)

ex: scanf(“%d%d%f“, &a, &b, &c);

L’opérateur d’adresse & doit être mis devant le nom des variables à saisir (en effet scanf a besoin de l’adresse des variables) sauf pour les variables de type chaines de caractères (c.f.

tableau de tous les formats sur diapo suivante).

Le tableau suivant donne les formats d’affichage pour les différents types déjà vus (ainsi qu’un que nous découvrirons plus tard ; les chaines de caractères).

Autres fonctions et macros usuelles

getchar(): renvoie le caractère suivant du fichier courant des entrées (clavier). Si la fin du fichier

(29)

char c; c = getchar();

putchar(c): envoie le caractère précisé en paramètre dans le fichier courant de sortie (écran) gets(s): lit une ligne à partir de l’entrée standard et la mémorise dans une zone réservée par l’appelant en la complétant par ‘\0’.

char s[20]; gets(s);

puts(s): écrit sur la sortie standard la ligne fournie en paramètre. Le caractère ‘\n’ est automatiquement ajouté après le dernier caractère de la ligne.

Conclusion

Les entrées sorties pourront être détaillées dans les chapitres suivants. Ici, seules les fonctions scanf et printf ont été présentées mais d’autres seront vues pour manipuler les entrées sorties de manière générale comme des fichiers.

Évaluation

Réaliser un programme contenant une fonction main() qui réalise les écritures suivantes : écrire le caractère ‹a› ;

écrire la chaîne de caractères «bonjour» ;

écrire l›entier 32567 dans les formats décimal, hexadécimal, octal et non signé;

écrire le flottant 3.1415927 dans les formats exponentielle et variable.

RESUME DE L’UNITE

Vous êtes à la fin de cette activité. Vous avez tout en main pour écrire un premier programme en C. Un bon IDE devrait vous permettre de programmer en C.

Pour le choix de l’IDE veuillez vous référer au site : http://en.wikipedia.org/wiki/

Comparison_of_integrated_development_environments

Évaluation de l’unité Vérifiez votre compréhension!

Devoir sur table 1 Directives

(30)

Système de notation

Le barème est indiqué à la suite des questions

Évaluation

Question 1 (2 pts)

On considère les expressions suivantes : n * k + m / 5 +12

‘A’ + 8 t[i] = i++

t[i++] = 5 5 = t[i++]

t[i++] = t[i]

Dire quelles sont les expressions correctes et celles incorrectes.

Evaluer les expressions correctes en donnant des valeurs aux variables.

On supposera que n, k, m et x sont des entiers et t un tableau d’entiers Question 2 (2 pts)

Soit x et y deux variables de type double et a et b deux variables de type int. Trouver les erreurs dans les instructions suivantes :

1. printf («La valeur de a est %d\n»);

2. printf («x/y = %d\n», x/y);

3. printf (“x = %lf\n”, x);

4. scanf(«%f», x);

5. scanf(«%d%d», a, b);

6. scanf(«%d, %d», a, b);

Question 3 (3 pts)

Quelles sont les valeurs lues dans les variables n et p (de type int), par l’instruction suivante :

scanf («%d%d» , &n , &p)

(31)

lorsqu’on lui fournit les données suivantes (le symbole ^ représente un espace et le symbole @ représente une validation) :

a) 253^45@

b) ^253^@

c) ^^4^5@

Question 4: opérateur ternaire (4 pts)

En utilisant 4 entiers i, j, k et l, avec k initialisé à 12 et l à 8, écrire le

programme qui lit les valeurs de i et j, écrit la valeur de k si i est nul, écrit la valeur de i + l si i est non nul et j est nul et écrit la valeur de i + j dans les autres cas.

Question 5 (4 pts)

Soient les déclarations suivantes : int n = 5, p = 9 ; int q ; float x ; Quelle est la valeur affectée aux différentes variables par chacune des instructions suivantes :

q = n < p ; q = n == p ; q = p % n + p > n ; x = p / n;

x = (float) p / n ; x = (p+0.5) / n ; x = (int) (p + 0.5) / n;

q = n * (p > n ? n : p) ; q = n * (p < n ? n : p) ; Question 6 (5 pts)

Quels résultats fournira ce programme :

# include <stdio.h>

main(){

(32)

int n, p, q ;

n = 5 ; p = 2 ; /* cas 1*/

q = n++ >p | | p++!=3 ;

printf(«A : n = %d p = %d q = %d \n»,n , p, q);

n = 5 ; p = 2 ; /* cas 2*/

q = n++ <p | | p++ !=3 ;

printf(«B : n = %d p = %d q = %d \n»,n , p, q);

n = 5 ; p = 2 ; /* cas 3*/

q = ++n ==3 && ++p ==3 ;

printf(«C : n = %d p = %d q = %d \n»,n , p, q);

n = 5 ; p = 2 ; /* cas 4*/

q = ++n == 6 && ++p ==3 ;

printf(«D : n = %d p = %d q = %d \n»,n , p, q);

}

Lectures et autres ressources

Les lectures et autres ressorces de cette unité se trouvent au niveau des lectures et autres ressources du cours.

(33)

Unité 2. Instructions de contrôle, fonctions

Introduction à l’unité

Dans cette unité, vous découvrirez la syntaxe des différentes instructions de contrôle existant en C ainsi que la notion de fonctions et de structure d’un programme en C avec différents modules.

Objectifs de l’unité

À la fin de cette unité, vous devriez être capable de:

• Écrire un programme avec une instruction de contrôle

• Répéter, sélectionner et sauter une suite d’instructions

• Ecrire une fonction qui est un sous programme

• Définir une fonction recursive et programmer en ligne de commande

• Constituer un programme de manière modulaire

TERMES DES

Controle: Une instruction de contrôle est une directive devant être exécutée

ou répétée ou ignorée, suivant des conditions .

Fonction: Unité modulaire d’un programme informatique pouvant être appelée plusieurs fois sur des données de valeurs différentes

Récursivité: Processus dont l’objet fait appel à lui même. Une fonction est

dite récursive, si dans sa définition elle fait appel à elle même.

Modularité: Procédé qui permet d’écrire un programme en plusieurs blocs

atomiques pour faciliter sa réutilisation et sa maintenance.

(34)

Activités d’apprentissage

Activité 1 – Les instructions de contrôle

Introduction

Cette activité introduit les instructions de contrôle. Elle vous permettra de découvrir les instructions alternatives, répétitives et celles de branchement. Au sortir de cette activité, vous serez capable d’écrire des programmes plus complexes.

Détails de l’activité

Découvrir les instructions alternatives

Les instructions alternatives permettent de réaliser des tests et d’exécuter des parties de code différentes suivant le résultat de ces tests.

Première instruction

→ if else Syntaxe :

if( expression ) instruction

if( expression ) instruction1 else instruction2

Ex d’expressions:

if (a == b); // vrai si a est égal à b if (a = b); // vrai si b est différent de 0

if (c = getchar()); // vrai si getchar ne retourne pas ‘\0’

if (c); // vrai si c est différent de 0

Ex avec instructions:

if (a != 0) b = 1/a;

if (c >= ‘0’ && c <= ‘9’) printf(«chiffre“); else printf(“autre”);

Deuxième instruction

(35)

Syntaxe :

switch (expression) {

case value1 : instruction1 break;

case value2 : instruction2 break;

case valueN : instructionN break;

default : instructionN+1}

• expression est une valeur entière ;

• les valeurs des case sont des constantes entières ;

• l’exécution se fait à partir du case dont la valeur correspond à l’expression. Elle s’exécute en séquence jusqu’à la rencontre d’une instruction break ;

• les instructions qui suivent la condition default sont exécutées lorsqu’aucune constante des case n’est égale à la valeur retournée par l’expression ;

• l’exécution à partir d’un case continue sur les instructions des autres case tant qu’un break n’est pas rencontré ;

• plusieurs valeurs de case peuvent aboutir sur les mêmes instructions ;

Découvrir les instructions répétitives

Les instructions répétitives permettent de réaliser des tests et de répéter des parties de code suivant le résultat de ces tests.

Première instruction 

→ for Syntaxe :

for( exp1 ; exp2 ; exp3 ) instruction

• l’expression expr1 est réalisée une seule fois lors de l’entrée dans la boucle, c’est expression d’initialisation ;

• l’expression expr2 est la condition d’exécution de l’instruction. Elle est testée à chaque itération, y compris la première.

• l’expression expr3 contrôle l’avancement de la boucle. Elle permet de manière générale de calculer la prochaine valeur avec laquelle la condition de passage va

(36)

Exemples:

for (i = 0 ; i < 10 ; i++) printf(”%d”, i); // affiche de 0 jusqu’a 9 for (i = 0 , j = 10 ; i < j ; i++ , j--) printf(”%d”, i*j);

Deuxième instruction 

→ while Syntaxe :

while( expression ) instruction

La boucle while répète l›instruction tant que la valeur de l›expression est vraie (différente de zéro).

Correspondance entre for et while :

for(exp1; exp2; exp3) instruction

est équivalent à

exp1;

while(exp2) {

instruction exp3;

}

Ex:

for (c = ‘a’; c <= ‘z’; c++) putchar(c);

est équivalent à

c = ‘a’;

while(c <= ‘z’) {

putchar(c);

c = c + 1;

}

Troisième instruction

→ do…while Syntaxe :

(37)

do instruction while( expression )

A l’inverse du while, do while place son test en fin d’exécution, d’où au moins une exécution.

Ex:

do {

printf(“donnez un nb > 0 :“);

scanf(“%d”, &n);

} while ( n <= 0);

Terminer avec les instructions de branchement

→ continue

L’instruction continue est utilisée en relation avec les boucles. Elle provoque le passage à l’itération suivante de la boucle en sautant à la fin du bloc. Elle provoque donc la non exécution des instructions qui la suivent à l’intérieur du bloc.

→ break

Il permet de sortir d’un bloc d’instruction associé à une instruction répétitive ou alternative. Il ne sort que d’un niveau d’imbrication.

Exemple dans un programme:

int n, N=10;

do {printf(“Donnez un nbre positif“);

scanf(“%d”, &n); if (n == N) break;

if ( n < 0) { printf(“le nbre doit être positif”);

continue; }

printf(“Son carré est : %d\n”, n * n);

} while(n);

Les instructions de branchement dans les boucles

La figure suivante donne, de la gauche vers la droite l’impact des instructions de banchement sur les boucles for, while et do...while.

(38)

→ return

return expression;

return;

L’instruction return provoque la terminaison de l’exécution de la fonction dans laquelle elle se trouve et le retour à la fonction appelante. Cette instruction peut être mise à tout moment dans le corps d’une fonction ; son exécution provoque la fin de celle-ci.

Exemple avec une fonction (a voir dans l’activité suivante):

int chercher(int x, int t[], int N) { int i;

for(i = 0; i < N; i++) if ( x == t[i]) return i;

return -1;

}

(39)

→ goto (à éviter)

goto etiquette;

etiquette: instruction

goto permet d’aller n’importe où à l’intérieur d’une fonction. Son utilisation systématique nuit à la lisibilité des programmes. Toutefois, il permet de sortir de plusieurs blocs imbriqués. Il est relié à une étiquette qui est une chaîne de caractères suivie de :

Exemple dans boucles imbriquées for (---) {

for (---- -- -) for(---)

if (---) goto sortie;

….

sortie : ….

}

Conclusion

Vous êtes maintenant prêt à aborder des programmes un peu plus complexes grace aux instructions de contôle qui comme leurs noms l’indiquent permettent de gérer le cours d’execution du programme. Les évaluations suivantes vont renforcer votre utilisation des instructions de contrôle.

Évaluation

→ Y’a t’il des erreurs commises dans les instructions suivantes :

(40)

1 -

if (a<b) printf (“ inf”) else printf(“ sup”) ;

2 –

do while ( (c =getchar()) != ‘\n’) ; 3 - int n ;

switch (2*n+1)

{ case 1 : printf (“ petit”) ; case n : printf (« moyen») ; }

4 -

#define LIM 100 int n ;

switch (n)

{ case LIM - 1 : printf (“moins”) ; case LIM : printf (“ juste”) ; case LIM+ 1 : printf («plus») ; }

→Soit le programme suivant :

switch (n)

{ case 0 : printf (“Nul\n”) ; case 1 :

case 2 : printf (“Petit \n”) ; break ; case 3 :

case 4 :

case 5 : printf (“Moyen\n”) ; default : printf («Grand\n») ; }

(41)

Quel est le résultat obtenu avec les données suivantes pour n : 0, 1, 4, 10, -5

→ Les boucles «for» peuvent être réécrites comme une boucle «while», et vice-versa. Est-ce que les deux programmes qui suivent sont équivalents ? si non, pourquoi ?

int main() {

int count = 1;

for( ; count <=5 ; count++) {

int count = 1;

print- f(“%d\n”,count);

}

return 0;

}

int main() {

int count = 1;

while ( count <=5 ) { int count = 1;

print- f(“%d\n”,count);

count++;

} return 0;

}

→ Que fournissent les suites d’instructions suivantes (n et p des entiers initialisés à 0):

1 – 2 –

(42)

Activité 2 – Les fonctions en C

Présentation

L’activité en cours vous initie aux fonctions en C. Elle montre comment regrouper un ensemble d’instructions pour en faire des sous-programme. Elle va aussi vous donner les notions de variables locales, globables et statiques, de passage de paramètres par valeur et par adresse, de programmation en ligne de commande.

Détails de l’activité

Définir une fonction en langage C

Les fonctions sont des parties d’un programme qui permettent de réaliser le même type de traitements plusieurs fois et ce sur des entrées qui peuvent être différentes.

Pour définir une fonction dans un programme, il faut :

une interface ou signature (la déclaration du type de retour et du nom de la fonction ; une parenthèse ouvrante ; la déclaration des types et des noms des paramètres; une parenthèse fermante)

et un corps de fonction qui est en fait un bloc d’instructions (une accolade ouvrante ; des déclarations de variables locales au bloc ; des instructions ; une accolade fermante)

float calcul(float x, float y) // l’interface de la fonction {

float z = x+y; // le corps de la fonction return z;

}

Variables locales, globales, statiques et temporaires

Variable permanente static

Une variable permanente occupe un emplacement en mémoire qui reste le même durant toute l’exécution du programme. Cet emplacement est alloué une fois pour toutes lors de la compilation. Une variable permanente est caractérisée par le mot-clef static et est initialisée à 0.

(43)

Variable temporaire auto (ou vide, par défaut)

Contrairement à la static, la variable temporaire auto se voit allouer un emplacement en mémoire de façon dynamique lors de l’exécution du programme. Elle n’est pas initialisée par défaut. Son emplacement en mémoire est libéré par exemple à la fin de l’exécution d’une fonction secondaire.

→ Variable globale

Une variable globale est une variable déclarée en dehors de toute fonction. Une variable globale est connue du compilateur dans toute la portion de code qui suit sa déclaration. Les variables globales sont systématiquement permanentes.

Dans le programme suivant, n est une variable globale (initialisée à 0) :

int n; // variable globale void fonction() {

n++;

printf(«appel numero %d\n», n);

return; }

main() { appel numero 3

int i; appel numero 4

for (i = 0; i < 5; i++) fonction(); appel numero 5 }

Ce programme affichera appel numero 1

appel numero 2 appel numero 3 appel numero 4 appel numero 5

→ Variable locale

Une variable locale est une variable déclarée à l’intérieur d’une fonction (ou d’un bloc

(44)

Par défaut, les variables locales sont temporaires. A la sortie de la fonction ou du bloc, les variables locales sont perdues. Elles n’ont en particulier aucun lien avec des variables globales de même nom. Par exemple, le programme suivant :

int n = 10; // variable globale void fonction() {

int n = 0; n++; // variable locale printf(«appel numero %d\n»,n);

return; }

main() {

int i;

for (i = 0; i < 5; i++) fonction();

}

Ce programme affichera appel numero 1

appel numero 1 appel numero 1 appel numero 1 appel numero 1

→ Définition ou déclaration ?

La déclaration se fait en écrivant (voir exemple ci-dessous):

soit une interface identique à celui de la définition soit une interface sans les noms des arguments formels

La définition de la fonction peut être donnée avant ou après son utilisation (dans la fonction main par exemple). Si elle est définie avant, ce n’est plus la peine de le déclarer dans la fonction main().

Executer ces exemples pour tester les déclarations et définitions ainsi que les variables statiques.

(45)

main( ) { void fct1(void);

int n;

for(n=1; n <= 5; n++) fct1( );

}

void fct1(void) { static int i; i++;

printf(″Appel numéro :%d\n″ , i);

}

main( ) { void fct2(int);

int n, j;

for(n=1, j=1; n <= 5; n++, j++) fct2(j);

}

void fct2(int j) { static int i; i++;

printf(″Appel pair numéro : %d\n″ , i+j);

}

→ Type de retour

Toute fonction qui n’a pas comme type de retour void doit retourner un résultat. Le type de ce résultat est celui de la fonction. Le retour de fonction est provoqué par l’appel de l’instruction return.

return expression;

Exemple

int plus(int a, int b) int main()

{ {

a=a+b; int x=4,y=6, z;

return(a) ; z = plus(1,23);

} z += (4 * plus(x,y));

return 0;

}

Quand une fonction ne renvoie pas de valeur, on le précise à la fois dans l’interface et dans sa déclaration par void

Distinguer le passage par adresse du passage par valeur

En C le passage des paramètres se fait toujours par valeur. La fonction appelante (dans notre exemple la fonction main) fait une copie de la valeur passée en paramètre (l’entier j) et passe cette copie à la fonction appelée (la fonction chg) à l’intérieur d’une variable créée momentanément dans l’espace mémoire.

(46)

Exemple:

#include <stdio.h>

void chg(int j ) { j++;

printf(«Paramètre incrémenté à : %d\n», j); // affiche 1 }

int main() { int j=0;

chg(j);

printf(«Paramètre non incrémenté : %d\n», j); // affiche 0 return 0;

}

→ Passage par adresse: Le langage C ne prévoit aucun mécanisme de passage par adresse.

Celui ci doit être programmé explicitement en utilisant comme argument un pointeur vers les variables. Attention: Ceci est valable pour les variables de type de base, de type pointeur, struct ou union. On verra le cas particulier des tableaux.

Comment utiliser un argument comme pointeur vers une variable?

Pour rappel (et par anticipation), un pointeur est une variable dont la valeur est l’adresse d’une autre variable. Passer un pointeur vers une variable comme argument, revient à donner à la fonction appelée l’adresse (et non la valeur) de la variable et ainsi la possibilité de pouvoir la modifier à souhait.

Opérateur d’adressage et de déréférencement: & et * si ad=&a; alors *ad retourne la valeur a

Exemple 1

Modification d’un paramètre

#include <stdio.h>

void chg(int *j ) { // passage par adresse de j

(47)

printf(«Paramètre incrémenté à : %d\n», *j); // affiche 1 }

int main() { int j=0;

chg(&j); // on donne l‘adresse de j à l‘appel printf(«Paramètre incrémenté : %d\n“, j); // affiche 1 return 0;

}

Exemple 2 : une fonction déjà utilisée et qui utilise le passage par adresse

scanf(“%d“, &i);

→ Cas des tableaux (le nom des tableaux sont déjà des adresses….)

Le nom d’un tableau d’éléments de type T est considéré comme ayant pour type « adresse d’un T » et pour valeur l’adresse du premier élément du tableau. Il n’est donc pas nécessaire pour les tableaux de faire un passage par adresse, puis que le nom des tableaux sont des adresses.

Dans la déclaration d’un argument formel t de type « tableau de T » : L’indication du nombre d’éléments de t est sans utilité

Les expressions type t[ ] et type *t sont tout à fait équivalentes

La fonction pourra être indifféremment appelée avec un tableau ou un pointeur pour argument effectif

int longueur( char s[80] );

int longueur( char s[ ] );

int longueur ( char *s) ;

peuvent toutes servir dans la définition ou la déclaration d’une fonction de calcul de longueur d’une chaine de caractères.

Exemple: char * s; scanf(“%s“, s);

(48)

Utiliser les arguments de la fonction main() int main(int argc,char *argv[])

Les noms argc et argv sont des noms mnémoniques. Ils signifient argument count et argument values. La fonction main() dispose donc toujours de paramètres passés par

l’environnement système. Parmi ces paramètres on a un entier et un tableau de pointeurs sur des caractères qui vont nous interesser.

argc : contient le nombre d’arguments qui ont été passés lors de l’appel du binaire exécutable (nombre de mots dans la ligne de commande inclus le nom du binaire) ; argv : contient les arguments de la ligne de commande au niveau du shell. Ces arguments sont découpés en chaine de caractères et constituent le tableau argv. Il y a toujours au moins un argument qui correspond au nom du binaire exécutable appelé ;

Exemple :

#include <stdio.h>

int main (int argc, char *argv[]) { int i;

printf(«Nous avons %d arguments : \n»,argc);

for(i=0; i<argc; i++)

printf(“argument %d == %s \n”, i, argv[i]);

return 0;

}

si on sauvegarde ce programme avec le nom exomain.c, l’execution en ligne de commande de la suite de terme : exomain essai passage parametres

provoquera le résultat suivant:

Nous avons 4 arguments : argument 0 == exomain argument 1 == essai argument 2 == passage

(49)

Ecrire un programme modulaire Enjeux d’une programmation modulaire

Nécessité de se fixer un certain nombre de règles d’écriture pour les programmes de taille importante destinés à être utilisés et maintenus par d’autres personnes.

Pour cela, il est nécessaire de fractionner le programme en plusieurs fichiers sources, que l’on compile séparément.

Trois principes essentiels doivent guider l’écriture d’un programme C:

La factorisation du code; une même portion de code à plusieurs endroits du programme n’est pas souhaitable. Utiliser systématiquement des fonctions. Il ne faut pas éviter de définir une multitude de fonctions de petite taille.

La fragmentation du code; découper un programme en plusieurs fichiers. De plus, cette règle permet de réutiliser facilement une partie du code pour d’autres applications.

Comment s’y prendre ?

Placer une partie du code dans un fichier en-tête (ayant l’extension .h) et l’inclure dans le fichier contenant le programme principal à l’aide de la directive #include»nomfichier.h». Par exemple, pour écrire un programme qui saisit deux entiers au clavier et affiche leur produit, on peut placer la fonction produit dans un fichier produit.h, et l’inclure dans le fichier main.c.

(50)

main.c

#include <stdlib.h>

#include <stdio.h>

#include “produit.h”

int main(void) { int a, b, c;

scanf(«%d»,&a);

scanf(«%d»,&b);

c = produit(a,b);

printf(«\nle produit vaut %d\n»,c);

return EXIT_SUCCESS;

}

produit.h

int produit(int, int);

int produit(int a, int b) { return(a * b);

}

Régles de compilation Unités de compilation

Un fichier .h n’est pas une unité de compilation

Un fichier .c est une unité de compilation qui inclut le fichier .h Règle de base

Compiler un module (le fichier .c) avant toute unité utilisatrice Modification du corps d’un module

Recompiler le fichier .c du module

Édition des liens sans recompiler les unités utilisatrices Modification de l’interface d’un module

Recompiler le fichier .c du module Recompiler toutes les unités utilisatrices

Un autre exemple d’organisation modulaire est présenté dans la figure suivante.

(51)

Il faut remarquer ici l’utilisation de trois fichiers au lieu de deux comme l’exemple précédent (où la définition et la déclaration de la fonction produit étaient dans le même fichier produit.h). Il est donc conseillé de séparer les définitions des déclarations et d’en faire deux fichiers séparés (tabio.h et tabio.c par exemple).

Conclusion

Voilà, vous connaissez maintenant les fonctions en C ainsi que la programmation modulaire.

N’hésitez plus à écrire vos programmes sous forme de fonctions même s’ils vous paraissent simples. Pour la programmation modulaire, les exercices viendront dans les chapitres suivants avec la découverte des structures de données plus complexes (tableaux, pointeurs, structures,

….). Les évaluations suivantes vont juste vous permettre de poser les bases d’utilisation des fonctions. Essayez de les coder tous pour vous faire une idée de leur exécution.

Évaluation

Ecrire une fonction qui reçoit en argument 2 nombres flottants et un caractère et fournit le résultat correspondant à l’une des 4 opérations appliquées à ses deux premiers arguments, en fonction de la valeur du dernier (addition avec ‘+’, soustraction avec ‘-‘, multiplication avec ‘*’, division avec ‘/’, tout autre sera considéré comme une addition). Utiliser ensuite cette fonction dans un main pour afficher le résultat de toutes les opérations entre deux flottants.

(52)

→ Qu’affiche le programme suivant :

# include <stdio.h>

void f1 ( int a , int * b ) { a = * b ; } void f2 ( int * b , int c ) { *b = c ; } void f3 ( int * a , int c ) { *a = c ; } int main ( ) {

int v1 , v2 , v3 ; v1 = 5 ; v2 = 8 ; v3 = 1 0 ;

printf(«Au départ : v1 = %d v2 = %d v3 = %d\n « , v1 , v2 , v3 ) ; f1(v1,&v2) ;

printf(«Apres f1 : v1 = %d v2 = %d v3 = %d\n « , v1 , v2 , v3 ) ; f2 (&v3,*(&v1)) ;

printf («Apres f2 : v1 = %d v2 = %d v3 = %d\n « , v1 , v2 , v3 ) ; f3 (&v3 ,v2) ;

printf(«Apres f3 : v1 = %d v2 = %d v3 = %d\n « , v1 , v2 , v3 ) ; }

→ Ecrire une fonction qui affiche la moyenne d’une suite d’entiers positifs entrés au clavier. On arrêtera la saisie quand le nombre -1 est entré, comme dans l’exemple suivant :

Entrez un entier positif : 5 Entrez un entier positif : 2 Entrez un entier positif : 3 Entrez un entier positif : -1

La moyenne de ces 3 entiers vaut 3.333333

RESUME DE L’UNITE

Vous venez de voir les instructions de contrôle pour gérer le cours d’execution d’un programme, ainsi que l’organisation en fonctions pour factoriser le code et permettre sa réutilisation. Vous avez maintenant tout ce qu’il faut pour démarrer un bon projet en langage C.

Les chapitres suivants viendront juste pour rajouter des structures de données à implémenter en plus (tableaux, pointeurs, structures, fichiers).

(53)

Ces structures permettront alors de modéliser des problèmes de plus en plus complexes.

Bonne continuation…

Évaluation de l’unité Vérifiez votre compréhension!

Devoir sur table 2 Directives

Répondre aux questions posées, l’évaluation dure 2h.

Système de notation

Le barème est indiqué à la suite des questions

Évaluation

Question 1 (3 pts)

Ecrire un programme qui calcule les solutions d’une équation du second degré, a X2 + b X +c = 0, où a, b et c sont trois entiers entrés au clavier.

Question 2 (5 pts)

On considère un texte formé de caractères composés uniquement de lettres et d’espaces. Ce texte est lu au clavier caractère par caractère et il se termine par le caractère ‘.’ . Un mot est une suite de lettres délimitée par des espaces ou par les extrémités du texte.

Ecrire un programme qui permet de saisir un texte caractère par caractère et qui affiche ensuite un message indiquant si le texte est un tautogramme, c’est-à-dire si tous les mots du texte commencent par la même lettre.

Exemple : le lion lape le lait lentement

NB : Les espaces superflus devront être éliminés.

(54)

Question 3 (4 pts)

Ecrire une fonction qui ne renvoie aucune valeur et qui détermine le chiffre le plus petit et le chiffre le plus grand d’un entier positif. Il faudra donc prévoir 3 arguments : l’entier positif, minchiffre, maxchiffre.

Question 4 (4 pts)

Une manière originale pour calculer le carré d’un nombre entier positif N est d’effectuer la somme des N premiers nombres impairs. Exemples : pour n = 4 ; 16 = 1 + 3 + 5 + 7 ;

pour n = 5 ; 25 = 1 + 3 + 5 + 7 + 9.

Définissez une fonction qui ne retourne rien et calcule le carré d’un nombre entier positif en utilisant la méthode ci-dessus.

Question 5 (4 pts)

Ecrire une fonction void ordreInverse() qui affiche à l’écran (sans utiliser de tableau) des entiers positifs lus au clavier dans l’ordre inverse où ils sont entrés. La suite sera terminée par une valeur négative.

Lectures et autres ressources

Les lectures et autres ressorces de cette unité se trouvent au niveau des lectures et autres ressources du cours.

(55)

Unité 3. Tableaux, pointeurs et chaînes de caractères, structures, unions et énumérations

Introduction à l’unité

Dans cette unité, vous découvrirez les types structurés en langage C. Il y sera beaucoup question de représenter et d’utiliser des données qui seront de type plus complexes que les types de base vus jusqu’ici.

Objectifs de l’unité

À la fin de cette unité, vous devriez être capable de:

• Écrire un programme avec des types composés

• Manipuler des tableaux

• Utiliser des pointeurs

• Effectuer une allocation de la mémoire

• Définir des structures dynamiques

TERMES DES

Types composés: De nouveaux types qui se définissent par composition, à partir des types de base (entier, réel, caractère)

Tableaux: Collection d’éléments de même type (avec des indices ordonnés pour retrouver les éléments facilement)

Pointeurs: Variable qui contient l’adresse de stockage d’une autre variable

Allocation: Procédé par lequel le programmeur réserve de l’espace en mémoire et récupère l’adresse de stockage.

(56)

Activités d’apprentissage Activité 1 – Tableaux et pointeurs

Introduction

Cette activité introduit les types tableaux et pointeurs, l’activité suivante reviendra sur leur équivalence. Ici, il sera question de les définir et de les utiliser séparément dans des programmes simples.

Détails de l’activité

Définir des tableaux et pointeurs

Les tableaux

Un tableau est un ensemble fini d’éléments de même type, stockés en mémoire à des adresses contiguës. La déclaration d’un tableau à une dimension se fait de la avec la syntaxe suivante :

type nom-tableau[nbr-ele];

Exemple: la déclaration int tab[10]; indique que tab est un tableau de 10 éléments de

type entier (int). (allocation en mémoire d’un espace de 10 × 4 octets consécutifs, l’espace est désigné pat tab).

Pour accéder à un élément du tableau on applique l’opérateur d’indexation [ ]. Ces éléments sont numérotés de 0 à nbt-ele - 1.

Initialisation des tableaux

On peut initialiser un tableau lors de sa déclaration par une liste de constantes de la façon

(57)

type nom-du-tableau[N] = {constante-1,constante-2,...,constante-N};

Si le nombre de données dans la liste d’initialisation est inférieur à la dimension du tableau, seuls les premiers éléments seront initialisés. Les autres éléments seront mis à zéro si le tableau est une variable globale ou une variable locale static.

Exemple : int t[10] = {9,8,7,6,5,4,3,2,1,0};

Initialisation par saisie manuelle des éléments

#define N 10

int main() { int t[N]; int i;

for (i = 0; i < N; i++) { printf(“ Donner t[%d] :”,i); scanf(“%d”,&t[i]);}

for (i = 0; i < N; i++) printf(“tab[%d] = %d\n”,i,t[i]);

return 0;}

le cas des tableaux de caractères

Un tableau de caractères peut aussi être initialisé par une liste de caractères, mais aussi par une constante chaîne de caractères. Dans ce cas, le compilateur complète toute la chaîne de caractères avec un caractère nul ‘\0’. Il faut donc prévoir un élément de plus que le nombre de caractères de la chaîne littérale.

#define N 8

char tab[N] = “exemple”;

int main() { int i;

for (i = 0; i < N; i++) printf(“tab[%d] = %c\n”,i, tab[i]);

return 0;

}

Tableaux à plusieurs dimensions

On peut aussi déclarer en C un tableau à plusieurs dimensions (ex: 2 dimensions).

type nom-du-tableau[nombre-lignes][nombre-colonnes]

(58)

En fait, un tableau à deux dimensions est un tableau unidimensionnel dont chaque élément est lui-même un tableau. On accède à un élément du tableau par l’expression ``tableau[i][j]’’.

Pour initialiser un tableau à plusieurs dimensions à la compilation, on utilise une liste dont chaque élément est une liste de constantes :

#define M 2

#define N 3

int tab[M][N] = {{1, 2, 3}, {4, 5, 6}};

int main() { int i, j;

for (i = 0 ; i < M; i++) {

for (j = 0; j < N; j++) printf(“tab[%d][%d]=%d\n”, i, j, tab[i][j]);

} }

Les pointeurs

Un pointeur est une variable dont la valeur est l’adresse d’une autre variable (cellule mémoire).

Déclaration et initialisation de pointeurs type * variable;

Exemple: char *pc; int *pi; float *pf;

pc, pi et pf contiennent des adresses de variables de type char, int et float.

L’opérateur unaire & permet d’obtenir l’adresse d’une variable int i, *pi; float f, *pf;

pi = &i; pf = &f;

Toute déclaration de variable occupe un certain espace dans la mémoire de l’ordinateur. La référence & permet de savoir où cet emplacement se trouve.

L’opérateur unaire d’indirection * permet d’accéder directement à la valeur de l’objet pointé.

Ainsi, si pi est un pointeur vers un entier i, *p désigne la valeur de i.

Références

Documents relatifs

Malgré que les valeurs des deux paramètres a et b ont été bien permutés dans la fonction echanger, on a modifié sur les copies de age1 et age2 et ces modifications ne sont

La syntaxe d’un langage de programmation d´etermine ce qui constitue un programme valide du point de vue de la forme/du texte.. Quelles s´equences de caract`eres constituent

Plutôt que de réécrire une suite d’instructions plusieurs fois dans un programme, il est plus commode de les ranger une seule fois dans un sous programme en mémoire et de l’appeler

On pourra se servir des nombreuses informations dans l’espace WEB consacré à QTCreator : http://www.siloged.fr/cours/QTCreator. 1/ Création du projet et des

 Pour l’intestin, le plateau de dépolarisation des OL de la longitudinale n’est jamais surchargé de potentiels rapides (contrairement à ce qui est vu pour l’estomac)

- return sert à sortir d’une méthode en renvoyant une valeur (du type déclaré pour le type retour dans la définition de la méthode) :. return i

Par exemple, le programme suivant permet de manipuler en mˆeme temps les deux champs de type unsigned int d’une structure en les identifiant `a un objet de type unsigned long

Comme je me forme ` a ce langage en mˆeme temps que je r´edige ce support, j’utilise ` a la fois le site du z´ero et mes propres exercices pour apprendre ce langage de