Cours generale pour debuter la programmation avec le langage C


Télécharger Cours generale pour debuter la programmation avec le langage C

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


Cours générale pour débuter la programmation avec le langage C

formation informatique

  1. GÉNÉRALITÉS SUR LE LANGAGE C

Dans ce chapitre, nous vous proposons une première approche d'un programme en langage C.

Nous dégagerons ensuite quelques règles générales concernant l'écriture d'un programme. Enfin, nous vous montrerons comment s'organise le développement d'un programme en vous rappelant ce que sont: l'édition, la compilation, l'édition de liens et l'exécution.

1.1 PRÉSENTATION PAR L'EXEMPLE DE QUELQUES INSTRUCTIONS DU LANGAGE C 1.1.1 Un exemple de programme en langage C Voici un premier exemple très simple de programme en langage C.

#includeint main(void)

{      int i ;

double x ;

i=0 ;

x=3.1415926535

printf(‘’Bonjour tout le monde \n‘’) ;

printf(‘’i vaut : %d et x vaut :%f’’,i,x) ;

return 0 ;

}

1.1.2 Structure d'un programme en langage C

La ligne: int main(void ) se nomme un "en-tête". Elle précise que ce qui sera décrit à sa suite est en fait le "programme principal" (int main). Lorsque nous aborderons l'écriture des fonctions en C, nous verrons que celles-ci possèdent également un tel en-tête; ainsi, en C, le programme principal apparaîtra en fait comme une fonction dont le nom (int main) est imposé.

Le programme (principal) proprement dit vient à la suite de cet en-tête. Il est délimité par les accolades "Ç" et "}". On dit que les instructions situées entre ces accolades forment un "bloc". Ainsi peut-on dire que la fonction main est constituée d'un en-tête et d'un bloc; il en ira de même pour toute fonction C. Notez qu'un bloc (comme en Pascal) peut lui-même contenir d'autres blocs. En revanche, nous verrons qu'une fonction ne peut jamais contenir d'autres fonctions (ce qui est le cas du Pascal).

1.1.3 Déclarations

Les deux instructions : int i; double x; sont des "déclarations".

La première précise que la variable nommée i est de type int, c'est-à-dire qu'elle est destinée à contenir des nombres entiers (relatifs). Nous verrons qu'en C il existe plusieurs types d'entiers.

L’autre déclaration précise que la variables x sont de type double c'est-à-dire qu'elles sont destinées à contenir des nombres flottants (approximation de nombres réels). Là encore, nous verrons qu'en C il existe plusieurs types flottants.

En C, comme en Pascal, les déclarations des types des variables sont obligatoires et doivent être regroupées au début du programme (on devrait plutôt dire: au début de la fonction main). Il en ira de même pour toutes les variables définies dans une fonction; on les appelle "variables locales" (en toute rigueur, les variables définies dans notre exemple sont des variables locales de la fonction main). Nous verrons également (dans le chapitre consacré aux fonctions) qu'on peut définir des variables en dehors de toute fonction; on parlera alors de variables globales.

1.1.4 Pour écrire des informations: la fonction printf

 L'instruction : printf ("Bonjour\n") ; appelle en fait une fonction "prédéfinie" (fournie avec le langage, et donc que vous n'avez pas à écrire vous-même) nommée printf. Ici, cette fonction reçoit un argument qui est : "Bonjour\n"

Les guillemets servent à délimiter une "chaîne de caractères" (suite de caractères). La notation \n est conventionnelle: elle représente un caractère de fin de ligne, c'est-à-dire un caractère qui, lorsqu'il est envoyé à l'écran, provoque le passage à la ligne suivante. Nous verrons que, de manière générale, le langage C prévoit une notation de ce type (\ suivi d'un caractère) pour un certain nombre de caractères dits "de contrôle", c'est-à-dire ne possédant pas de "graphisme" particulier.

Notez que, apparemment, bien que printf soit une fonction, nous n'utilisons pas sa valeur. Nous aurons l'occasion de revenir sur ce point, propre au langage C. Pour l'instant, admettez que nous pouvons, en C, utiliser une fonction comme ce que d'autres langages nomment une "procédure" ou un "sous-programme".

1.1.5 La fonction return

On la reverra plus tard, notez simplement qu’elle est obligatoire.

1.1.6 Les directives à destination du préprocesseur

La première ligne de notre programme : #include est en fait un peu particulière. Il s'agit d’une "directive" qui est prise en compte avant la traduction (compilation) du programme. Ces directives, contrairement au reste du programme, doivent être écrites à raison d'une par ligne et elles doivent obligatoirement commencer en début de ligne. Leur emplacement au sein du programme n'est soumis à aucune contrainte (mais une directive ne s'applique qu'à la partie du programme qui lui succède). D'une manière générale, il est préférable de les placer au début, comme nous l'avons fait ici.

La directive demande en fait d'introduire (avant compilation) des instructions (en langage C) situées dans le fichier stdio.h. Notez qu'un même fichier en-tête contient des déclarations relatives à plusieurs fonctions. En général, il est indispensable d'incorporer stdio.h.

1.2 QUELQUES RÈGLES D'ÉCRITURE

Ce paragraphe vous expose un certain nombre de règles générales intervenant dans l'écriture d'un programme en langage C. Nous y parlerons précisément de ce que l'on appelle les "identificateurs" et les "mots clés", du format libre dans lequel on écrit les instructions, de l'usage des séparateurs et des commentaires.

1.2.1 Les identificateurs

Les identificateurs servent à désigner les différents "objets" manipulés par le programme: variables, fonctions, etc Comme dans la plupart des langages, ils sont formés d'une suite de caractères choisis parmi les lettres ou les chiffres, le premier d'entre eux étant nécessairement une lettre.

1.2.2 Les mots clés

Certains "mots clés" sont réservés par le langage à un usage bien défini et ne peuvent pas être utilisés comme identificateurs. En voici la liste, classée par ordre alphabétique.

auto                        default                   float                      register                   struct                      volatile



break                      do                           for                         return                     switch                     while

case                        double                    goto                      short                       typedef

char                        else                         if                            signed                     union

const                      enum                      int                          sizeof                     unsigned

continue                extern                     long                       static                      void

1.2.3 Les séparateurs

Dans notre langue écrite, les différents mots sont séparés par un espace, un signe de ponctuation ou une fin de ligne. Il en va quasiment de même en langage C dans lequel les règles vont donc paraître naturelles. Ainsi, dans un programme, deux identificateurs successifs entre lesquels la syntaxe n'impose aucun signe particulier doivent impérativement être séparés soit par un espace, soit par une fin de ligne. Par contre, dès que la syntaxe impose un séparateur quelconque, il n'est alors pas nécessaire de prévoir d'espaces supplémentaires (bien qu'en pratique cela améliore la lisibilité du programme).

Ainsi, vous devrez impérativement écrire : int x,y et non : intx,y

En revanche, vous pourrez écrire indifféremment : int n,compte,total ou plus lisiblement : int n, compte, total formation informatique

1.2.4 Les commentaires

Comme tout langage évolué, le langage C autorise la présence de commentaires dans vos programmes source. Il s'agit de textes explicatifs destinés aux lecteurs du programme et qui n'ont aucune incidence sur sa compilation. Ils sont formés de caractères quelconques placés entre les symboles /* et */. Ils peuvent apparaître à tout endroit du programme où un espace est autorisé. En général, cependant, on se limitera à des emplacements propices à une bonne lisibilité du programme.

Voici quelques exemples de commentaires:

//             programme de calcul de racines carrées

/* commentaire s'étendant sur plusieurs lignes de programme source         */

1.3 CRÉATION D'UN PROGRAMME EN LANGAGE C

La manière de développer et d'utiliser un programme en langage C dépend naturellement de l’environnement de programmation dans lequel vous travaillez. Nous vous fournissons ici quelques indications générales (s'appliquant à n'importe quel environnement) concernant ce que l'on pourrait appeler les grandes étapes de la création d'un programme, à savoir: édition, compilation et édition de liens.

1.3.1 L'édition du programme

L'édition du programme (on dit aussi parfois "saisie") consiste à créer, à partir d'un clavier, tout ou partie du texte d'un programme: on parle alors de "programme source". En général, ce texte sera conservé dans un fichier que l'on nommera "fichier source".

1.3.2 La compilation

Elle consiste à traduire le programme source (ou le contenu d'un fichier source) en langage machine, en faisant appel à un programme nommé compilateur. En langage C, compte tenu de l'existence d'un préprocesseur, cette opération de compilation comporte en fait deux étapes.Le résultat de compilation porte le nom de module objet.

1.3.3 L'édition de liens

Le module objet créé par le compilateur n'est pas directement exécutable. Il lui manque, au moins, les différents modules objet correspondant aux fonctions prédéfinies (on dit aussi "fonctions standard") utilisées par votre programme (comme printf, scanf, sqrt).

C'est effectivement le rôle de l'éditeur de liens que d'aller rechercher dans la "bibliothèque standard" les modules objet nécessaires. Le résultat de l'édition de liens est ce que l'on nomme un "programme exécutable", c'est-à-dire un ensemble autonome d'instructions en langage machine. Si ce programme exécutable est rangé dans un fichier, il pourra ultérieurement être exécuté sans qu'il soit nécessaire de faire appel à un quelconque composant de l'environnement de programmation en C.

Exercice :

Ecrire un programme permettant d’afficher « bonjour » à l’écran.

  1. LES TYPES DE BASES DU LANGAGE C

Les types char, int et double que nous avons déjà rencontrés sont souvent dits "scalaires" ou "simples", car, à un instant donné, une variable d'un tel type contient une seule valeur. Ils s'opposent aux types "structurés" (on dit aussi "agrégés") qui correspondent à des variables qui, à un instant donné, contiennent plusieurs valeurs (de même type ou non).

2.1 LA NOTION DE TYPE

La mémoire centrale est un ensemble de "positions binaires" nommées bits. Les bits sont regroupés en octets (8 bits), et chaque octet est repéré par ce qu'on nomme son adresse.

L'ordinateur, compte tenu de sa technologie (actuelle !), ne sait représenter et traiter que des informations exprimées sous forme binaire. Toute information, quelle que soit sa nature, devra être codée sous cette forme. Dans ces conditions, on voit qu'il ne suffit pas de connaître le contenu d'un emplacement de la mémoire (d'un ou de plusieurs octets) pour être en mesure de lui attribuer une signification. Par exemple, si "vous" savez qu'un octet contient le "motif binaire" suivant : 01001101 vous pouvez considérer que cela représente le nombre entier 77 (puisque le motif ci-dessus correspond à la représentation en base 2 de ce nombre). Mais pourquoi cela représenterait-il un nombre? En effet, toutes les informations (nombres entiers, nombres réels, nombres complexes, caractères, instructions de programme en langage machine, graphiques...) devront, au bout du compte, être codées en binaire. Dans ces conditions, les huit bits ci-dessus peuvent peut-être représenter un caractère; dans ce cas, si nous connaissons la convention employée sur la machine concernée pour représenter les caractères, nous pouvons lui faire correspondre un caractère donné (par exemple M, dans le cas du code ASCII). On comprend donc qu'il n'est pas possible d'attribuer une signification à une information binaire tant que l'on ne connaît pas la manière dont elle a été codée. Qui plus est, en général, il ne sera même pas possible de "traiter" cette information. Par exemple, pour additionner deux informations, il faudra savoir quel codage a été employé afin de pouvoir mettre en œuvre les "bonnes" instructions (en langage machine).



D'une manière générale, la notion de type, telle qu'elle existe dans les langages évolués, sert à régler (entre autres choses) les problèmes que nous venons d'évoquer.

Les types de base du langage C se répartissent en trois grandes catégories en fonction de la nature des informations qu'ils permettent de représenter:

- nombres entiers (mot clé int),

- nombres flottants (mot clé double),

- caractères (mot clé char); nous verrons qu'en fait char apparaît (en C) comme un cas particulier de int.

2.2 LES TYPES ENTIERS

2.2.1 Leur représentation en mémoire

Le mot clé int correspond à la représentation de nombres entiers relatifs. Pour ce faire: un bit est réservé pour représenter le signe du nombre (en général 0 correspond à un nombre positif); les autres bits servent à représenter la valeur absolue du nombre.

2.2.2 Les différents types d'entiers

Le C prévoit que, sur une machine donnée, on puisse trouver jusqu'à trois "tailles" différentes d'entiers, désignées par les mots clés suivants:

- short

- int (c'est celui que nous utiliserons systématiquement), - long int .

 Chaque taille impose naturellement ses limites. Toutefois, ces dernières dépendent, non seulement du mot clé considéré, mais également de la machine utilisée: tous les int n'ont pas la même taille sur toutes les machines ! Fréquemment, deux des trois mots clés correspondent à une même taille (par exemple, sur PC, short et int correspondent à 16 bits, tandis que long correspond à 32 bits).

A titre indicatif, avec 16 bits, on représente des entiers s'étendant de -32 768 à 32 767; avec 32 bits, on peut couvrir les valeurs allant de -2 147 483 648 à 2 147 483 647.

Remarque: en toute rigueur, chacun des trois types (short, int et long) peut être nuancé par l'utilisation du "qualificatif" unsigned (non signé). Dans ce cas, il n'y a plus de bit réservé au signe et on ne représente plus que des nombres positifs. Son emploi est réservé à des situations particulières.

2.2.3 Notation des constantes entières

La façon la plus naturelle d'introduire une constante entière dans un programme est de l'écrire simplement sous forme décimale, avec ou sans signe, comme dans ces exemples: -533 ou 48...

2.3 LES TYPES FLOTTANTS

2.3.1 Les différents types et leur représentation en mémoire

Les types "flottants" permettent de représenter, de manière approchée, une partie des nombres réels. Pour ce faire, ils s'inspirent de la notation "scientifique" (ou "exponentielle") bien connue qui consiste à écrire un nombre sous la forme 1.5.1022 ou 0.472 .10-8; dans une telle notation, on nomme "mantisses" les quantités telles que 1.5 ou 0.472 et "exposants" les quantités telles que 22 ou -8.

Le C prévoit trois types de flottants correspondant à des tailles différentes: float, double (c’est celui que l’on emploie systématiquement) et long double.

La connaissance des caractéristiques exactes du système de codage n'est généralement pas indispensable. En revanche, il est important de noter que de telles représentations sont caractérisées par deux éléments:

- la précision: lors du codage d'un nombre décimal quelconque dans un type flottant, il est nécessaire de ne conserver qu'un nombre fini de bits. Or la plupart des nombres s'exprimant avec un nombre limité de décimales ne peuvent pas s'exprimer de façon exacte dans un tel codage. On est donc obligé de se limiter à une représentation approchée en faisant ce qu'on nomme une "erreur de troncature". Quelle que soit la machine utilisée, on est assuré que cette erreur (relative) ne dépassera pas 10-6 pour le type float et 10-10 pour le type long double.

- le domaine couvert, c'est-à-dire l'ensemble des nombres représentables à l'erreur de troncature près. Là encore, quelle que soit la machine utilisée, on est assuré qu'il s'étendra au moins de 10-37 à 10+37.

2.3.2 Notation des constantes flottantes

Comme dans la plupart des langages, les constantes flottantes peuvent s'écrire indifféremment suivant l'une des deux notations: décimale et exponentielle.La notation décimale doit comporter obligatoirement un point (correspondant à notre virgule). La partie entière ou la partie décimale peut être omise (mais, bien sûr, pas toutes les deux en même temps !). En voici quelques exemples corrects:

12.43 -0.38 -.38 4.                               .27

Par contre, la constante 47 serait considérée comme entière et non comme flottante. Dans la pratique, ce fait aura peu d'importance, compte tenu des conversions automatiques qui seront mises en place par le compilateur (et dont nous parlerons dans le chapitre suivant).

 La notation exponentielle utilise la lettre e (ou E) pour introduire un exposant entier (puissance de 10), avec ou sans signe. La mantisse peut être n'importe quel nombre décimal ou entier (le point peut être absent dès que l'on utilise un exposant). Voici quelques exemples corrects (les exemples d'une même ligne étant équivalents):

  1. 25E4 4 . 25e+4               42. 5E3

54.27E-32             542.7E-33            5427e-34

Par défaut, toutes les constantes sont créées par le compilateur dans le type double. 2.4 LES TYPES CARACTÈRES

2.4.1 La notion de caractère en langage C

Le C permet, comme le Pascal, de manipuler des caractères codés en mémoire sur un octet. Bien entendu, le code employé, ainsi que l'ensemble des caractères représentables, dépend de l'environnement de programmation utilisé (c'est-à-dire à la fois de la machine concernée et du compilateur employé). Néanmoins, on est toujours certain de disposer des lettres (majuscules et minuscules), des chiffres, des signes de ponctuation et des différents séparateurs (en fait, tous ceux que l'on emploie pour écrire un programme !). En revanche, les caractères "nationaux" (caractères accentués ou ç) ou les caractères "semi-graphiques" ne se rencontrent pas dans tous les environnements.

Par ailleurs, la notion de caractère en C dépasse celle de caractère imprimable, c'est-à-dire auquel est obligatoirement associé un graphisme (et qu'on peut donc imprimer ou afficher sur un écran). C'est ainsi qu'il existe certains "caractères" de changement de ligne, de tabulation, d'activation d'une alarme sonore (cloche),... Nous avons d'ailleurs déjà utilisé le premier (sous la forme \n).



2.4.2 Notation des constantes caractères

Les constantes de type "caractère", lorsqu'elles correspondent à des caractères imprimables, se notent de façon classique, en écrivant entre apostrophes (ou quotes) le caractère voulu, comme dans ces exemples :'Y', ‘+', '$' Certains caractères non imprimables possèdent une représentation conventionnelle utilisant le caractère " \caractères (\, ', " et ?) qui, bien que disposant d'un graphisme, jouent un rôle particulier de délimiteur qui les empêche d'être notés de manière classique entre deux apostrophes. Voici la liste de ces caractères.

Cours générale pour débuter la programmation avec le langage C

11 Les fonctions d'entrées-sorties classiques

Il s'agit des fonctions de la librairie standard stdio.h utilisées avec les unités classiques d'entrées-sorties, qui sont respectivement le clavier et l'écran. Sur certains compilateurs, l'appel à la librairie stdio.h par la directive au préprocesseur

#include <stdio.h>

n'est pas nécessaire pour utiliser printf et scanf.

11.1 La fonction d'écriture « printf »

La fonction printf est une fonction d'impression formatée, ce qui signifie que les données sont converties selon le format particulier choisi. Sa syntaxe est

 printf("chaîne de contrôle ",expression1, ..., expressionN);

La chaîne de contrôle contient le texte à afficher et les spécifications de format correspondant à chaque expression de la liste. Les spécifications de format ont pour but d'annoncer le format des données à visualiser.

Elles sont introduites par le caractère %, suivi d'un caractère désignant le format d'impression. Les formats d'impression en C sont donnés dans la table 1suivante.

En plus du caractère donnant le type des données, on peut éventuellement préciser certains paramètres du format d'impression, qui sont spécifiés entre le % et le caractère de conversion dans l'ordre suivant :

  • largeur minimale du champ d'impression : %10d spécifie qu'au moins 10 caractères seront réservés pour imprimer l'entier. Par défaut, la donnée sera cadrée à droite du champ. Le signe - avant le format signifie que la donnée sera cadrée à gauche du champ (%-10d).
  • précision : %.12f signifie qu'un flottant sera imprimé avec 12 chiffres après la virgule. De même %10.2f signifie que l'on réserve 12 caractères (incluant le caractère .) pour imprimer le flottant et que 2 d'entre eux sont destinés aux chiffres après la virgule. Lorsque la précision n'est pas spécifiée, elle correspond par défaut à 6 chiffres après la virgule. Pour une chaîne de caractères, la précision correspond au nombre de caractères imprimés : %30.4s signifie que l'on réserve un champ de 30 caractères pour imprimer la chaîne mais que seulement les 4 premiers caractères seront imprimés (suivis de 26 blancs).

La fonction de saisie « scanf »

La fonction scanf permet de saisir des données au clavier et de les stocker aux adresses spécifiées par les arguments de la fonctions.

 scanf("chaîne de contrôle",argument1,...,argumentN)

La chaîne de contrôle indique le format dans lequel les données lues sont converties. Elle ne contient pas d'autres caractères (notamment pas de \n).

Comme pour printf, les conversions de format sont spécifiées par un caractère précédé du signe %. Les formats valides pour la fonction scanf diffèrent légèrement de ceux de la fonction printf et sont donnés dans la table 2.

Les données à entrer au clavier doivent être séparées par des blancs ou des <RETURN> sauf s'il s'agit de caractères. On peut toutefois fixer le nombre de caractères de la donnée à lire. Par exemple %3s pour une chaîne de 3 caractères, %10d pour un entier qui s'étend sur 10 chiffres, signe inclus.

Exemple :

#include <stdio.h>

main()

{

 int i;

 printf("entrez un entier sous forme hexadecimale i = ");

11.3 Impression et lecture de caractères

Les fonctions getchar et putchar permettent respectivement de lire et d'imprimer des caractères. Il s'agit de fonctions d'entrées-sorties non formatées.

La fonction getchar retourne un int correspondant au caractère lu. Pour mettre le caractère lu dans une variable caractere, on écrit

 caractere = getchar();

Lorsqu'elle détecte la fin de fichier, elle retourne l'entier EOF (End Of File), valeur définie dans la librairie stdio.h. En général, la constante EOF vaut -1.

La fonction putchar écrit caractere sur la sortie standard :

 putchar(caractere);

Elle retourne un int correspondant à l'entier lu ou à la constante EOF en cas d'erreur.

Les types composés

A partir des types prédéfinis du C (caractères, entiers, flottants), on peut créer de nouveaux types, appelés types composés, qui permettent de représenter des ensembles de données organisées.

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 façon suivante : type nom-du-tableau[nombre-éléments]; où nombre-éléments est une expression constante entière positive. Par exemple, la déclaration int tab[10]; indique que tab est un tableau de 10 éléments de type int. Cette déclaration alloue donc en mémoire pour l'objet tab un espace de 10 × 4 octets consécutifs.


282