le c en 20h

Upload: amin-dvillas

Post on 07-Apr-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/6/2019 Le C en 20h

    1/177

  • 8/6/2019 Le C en 20h

    2/177

    Eric Berthomier, Daniel Schang

    Le C en 20 heures

    Ce livre et lillustration en couverture sont publies sous la licence libreCreative Commons-BY-SA :

    http ://creativecommons.org/licenses/by-sa/2.0/fr

    La collection Framabook est un projet Framasoft(http ://www.framasoft.net)

  • 8/6/2019 Le C en 20h

    3/177

    ii

    Immeuble ACCET

    4, place de la Pergola95021 Cergy-Pontoise Cedex

    Conception graphique de la couverture : Nadege Dauvergne

    Mise en page : La Poule ou lOeuf (http ://www.lescomplexes.com/)

    ISBN : 978-2-35922-030-8Depot legal : 2e semestre 2010

  • 8/6/2019 Le C en 20h

    4/177

    Avant de commencer

    Louvrage que vous tenez dans les mains ou que vous consultez sur votre cran a pour objectifde vous faire dcouvrir, par la pratique, la programmation en langage C.

    Il a t test par de nombreux tudiants qui navaient aucune connaissance pralable de celangage. En 20 30 heures de travail, ils sont tous parvenus au terme de leur apprentissage. Sivous ne connaissez encore rien la programmation et que vous dsirez apprendre, vous serez

    donc probablement trs intress(e) par le contenu de cet ouvrage : il est trs facile daccs etdestin aux grands dbutants.Il existe une multitude de faons de programmer un ordinateur, qui dpendent du matriel

    dont vous disposez, du systme dexploitation que vous utilisez et du langage de programmationque vous choisirez. Nous avons fait le choix dun systme dexploitation libre : Gnu/Linux et dulangage C, trs rpandu, largement enseign, et finalement assez simple dans ses constructions.Nanmoins, mme si vous nutilisez pas Gnu/Linux, vous pouvez sans risque vous lancer dansla lecture de cet ouvrage. Plus de quatre-vingt-quinze pour cent de ce vous y trouverez est

    utilisable sans modification avec dautres systmes dexploitation

    1

    .1. Les auteurs vous encouragent nanmoins trs vivement franchir le pas, et dans le cas o vous ne voudriez

    pas supprimer tout simplement votre vieux systme dexploitation, rien ne vous empche den avoir plusieurssur le mme ordinateur.

    1

  • 8/6/2019 Le C en 20h

    5/177

    2

    Ce livre nest pas un ouvrage de rfrence, que vous garderez sur une tagre pour vous yreporter en cas de doute ou doubli. Il a t crit pour tre lu dun bout lautre, dans lordre :il vous guidera dans votre apprentissage et vous suggrera de programmer telle chose, de testertelle autre. En ce sens, il est orient vers la pratique de la programmation et lenseigne sans doute la manire dont les auteurs lont apprise : devant un ordinateur, essayer de programmerquelque chose. Vous ne pourrez donc pas profiter pleinement de cet ouvrage sans essayer defaire les nombreux exercices quil contient. Et lorsque vous aurez fait ces exercices, vous pourrezcomparer vos solutions avec celles indiques la fin de chaque chapitre : vous apprendrez encrivant du code, et en lisant du code. Vous pourrez aussi travailler votre vitesse. Vous irezpeut tre vite au dbut et vous trouverez tout ceci trs facile. Il sera nanmoins ncessaire deprendre le temps de ne pas aller trop vite : cest pourquoi nous vous encourageons ne pas

    ncessairement faire des copier/coller du code, mais le saisir nouveau, afin de lassimiler, etaussi de commettre des erreurs que vous devrez ensuite corriger.

    Les premires briques de cet ouvrage ont pour origine un cours de Turbo Pascal 1 quricBerthomier dispensait au sein de lassociation Fac Info lUniversit de Poitiers. La seconderange de briques fut pose avec lassociation Les Mulots Chasseneuil du Poitou o Ericdonna des cours bnvoles de C sous Turbo C 2.0 et MS/DOS. Grce cette association, ricrencontra le GULP (Groupement des Utilisateurs de Linux de Poitiers) qui lui fit dcouvrirGnu/Linux : la troisime range de briques pouvait commencer. Accompagn par dautres

    membres duGulp

    , ric donna des cours de C au sein de cette association lEspace MendsFrance de Poitiers.

    Le contenu de louvrage alors disponible sous forme de fichiers Postscript a stagn quelquesannes avant dtre rcupr et adapt par Daniel Schang, qui la utilis et enrichi dune qua-trime range de briques dans un cadre plus acadmique lESEO dAngers.

    Il ne nous sera pas possible de dire combien de versions de ce cours ont exist mais l nestpas le plus important, ce qui compte cest que vous ayez maintenant ce livre entre les mains etceci grce lassociation FramaSoft.

    1. Dont quelques lignes directrices avaient elles mmes t dfinies par une autre personne.

  • 8/6/2019 Le C en 20h

    6/177

    Chapitre

    1

    Premiers pas

    1.1 Systme d'exploitation et C

    Pour pouvoir raliser des programmes en C, il est ncessaire de sappuyer sur un systmedexploitation. Le systme dexploitation utilis est ici Gnu/Linux. Nanmoins, la quasi-totalitde ce qui est dcrit ici peut tre ralis en utilisant dautres systmes dexploitation.

    Cet ouvrage nest pas une introduction lutilisation de Gnu/Linux. Nous nvoquerons donc

    que les outils ncessaires la programmation en C.

    1.2 Utiliser un diteur sous Gnu/Linux

    Nous allons dans cette section tenter de dfinir une manipulation pour lancer un diteur 1. Ilexiste une multitude dditeurs de texte qui permettent de saisir des programmes : Emacs (quejutilise en ce moment mme), Kate, Bluefish, Gedit

    Souvent, les diteurs sont accessibles quelque part dans un menu. En ce qui nous concerne,nous allons lancer lditeur de texte depuis la ligne de commande du shell. Pour cela, nous allons

    1. Un diteur est un programme (comme le bloc-notes de Windows) qui nous servira crire nos programmes.

    3

  • 8/6/2019 Le C en 20h

    7/177

    4 Premiers pas

    excuter un terminal. Selon la distribution que vous utilisez le terminal nest pas forcment rangau mme endroit. Voici quelques pistes qui pourront vous aider :

    sous Ubuntu, faites Applications / Accessoires / Terminal ; sous Xfce (et avec une Debian), faites clic droit, puis Terminal ; dans un autre environnement, recherchez quelque chose qui pourrait sappeler Terminal,

    Console ou Xterm.

    Dans cette nouvelle fentre qui ressemble celle de la figure 1.1, excutez lditeur Scite entapant la commande scite puis en validant. Lditeur doit souvrir (voir figure 1.2).

    Figure 1.1 - Une fentre de terminal

    Figure 1.2 - Une fentre de terminal et lditeur Scite

  • 8/6/2019 Le C en 20h

    8/177

    1.3 Exemple de programme 5

    Scite est un diteur trs simple dutilisation. Il est de plus disponible pour plusieurs systmesdexploitation, est lger, peut tre personnalis, offre la coloration syntaxique, permet de plier les fonctions

    Si en essayant de lancer la commande scite vous obtenez un message derreur comme :Commande inconnue ou Command not found, cest que Scite nest probablement pas installsur votre machine. Vous devrez alors regarder du ct des outils de gestion des paquetagespour ajouter ce logiciel (peut tre disposez-vous des outils de gestion des paquetages : Synaptic,Aptitude, Rpmdrake, Gurpmi, Yast ).

    1.3 Exemple de programme

    Voici un premier programme. Il est fonctionnel, mme sil nest pas normalis 1. Il affiche lemot Bonjour lcran. laide de votre diteur de texte (dans la fentre Scite donc), tapezle texte qui se trouve lintrieur du cadre suivant :

    main () {puts ("Bonjour");getchar ();

    }

    Puis, sauvegardez ce fichier (raccourci clavier : CTRL + S ) sous le nom suivant : pro-gramme1.c

    Une fois le texte du programme tap, il faut le compiler, cest dire le transformer en pro-gramme excutable (nous reviendrons sur la compilation plus tard). Nous allons donc ouvrirune seconde fentre dans laquelle nous allons compiler notre programme : comme tout lheurelancez un terminal (figure 1.1).

    La compilation se fait avec le compilateur gcc. Tapez dans cette nouvelle fentre 2 :

    gcc -o programme1 programme1.c

    De la mme faon que vous pourriez ne pas disposer de lditeur Scite, il se peut que vous nayezpas les outils de dveloppement. L aussi, selon votre distribution, recherchez loutil de gestiondes logiciels installs, et installez le compilateur Gcc. Il est probable que son installation induiselinstallation dautres outils de dveloppement ncessaires (la plupart des outils dinstallationde paquets grent les dpendances entre logiciels).

    Si vous navez pas fait derreur, la ligne prcdente ne provoquera aucun affichage (pas denouvelle, bonne nouvelle) La commande entre vient de crer un fichier nomm programme1.Vous pouvez le vrifier en tapant ls -l (attention, tapez bien s ) qui devrait vous renvoyerquelque chose du type :

    -rw-r-r- 1 dschang dschang 44 2008-10-14 11:10 programme1.c-rwxr-xr-x 1 dschang dschang 6525 2008-10-14 11:11 programme1

    1. Nous verrons par la suite quun programme crit en Langage C doit respecter certaines normes

    2. Il faut se placer dans le rpertoire contenant programme1.c. Vous pouvez consulter le contenu durpertoire courant en entrant la commande ls (la lettre pas le chiffre 1). Vous pouvez vous dplacer dans unrpertoire particulier en entrant cd .

  • 8/6/2019 Le C en 20h

    9/177

    6 Premiers pas

    En y regardant de plus prs, nous pouvons voir le fichier intitul programme1.c qui a tsauvegard 11h10 et qui contient 44 octets. En dessous se trouve le fichier programme1 quivient dtre cr et qui contient 6525 octets. Ce dernier fichier contient le code machine (codequi est comprhensible par la machine).

    Le fichier programme1 est un fichier excutable . Le fichier programme1.c est un fichiersource (source de tous les bonheurs de Gnu/Linux). Un fichier source dsigne un fichierquun tre humain peut comprendre par opposition un excutable que seule la machine arrive comprendre. Il ne reste plus qu excuter le programme :

    ./programme1

    La machine affichera alors Bonjour et attendra que vous appuyiez sur ENTREE .

    Nous reviendrons par la suite sur le fait quil faille taper ./programme1 et pas sim-plement programme1.

    Par ailleurs, vous avez pu constater que la fin des lignes se terminait par un ; saufla premire ligne (celle qui contient le mot main). Nous reviendrons l-dessus Disonspour linstant que cest un peu comme en franais o chaque phrase se termine par un. sauf le titre.

    1.4 Normalisation du programme

    Jusqu prsent, nous avons fait un peu dans le sale. Nous nous en rendrons compte endemandant au compilateur dtre plus bavard. Lancez la commande :

    gcc -o programme1 programme1.c -Wall

    Observez les insultes :

    programme1.c:5: warning: return-type defaults to `int'programme1.c: In function `main':programme1.c:6: warning: implicit declaration of function `puts'programme1.c:9: warning: control reaches end of non-void function

    Les remarques du compilateur vous paraissent peut-tre peu comprhensibles (voire offen-santes) et cest normal.

    Loption de compilation -Wall permet de dclencher la production de messages soulignanttoute technique autorise mais discutable , en deux mots : viter.

    Nous allons donc normaliser ce programme.Fondamentalement, le langage C nest quun nombre restreint dinstructions et un ensemble

    de bibliothques. Dans ces dernires, le compilateur trouve les fonctions et les applications quilui permettent de crer un programme excutable. Cest un peu ce que vous faites lorsque vousrecherchez dans une encyclopdie pour raliser un expos.

    Certaines bibliothques (les plus courantes) sont incluses par dfaut ce qui permet notreprogramme de se compiler 1.

    1. Pour tre exact, cest ldition de liens qui a ici le mrite de fonctionner.

  • 8/6/2019 Le C en 20h

    10/177

    1.5 Petit mot sur ce qu'est une bibliothque 7

    La fonction puts est stocke dans la bibliothque standard dentres-sorties, incluse par d-faut. Nanmoins, lutilisation dune bibliothque ncessite que nous informions le compilateurde notre souhait de lutiliser : il suffit dajouter #include en dbut de programme 1.

    Ainsi, puisque nous utilisons la fonction puts, qui est dans la librairie standarddentres/sorties, nous indiquerons en dbut de programme 2 : #include

    Un autre point corriger est lajout de la ligne return 0. Tout programme doitrenvoyer unevaleur de retour, tout la fin. Cette valeur de retour permet de savoir si le programme que lonexcute sest correctement termin. En gnral 0 signifie une terminaison sans erreur. Enfin, ilfaut transformer la ligne main () en int main(). Ce point sera dtaill par la suite lorsquenous parlerons des fonctions

    En rajoutant ces quelques correctifs nous obtenons donc :

    #include

    int main () {puts ("Bonjour");

    getchar (); /* Permet d'attendre la frappe d'une touche */return 0;

    }

    1.5 Petit mot sur ce qu'est une bibliothque

    linstar de ltudiant qui recherche dans des livres, nous pouvons dire que le .h reprsentelindex du livre et le .c le contenu du chapitre concern.

    Aprs avoir lu (et retenu) le contenu des fichiers .h inclus, si le compilateur rencontrelappel la fonction puts, il est en mesure de vrifier si la fonction figurait dans un desinclude. Si ce nest pas le cas, il mettra un avertissement.

    1.6 Un exemple de fichier en-tte

    Vous trouverez ci-dessous, un extrait du fichier en-tte stdio.h. On y retrouve notammentla dclaration de puts (en dernire ligne de lextrait) que nous venons de mentionner et ladclaration de printf que nous verrons dans les chapitres suivants. Cest assez compliqu ony jette juste un oeil, pas plus ;)

    /* Write formatted output to STREAM. */extern int fprintf __P ((FILE *__restrict __stream,

    __const char *__restrict __format, ...));/* Write formatted output to stdout. */extern int printf __P ((__const char *__restrict __format, ...));/* Write formatted output to S. */extern int sprintf __P ((char *__restrict __s,

    1. Le nom ajout ici nest pas exactement celui de la bibliothque, mais celui du fichier den-tte (lextension.h est mis pour le mot anglais header qui signifie en-tte) qui correspond la bibliothque.

    2. stdio vient de STanDard Input Output.

  • 8/6/2019 Le C en 20h

    11/177

    8 Premiers pas

    __const char *__restrict __format, ...));

    /* Write formatted output to S from argument list ARG. */

    extern int vfprintf __P ((FILE *__restrict __s,__const char *__restrict __format,_G_va_list __arg));

    /* Write formatted output to stdout from argument list ARG. */extern int vprintf __P ((__const char *__restrict __format,

    _G_va_list __arg));/* Write formatted output to S from argument list ARG. */extern int vsprintf __P ((char *__restrict __s,

    __const char *__restrict __format,_G_va_list __arg));

    /* Write a string, followed by a newline, to stdout. */extern int puts __P ((__const char *__s));

    1.7 Complments

    Explicitons notre programme,

    #include

    int main () {puts ("Bonjour");

    getchar (); /* Permet d'attendre la frappe d'une touche */return 0;

    }

    puts : permet dafficher du texte suivi dun retour la ligne. getchar : permet dattendre la frappe dune touche suivie dune validation par la touche

    ENTREE

    , ou un simple appui sur la toucheENTREE

    . /* Commentaire */ : met en commentaire tout le texte compris entre /* et */ 1. Ontrouvera aussi // qui permet de mettre le reste de la ligne courante en commentaire 2.

    Notre programme affiche donc Bonjour et attend que lon appuie sur la touche entre ou surune autre touche puis la touche entre.

    1.8 Squelette de programme

    On peut dfinir le squelette dun programme C de la faon suivante :

    /* Dclaration des fichiers d'enttes de bibliothques */

    int main () {/* Dclaration des variables (cf. chapitres suivants...) */

    /* Corps du programme */getchar(); /* Facultatif mais permet d'attendre l'appui d'une touche */

    1. Un commentaire est une portion de texte que le compilateur ignore mais qui peut aider la comprhensiondun lecteur humain.

    2. Cette dernire faon de noter les commentaires provient du C++, mais elle est supporte par la plupartdes compilateurs C.

  • 8/6/2019 Le C en 20h

    12/177

    1.9 Blocs 9

    return 0; /* Aucune erreur renvoye */}

    1.9 Blocs

    La partie de programme situe entre deux accolades est appele un bloc. On conseille deprendre lhabitude de faire une tabulation 1 aprs laccolade. Puis retirer cette tabulation auniveau de laccolade fermante du bloc. Ainsi, on obtient :

    int main () {TabulationTout le code est frapp cette hauteur

    }

    Retrait de la tabulationTout le texte est maintenant frapp cette hauteur.

    Cette mthode permet de contrler visuellement la fermeture des accolades et leurs corres-pondances 2.

    1.10 Commentaires

    Bien commenter un programme signifie quune personne ne connaissant pas votre code doitpouvoir le lire et le comprendre. Les commentaires sont indispensables dans tout bon pro-gramme. Ils peuvent tre placs nimporte quel endroit. Ils commencent par /* et se terminentpar */ :

    /* Commentaire */

    Comme nous lavons dj mentionn, vous trouverez aussi parfois des commentaires C++ :

    // Le reste de la ligne est un commentaire

    1.11 Exercice dapplication

    crivez un programme qui : affiche Salut toi, appuie sur une touche sil te plat ; attend lappui dune touche ; affiche : Merci davoir appuy sur une touche .Une fois que vous serez satisfait de votre solution, vous pourrez la comparer avec la solution

    qui apparat un peu plus loin.

    1. La touche de tabulation TAB est la touche du clavier gauche de la touche A . Cette touche sert dcaler le texte.

    2. Sous Scite, CTRL + E permet didentifier laccolade associe celle pointe.

  • 8/6/2019 Le C en 20h

    13/177

    10 Premiers pas

    Sous Linux, il est possible dviter de retaper chaque fois les commandes :

    Pour cela, il suffit dappuyer plusieurs fois sur la flche vers le haut , ce quifera rapparatre les dernires commandes valides. Les flches haut et bas permettent ainsi de circuler dans lhistorique des commandes entres.

    1.12 Corrig de lexercice du chapitre

    #include

    int main () {/* Affiche premier message */puts ("Salut toi, appuie sur une touche s'il te plat");

    getchar (); /* Attend la frappe d'une touche */

    /* Affiche le second message */puts ("Merci d'avoir appuy sur une touche");

    return 0;}

    1.13 retenir

    lissue de ce chapitre, il serait souhaitable de :

    Se souvenir que lditeur que lon utilise dans cet ouvrage sappelle Scite ;

    Connatre les fonctions puts et getchar qui apparaissent dans le programme suivant :#include

    int main () {puts ("Bonjour");getchar (); /* Permet d'attendre la frappe d'une touche */return 0;

    }

    Savoir compiler un code source de programme : gcc -o programme1 programme1.c Savoir excuter un programme : ./programme1

  • 8/6/2019 Le C en 20h

    14/177

    Chapitre

    2

    Variables (1re partie)

    Allez votre rythme, limportant est decomprendre

    2.1 Objectif

    Afin de stocker des valeurs, calculer, effectuer un traitement quelconque, il est ncessairedenregistrer de manire temporaire des donnes. Cet enregistrement ncessite la dclarationdun lieu de la mmoire qui servira ce stockage : une variable.

    2.2 Affichage : la fonction printf

    #include

    int main () {

    11

  • 8/6/2019 Le C en 20h

    15/177

    12 Variables (1re partie)

    /* Affiche Coucou c'est moi l'cran puis saute une ligne */printf ("Coucou c'est moi\n");

    return 0;}

    La fonction printf, tout comme puts vue prcdemment, permet dafficher une chane decaractres. Elle est cependant beaucoup plus puissante.

    La syntaxe de printf est trs complexe et pourrait elle seule faire lobjet dunchapitre, nous nen verrons donc que des applications au fur et mesure des besoins.

    2.3 Notion de variable

    Comme son nom lindique, une variable est quelque chose qui varie. Cest vrai mais ce nestpas suffisant. Une variable peut tre considre comme une bote dans laquelle on met desdonnes. Il est possible de lire le contenu de cette bote ou dcrire des donnes dans celle-ci.

    La manire la plus immdiate de lire le contenu dune variable est de simplement mentionner

    son nom.La faon la plus simple daffecter une valeur une variable est loprateur daffectation =.

    Essayer dutiliser une variable laquelle nous navons encore affect aucune valeur peutdonner nimporte quel rsultat (si on affiche le contenu dune variable non initialise parexemple, on pourra obtenir nimporte quelle valeur lcran).

    Affecter une valeur une variable ayant dj une valeur revient la modifier. En effet,une variable ne peut contenir quune seule chose la fois. Si vous mettez une secondedonne dans la variable, la prcdente est efface.

    2.4 Dclaration d'une variable

    La dclaration dune variable se fait en utilisant la syntaxe suivante :

    ;

    Comme le montre le programme qui suit, il ne faut pas mettre les < et > comme celaapparaissait dans ;.

    #include

    int main () {

    int i; /* dclare un entier de nom i */char c; /* dclare un caractre de nom c */}

  • 8/6/2019 Le C en 20h

    16/177

    2.5 Application : exemples 13

    2.5 Application : exemples

    Premier exemple, avec des variables du type entier

    Lisez le programme, ainsi que les explications associes.

    #include

    int main () {int i;/* i : variable de type entier */int j;/* j : variable de type entier */

    i=22;/* i vaut 22 */

    j=i;/* on recopie la valeur de i dans j *//* donc j vaut aussi 22 prsent */

    printf ("i vaut %d\n", i);/* Affiche la valeur de i */printf ("i+j vaut %d\n", i+j);/* Affiche la valeur de i+j */

    return 0;}

    printf ("i vaut %d\n", i); : %d signifie que lon attend une valeur entire etquil faut lafficher en dcimal (base 10). Le %d sera remplac par la valeur de i.Cette ligne provoquera donc laffichage suivant : i vaut 22

    printf ("i+j vaut %d\n", i+j); : dans ce cas, %d est remplac par la valeur delexpression i+j. Nous obtiendrons laffichage suivant : i+j vaut 44

    Lexcution complte de ce programme donne donc :

    i vaut 22

    i+j vaut 44

    Second exemple, avec des variables du type caractre

    nouveau, lisez le programme ainsi que les explications associes.

    #include

    int main () {char car; /* car: variable de type caractre */char f; /* f: variable de type caractre */

    car='E';f='e';

    printf("car=%c f=%c\n",car,f);

    return 0;}

    car='E' : nous mettons dans la variable car la valeur (le code Ascii) du caractreE.

  • 8/6/2019 Le C en 20h

    17/177

    14 Variables (1re partie)

    f='e' : nous mettons dans la variable f la valeur (le code Ascii) du caractre e.Notons au passage que, f=e signifierait affecter la valeur de la variable e (qui nexistepas) f. En oubliant les quotes (guillemets simples). nous aurions donc obtenu uneerreur de compilation (variable inexistante).

    Lexcution complte de ce programme affiche donc :

    car=E f=e

    En informatique, tout nest que nombre ; nous parlons donc de la valeur de E pluttque de E car cest le code Ascii du caractre E qui est affect la variable. Nousreviendrons sur ce point un peu plus tard.

    2.6 Utilisation de % dans printf

    lintrieur du premier paramtre dun printf (appel le format), lemploi de %x signifiequ lexcution, %x doit tre remplac par la valeur correspondante qui figure dans les para-mtres suivants, aprs transformation de ce paramtre dans le type puis le format dsign parx. Nous avons notre disposition plusieurs formats daffichage, comme : %d, %x

    Exemple :

    int i;i=65;printf ("Le caractre %d est %c",i,i);

    nous donnera laffichage suivant :Le caractre 65 est A

    le %d est remplac par la valeur numrique de i cest dire 65. le %c est remplac par la valeur alphanumrique (Ascii) de i cest dire le caractre A (cf.

    table Ascii en annexe). Cette table est trs utile car lordinateur ne comprend que desnombres. Elle donne une correspondance entre les lettres (que nous autres, tres humains,comprenons) et leur codage par la machine. En rsum, chaque fois que nous manipuleronsla lettre A, pour lordinateur, il sagira de la valeur numrique 65

    2.7 Exercices

    Dans les exercices qui suivent, vous devez utiliser ce que nous venons de voir sur les variables,les caractres, et sur printf.

    Exercice n2.1 Dclarer, afficher (a)

    Dclarez des variables avec les valeurs suivantes 70, 82, 185 et 30 puis affichez lecontenu de ces variables.

  • 8/6/2019 Le C en 20h

    18/177

    2.8 Rutilisation d'une variable 15

    Exercice n2.2 Dclarer, afficher (b)

    Faites la mme chose avec les caractres c, o, u, C, O, U.

    Une fois que vous avez votre propre solution, comparez avec celle qui se trouve la fin duchapitre

    2.8 Rutilisation d'une variable

    Il est possible de rutiliser une variable autant de fois que lon veut. La prcdente valeur

    tant alors efface :i = 3;

    i = 5;

    i = 7; Maintenant, i contient 7, les autres valeurs ont disparu.

    car = 'E';

    car = 'G';

    car = 'h'; La variable car contient maintenant le caractre 'h'.

    2.9 Caractres spciaux

    Certains caractres ( % par exemple) ncessitent dtre prcds par le caractre \ pourpouvoir tre affichs ou utiliss.

    Pour afficher un % avec printf, nous cririons :

    printf("La rduction tait de 20\%") ;

    Pour dsigner le caractre quote ' on crira :

    char car;car = '\'';

    En effet, le compilateur serait perdu avec une expression du type :

    char car;car = ''';

    Exercice n2.3 Erreur volontaire

    Essayez dcrire un programme contenant car=''' et constatez lerreur obtenue lacompilation.

  • 8/6/2019 Le C en 20h

    19/177

    16 Variables (1re partie)

    2.10 Exercices

    Exercice n2.4 Okay!

    Ralisez un programme qui permet dobtenir laffichage suivant :

    C

    '

    e

    s

    t

    Ok i vaut : 1

    Pour pouvoir utiliser un caractre rserv la syntaxe du C, on utilise le caractre \comme prfixe ce caractre (on dit que \ est un caractre dchappement).

    pour obtenir un ", on utilise donc \" pour obtenir un ', on utilise donc \'

    2.11 Corrigs des exercices du chapitreCorrig de lexercice n2.1 Dclarer, afficher (a)

    #include

    int main () {int i,a,b,c;i=70;

    a=82;b=185;

    c=30;

    printf ("i vaut %d.\n",i);printf ("a vaut %d.\n",a);

    printf ("b vaut %d.\n",b);printf ("c vaut %d.\n",c);

    return 0;}

    Corrig de lexercice n2.2 Dclarer, afficher (b)

    #include

    int main () {char a,b,c,d,e,f;a='c';

    b='o';c='u';d='C';

    e='O';f='U';

    printf ("a vaut %c.\n",a);

  • 8/6/2019 Le C en 20h

    20/177

    2.11 Corrigs des exercices du chapitre 17

    printf ("b vaut %c.\n",b);

    printf ("c vaut %c.\n",c);printf ("d vaut %c.\n",d);printf ("e vaut %c.\n",e);

    printf ("f vaut %c.\n",f);

    return 0;}

    Corrig de lexercice n2.3 Erreur volontaire

    #include

    int main () {char car;car='''; // erreur volontaire !!!return 0;

    }

    gcc -o essai essai.cessai.c:5:6: error: empty character constantessai.c: In function 'main':

    essai.c:5: error: missing terminating ' character

    essai.c:6: error: expected ';' before 'return'

    Corrig de lexercice n2.4 Okay!

    #include

    int main () {char car;int i;i = 1;

    car = 'C';

    printf ("\n%c",car);car = '\'';printf ("\n%c",car);

    car = 'e';printf ("\n%c",car);car = 's';

    printf ("\n%c",car);car = 't';printf ("\n%c",car);

    printf ("\nOk i vaut : %d\n",i);

    return 0;}

  • 8/6/2019 Le C en 20h

    21/177

    18 Variables (1re partie)

    2.12 retenir

    Exemples de types de variables :char permet de dfinir une variable de type caractre.

    int permet de dfinir une variable de type entier.

    Exemple de programme avec variables :

    #include

    int main () {char caractere;

    int entier;caractere = 'c';entier = 1;

    printf ("caractere vaut : %c\n",caractere);printf ("entier vaut : %d\n",entier);

    return 0;}

  • 8/6/2019 Le C en 20h

    22/177

    Chapitre

    3

    Variables (2e partie)

    3.1 Objectif

    Dans ce chapitre nous allons utiliser le langage C comme une simple calculatrice et faire desadditions, multiplications

    Nous allons voir quafin de pouvoir utiliser la bibliothque mathmatique du langage

    C (#include ), il est ncessaire dajouter au moment de la compilation 1 :-lm (lisez bien m) ; ce qui nous donne :

    gcc -o monprog monprog.c -lm

    1. Pour tre prcis, cest plutt ltape ddition de liens qui ncessite cette option, mais nous yreviendrons

    19

    20 Variables (2e partie)

  • 8/6/2019 Le C en 20h

    23/177

    20 Variables (2e partie)

    3.2 Exercice de mise en bouche

    Exercice n3.1 Introduction une calculatrice

    crivez un programme qui : crit Calculatrice : et saute 2 lignes crit Valeur de a : et saute 1 ligne attend lappui dune touche crit Valeur de b : et saute 1 ligne attend lappui dune touche crit Valeur de a + b :

    Normalement, vous naurez pas de soucis pour lcrire comparez ensuite avec lasolution en fin de chapitre

    Pas pas, nous allons maintenant raliser notre petit programme de calculatrice.

    3.3 Dclaration des variables

    Exercice n3.2 Somme

    Compltez le programme en :

    dclarant 2 variables a et b de type int (entier) ; assignant ces deux variables les valeurs 36 et 54 ; faisant afficher le rsultat de la somme de a+b (attention, ncrivez pas le rsultat90 dans votre programme !).

    Pour faire afficher le rsultat, il est possible dutiliser la fonction printf en utilisant une troi-sime variable. Mais pour rester plus concis, nous afficherons directement de la faon suivante :

    printf ("Valeur de a + b : %d",a+b) ;

    %d sera remplac par la valeur de lexpression a+b.

    3.4 Saisie des variables

    Si une calculatrice lectronique se limitait calculer la somme de deux nombres fixes, leboulier serait encore trs rpandu.

    Pour saisir une variable 1, il est possible dutiliser la fonction scanf. La fonction scanfsutilise de la faon suivante :

    scanf ("%d", &a); // saisie de la valeur a

    1. Par saisir , nous voulons dire que lordinateur va attendre que lutilisateur entre une valeur auclavier puis quil appuie sur la touche entre.

    3 4 Saisie des variables 21

  • 8/6/2019 Le C en 20h

    24/177

    3.4 Saisie des variables 21

    Comme pour printf, nous reconnaissons le %d pour la saisie dun nombre entier. Le & devantle a signifie que nous allons crire dans la variable a.

    Ae En fait &a signifie ladresse mmoire de a. La fonction scanf va donc crire danslemplacement mmoire (la petite bote contenant la variable) de a. Si nous oublions le &, nouscrirons chez quelquun dautre, une autre adresse. Et l a peut faire mal, trs mal Maisceci est une autre histoire sur laquelle nous reviendrons longuement par la suite Pour linstant,noubliez pas le &.

    Nous allons maintenant saisir les variables a et b. Pour exemple, voici le code pour la saisiede a, la saisie de b reste faire par vos soins titre dexercice.

    /* Saisie de la valeur de a */printf ("Valeur de a :\n");

    scanf ("%d", &a);

    Initialiser les variables

    Il est conseill dinitialiser les variables avant de les utiliser. Au dbut du programme, aprsleur dclaration, assignez la valeur 0 a et b.

    Une fois complt, compil, nous allons tester votre programme.

    Entrez une valeur pour a puis appuyez sur la touche ENTREE . Renouvelez ensuitelopration pour donner la valeur de b. Vrifiez que le rsultat est correct.

    Pour aller plus rapidement, il est possible dinitialiser une variable en mme tempsque nous la dclarons. Pour cela, rien de plus simple : ajoutez la fin de la dclarationle symbole daffectation = suivi de la valeur dinitialisation :

    int i = 10;

    Votre programme devrait ressembler ceci (lisez le programme puis la remarque importantequi se trouve en dessous) :

    #include #include

    int main () {

    int a=0;int b=0;

    printf("Calculatrice :\n\n");printf("Valeur de a : \n");

    scanf("%d",&a);printf("\n");printf("Valeur de b : \n");

    scanf("%d",&b);

    printf("\nValeur de a+b : %d\n",a+b); /* Affichage de la somme */

    getchar ();return 0;

    }

    22 Variables (2e partie)

  • 8/6/2019 Le C en 20h

    25/177

    22 Variables (2 partie)

    Vous pouvez tester ce programme et vous vous apercevrez que curieusement, le pro-gramme se finit alors que vous navez mme pas eu le temps dappuyer sur la touche

    ENTREE . Cest comme si le getchar() de la fin tait purement et simplement oubli ? !En fait, il sagit dune petite sournoiserie du Langage C ; en effet le scanf("%d",&b)attend que vous entriez une valeur au clavier.

    Pour fixer les ides, supposons que vous entriez la valeur 1234.

    La chose bien comprendre est que pour entrer cette valeur, vous appuyez galementsur la touche ENTREE . La subtilit tient au fait que le scanf("%d",&b) veut justeune valeur entire. Il laissera donc la valeur de la touche ENTREE disponible pour laprochaine instruction qui ira lire quelque chose au clavier (en fait, lappui sur la toucheENTREE reste disponible sur lentre standard) ; cest prcisment le getchar() qui vale rcuprer et qui permettra donc la sortie du programme.

    Ae ae ae, dur dur dtre programmeur.

    Notre ide simple de dpart commence se compliquer, et tout a pour faire quelques opra-tions basiques

    Exercice n3.3 Initialisation

    Dclarez une troisime valeur de type int (pensez linitialiser 0) que nous nom-merons simplement s comme somme. Une fois les valeurs de a et b saisies, initialisez savec la valeur de a+b. Affichez la valeur de s. Nous devrions avoir les mmes rsultatsquauparavant, bien sr.

    Exercice n3.4 Obtenir des rsultats

    Ralisez deux petits programmes qui font :

    la soustraction de deux nombres ; la multiplication de deux nombres.Une fois que vous avez votre solution, comparez avec la correction propose plus loin.

    3.5 Les types flottants

    Nous allons tudier un nouveau type de donnes : les nombres virgule flottante ou simplement

    flottants (float), qui permettent de reprsenter des nombres virgule. Le type float permetde dclarer un tel nombre. Transformez les trois programmes prcdents en utilisant le typefloat au lieu du type int. Enfin, si pour les int, nous utilisions le format %d au sein desprintf et des scanf, prsent, nous allons utiliser le format %f pour les flottants.

    Pour vous aider, voici un petit morceau de programme qui permet la saisie de la valeur de aet laffiche :

    float a;printf("Saisie de a :");scanf("%f",&a);

    printf("\n a vaut : %f\n",a);

    3.6 D'autres fonctions utiles 23

  • 8/6/2019 Le C en 20h

    26/177

    Pour un affichage plus agrable il est possible de fixer le nombre de chiffres aprs lavirgule de la faon suivante :

    %.[nombre de chiffres aprs la virgule]f

    Voici un exemple : printf ("%.2f",a);

    Exercice n3.5 Ouah, les 4 oprations !

    Crez un quatrime programme qui ralise la division de deux nombres. Vous pourrezvous amuser le tester avec une division par 0 ! La solution ce petit problme sera vu

    dans le chapitre sur les conditions (if).

    3.6 D'autres fonctions utiles

    La fonction abs permet dobtenir la valeur absolue dun nombre entier. La fonction fabsfpermet dobtenir la valeur absolue dun float.

    Notez que pour utiliser ces deux fonctions mathmatiques, il faut ajouter #include dans le source et ajouter loption -lm dans la commande de compilation.

    Exercice n3.6 Absolument !

    Utilisez cette dernire fonction pour calculer la valeur absolue de (a-b).

    Exercice n3.7 Arrondissez

    La fonctionceilf

    permet dobtenir larrondi entier suprieur dun flottant. Utilisezcette fonction pour calculer larrondi suprieur de (a/b).

    3.7 Corrigs des exercices du chapitre

    Corrig de lexercice n3.1 Introduction une calculatrice

    #include #include

    int main () {printf("Calculatrice :\n\n");

    printf("Valeur de a : \n");getchar();

    printf("Valeur de b : \n");getchar();

    printf("Valeur de a+b :\n");return 0;

    }

    24 Variables (2e partie)

  • 8/6/2019 Le C en 20h

    27/177

    ( )

    Corrig de lexercice n3.2 Somme

    #include #include

    int main () {int a,b;

    a=36;b=54;

    printf("Valeur de a+b : %d\n",a+b);

    getchar();return 0;

    }

    Corrig de lexercice n3.3 Initialisation

    #include #include

    int main () {int a,b;

    int s;

    a=0;b=0;

    printf("Calculatrice :\n\n");

    printf("Valeur de a : ");scanf("%d",&a);printf("\n");

    printf("Valeur de b : ");scanf("%d",&b);

    s=a+b;printf("Valeur de a+b : %d\n",s);

    getchar ();return 0;

    }

    Corrig de lexercice n3.4 Obtenir des rsultats

    ...int d;/* Rsultat de la diffrence */int m;/* Rsultat de la multiplication */

    d = a-b;printf("Valeur de a-b : %d\n", d);

    m = a*b;printf("Valeur de a*b : %d\n", m);

    ...

    3.7 Corrigs des exercices du chapitre 25

  • 8/6/2019 Le C en 20h

    28/177

    Corrig de lexercice n3.5 Ouah, les 4 oprations !

    ...int d;/* Rsultat de la division */

    d = a/b;printf("Valeur de a/b : %d\n", d);

    getchar ();...

    Corrig de lexercice n3.6 Absolument !

    Calculez la valeur absolue de a-bfloat r;...r=fabsf(a-b);

    printf("Valeur de r : %f\n",r);

    Corrig de lexercice n3.7 Arrondissez

    Calculez larrondi de a+b

    float arrondi;...

    arrondi=ceilf(a/b);/* Calcul de l'arrondi */printf("Valeur arrondie : %f\n",arrondi);

    Remarque : Il aurait t possible dutiliser %d du fait que larrondi est un nombreentier !

    26 Variables (2e partie)

  • 8/6/2019 Le C en 20h

    29/177

    3.8 retenir

    #include

    // ne pas oublier pour l'utilisation des fonctions mathmatiques#include

    int main () {float pi=3.14159;int i=10;// dclaration + initialisationint j;// dclaration seule (pas d'initialisation)

    // Attention, bien mettre %f et non pas %dprintf ("pi vaut environ: %f",pi);

    printf("\n i vaut:%d\n",i);

    printf("\n entrez une valeur:");scanf("%d",&j);// Attention ne pas oublier le &printf("\n vous venez d'entrer %d",j);

    return 0;}

    Nous compilerons ce programme comme ceci 1 : gcc -o programme1 programme1.c -lm Nous le lancerons comme ceci : ./programme1

    1. Mme si, en loccurence nous nutilisons pas de fonctions de la librairie mathmatique.

  • 8/6/2019 Le C en 20h

    30/177

    Chapitre

    4

    Conditions

    4.1 Objectif

    Dans ce chapitre, nous allons voir comment introduire des conditions dans nos programmes,de manire ce que selon les circonstances, telle ou telle partie du code soit excute.

    4.2 Exercice de mise en bouche

    crivez un programme qui met en application le thorme de Pythagore pour calculer lalongueur de lhypotnuse dun triangle rectangle.

    Rappelons que dans un triangle rectangle, la longueur de lhypotnuse (le plus grandct) peut se calculer en appliquant la formule suivante :

    Longueur hypotnuse =

    a2 + b2

    o a et b sont les longueurs des deux autres cts.

    27

    28 Conditions

  • 8/6/2019 Le C en 20h

    31/177

    La racine carre sobtient par lutilisation de la fonction sqrt(valeur) contenue dansla bibliothque de mathmatiques (#include )

    a2

    peut sobtenir par a*a.Exercice n4.1 Pythagore

    1. Recherchez les variables ncessaires et dclarez-les dans le programme.2. Faites saisir a au clavier.3. Faites saisir b au clavier.4. Appliquez la formule et affichez le rsultat.

    Rappelons que, afin de pouvoir utiliser la bibliothque mathmatique du C (#include), il est ncessaire dajouter au moment de la compilation -lm (un tiret, lalettre , la lettre m) ce qui nous donne :

    gcc -o monprog monprog.c -lm

    Une fois que vous tes satisfait(e) de votre solution, vous pourrez comparer avec la solutionqui se trouve la fin de ce chapitre.

    4.3 Condition : Si Alors Sinon

    En franais, nous pourrions dire quelque chose de ce type :

    si (je travaille)

    alors je progresseraisinon je stagnerai

    En se rapprochant un peu du Langage C, on traduirait (toujours en franais) ce premierprogramme ainsi :

    si (je travaille) {

    alors je progresserai}sinon {

    je stagnerai}

    Enfin, le programme en Langage C ressemblera ceci :

    if (je travaille) {je progresserai

    }else {je stagnerai

    }

    Les conditions sexpriment avec des oprateurs logiques dont nous allons expliquer tout desuite la signification et lutilisation.

    4.4 Oprateurs de comparaison 29

  • 8/6/2019 Le C en 20h

    32/177

    4.4 Oprateurs de comparaison

    Ils servent comparer deux nombres entre eux :

    Signification OprateurInfrieur gal ==

    Diffrent !=Infrieur ou gal =

    Table 4.1 - Oprateurs de comparaison

    Voici un exemple de programme qui demande lutilisateur de saisir deux valeurs puis affichela plus grande :

    #include

    int main () {

    int valeur1;int valeur2;

    /* Saisie de valeur1 */printf ("Entrez une 1ere valeur : ");scanf ("%d",&valeur1);

    /* Saisie de valeur2 */printf ("Entrez 2eme valeur : ");

    scanf ("%d",&valeur2);

    if (valeur1

  • 8/6/2019 Le C en 20h

    33/177

    4.5 Oprateurs logiques

    Les oprateurs logiques permettent de combiner des expressions logiques.

    Libell OprateurEt (and) &&Ou (or) ||

    Non (not) !

    Table 4.2 - Oprateurs logiques

    | se nomme en anglais un pipe (prononcer pape). Des exemples suivront bientt

    4.6 Vrai ou faux

    La valeur Vrai peut tre assimile la valeur numrique 1 ou toute valeur non nulle.

    La valeur Faux peut tre assimile la valeur numrique 0.

    Loprateur Ou (||) correspond alors une addition :

    Ou Vrai Faux + 1 0Vrai Vrai Vrai 1 2 1Faux Vrai Faux 0 1 0

    Table 4.3 - Loprateur ou

    Loprateur Et (&&) correspond alors une multiplication 1 :

    Et Vrai Faux * 1 0Vrai Vrai Faux 1 1 0Faux Faux Faux 0 0 0

    Table 4.4 - Loprateur et

    On notera que :

    !(Vrai) = Faux

    !(Faux) = Vrai

    1. Lanalogie entre les oprateurs logiques dune part et les oprations daddition et de multiplication dautre

    part nest pas parfaite. Elle permet nanmoins de se faire une ide plus calculatoire du fonctionnement desoprateurs logiques.

    4.7 Combinaison 31

  • 8/6/2019 Le C en 20h

    34/177

    Par exemple :

    int i1 =1;

    int i2 =0;printf("i1 || i2 = %d",i1||i2);

    /* affichera 1 car : vrai||faux=vrai et vrai vaut 1 */printf("i1 && i2 = %d",i1&&i2);

    /* affichera 0 car : vrai&&faux=faux et faux vaut 0 */

    printf("contraire(1)=%d",!(1));/* affichera 0 car : !(vrai)=faux et faux vaut 0 */

    4.7 CombinaisonToutes les oprations logiques peuvent se combiner entre elles. Il faut nanmoins veiller aux

    diffrentes priorits des oprateurs et il faut que la condition dans sa totalit soit entoure de().

    Les exemples suivants montrent ce qui est possible et ce qui ne lest pas :

    Correct

    Incorrect

    if (car == a)

    if car == a

    Correct

    Incorrect

    if ( car == a || car == A)

    if (car == a) || (car == A)

    Correct

    Incorrect

    if ((c == a || c == A) && (c2 == G))

    if (c == a || c == A) && (c2 == G)

    Table 4.5 - Oprateurs : formulations correctes et incorrectes

    Vous verrez souvent ce type de code crit :

    if (er) {/* Alors faire quelque chose */

    }

    En appliquant ce qui a t vu prcdemment, on en dduit que ce code signifie que

    si (er != 0) /* si er diffrent de 0 */{

    /* Alors faire quelque chose */

    }

    Ce qui donne en Langage C :

    32 Conditions

  • 8/6/2019 Le C en 20h

    35/177

    if (er != 0) { /* si er diffrent de 0 *//* Alors faire quelque chose */

    }

    Dans limmdiat, prfrez if (er!=0) if (er) ! ! !

    4.8 Accolades

    Les accolades entourant les blocs dinstructions dune condition peuvent tre omises si le blocnest constitu que dune seule instruction.

    Voici une version lourde :

    /* VERSION LOURDE : */if (car == 'b') {printf ("car vaut b.");

    }else {printf ("car est diffrent de b.");

    }

    Voici une version plus lgre :

    /* VERSION LEGERE : */if (car == 'b')printf ("car vaut b.");

    elseprintf ("car est diffrent de b.");

    Au contraire, dans lexemple ci-dessous, il faut imprativement mettre des accolades !

    if (car == 'b') { // il y a 2 instructions donc on met des { }printf ("car vaut ");// 1re instructionprintf(" %c",car);// 2me instruction

    }elseprintf ("car est diffrent de b.");

    4.9 ExercicesExercice n4.2 Variable positive, ngative ou nulle

    Faites saisir une variable de type entier et indiquez lutilisateur si celle-ci est stricte-ment positive, strictement ngative ou nulle. Votre code contiendra quelque chose commececi :

    if (a > 0)printf ("Valeur positive");

    elseprintf ("Valeur ngative");

    4.10 Corrections des exercices du chapitre 33

  • 8/6/2019 Le C en 20h

    36/177

    Exercice n4.3 Voyelles, consonnes

    Faites saisir une variable de type caractre et indiquez lutilisateur si celle-ci est unevoyelle ou une consonne. On considrera que le caractre saisi est en minuscule.

    Notez que si le caractre saisi est une lettre et nest pas une voyelle, cest ncessairementune consonne.

    4.10 Corrections des exercices du chapitre

    Corrig de lexercice n4.1 Pythagore

    #include #include

    int main () {float h; /* valeur de l'hypotnuse */float a; /* a,b les deux autres cts */float b;

    /* Initialisation des variables par prcaution */

    a = 0;b = 0;

    /* Saisie de a */

    printf ("Valeur du premier petit ct : ");scanf ("%f",&a);

    /* Saisie de b */printf ("Valeur du second petit ct : ");

    scanf ("%f",&b);

    /* Calcul de la longueur de l'hypotnuse */

    h = sqrt (a*a + b*b);

    /* Affichage du rsultat */

    printf ("L'hypotnuse mesure : %.2f\n",h);

    /* Attendre avant de sortir */

    getchar ();

    return 0;}

    Corrig de lexercice n4.2 Variable positive, ngative ou nulle

    #include

    int main () {/* Variable pour stocker la valeur saisie */int a = 0;

    /* Saisie de a */

    printf("Saisie de a : ");scanf("%d",&a);

    /* Strictement ngative ? */

    if (a < 0)printf("la variable a est ngative.\n");

    34 Conditions

  • 8/6/2019 Le C en 20h

    37/177

    else {/* Strictement positive ? */if (a > 0)printf("la variable a est positive\n");

    /* Sinon a est nulle */elseprintf("la variable a est nulle\n");

    }

    getchar ();return 0;

    }

    Corrig de lexercice n

    4.3 Voyelles, consonnes#include

    int main () {/* Variable pour stocker la valeur saisie */char car;

    /* Saisie du caractre a */printf("Saisie du caractre : ");scanf("%c",&car);

    /* Test condition car voyelle minuscule */if ((car == 'a') || (car == 'e') || (car == 'i') || (car == 'o') || (car

    =='u') || (car == 'y'))printf("la variable car est une voyelle.\n");

    elseprintf("la variable car est une consonne.\n");

    getchar ();return 0;

    }

    4.11 retenir La valeur Vrai peut tre assimile la valeur numrique 1 ou toute valeur non nulle. La valeur Faux peut tre assimile la valeur numrique 0. Ne pas oublier les parenthses lorsquil y a un if :

    if a > 0 // ne sera pas compil !!!

    printf ("Valeur positive");elseprintf ("Valeur ngative");

    au contraire, il faudrait crire :

    if (a > 0)printf ("Valeur positive");

    elseprintf ("Valeur ngative");

    Diffrencier loprateur daffectation = Et loprateur de comparaison ==.

  • 8/6/2019 Le C en 20h

    38/177

    Chapitre

    5

    Mise au point

    5.1 Objectif

    Lobjet de ce chapitre est de raliser une pause dans lapprentissage du C et de sattacher ce que lon est capable de raliser avec le peu de moyens que lon a.

    Ce chapitre est constitu de trois exercices de difficult croissante. Ils nous permettrontdapprendre utiliser une nouvelle fonction et de raliser un exercice complet de program-

    mation.

    5.2 Plus petit ou plus grand

    Exercice n5.1 Plus grand ou plus petit que

    Ralisez un programme qui saisit un nombre puis indique lutilisateur si ce nombreest plus grand ou plus petit quun autre nombre dfini lavance dans le programme.

    35

    36 Mise au point

  • 8/6/2019 Le C en 20h

    39/177

    Par exemple :

    si (nbre_saisi < 10)

    alors crire "plus petit"

    Vous pouvez reprendre lexercice du chapitre sur les conditions qui indiquait si unnombre est strictement positif, strictement ngatif ou nul.

    5.3 Retour sur getchar()

    La fonction getchar() permet dattendre la frappe dun caractre au clavier, de le lire et dele renvoyer. Deux utilisations peuvent donc tre faites de getchar(), la premire est celle permettant dattendre la frappe dune touche sans se soucier de sa

    valeur, simplement pour marquer une pause. la seconde est celle permettant de lire un caractre au clavier.

    getchar();

    char car;car = getchar();

    chaque fois, getchar() effectue le mme traitement : attendre la frappe dune touche au clavier suivie de la touche ENTREE

    renvoyer le caractre frapp.Dans le premier exemple, ce caractre est simplement ignor.

    5.4 Boucle : Faire Tant que (condition)

    do while (traduisez par Faire Tant que) permet de raliser une suite dinstructions tantquune ou plusieurs conditions sont remplies.

    1. lisez le programme suivant2. lisez les explications qui figurent en dessous du programme3. excutez, testez, comprenez ce programme

    #include

    int main () {char car=' ';

    int sortie=0;do {printf ("Appuyez sur S pour sortir !\n");

    5.4 Boucle : Faire Tant que (condition) 37

  • 8/6/2019 Le C en 20h

    40/177

    car = getchar ();

    /* On le compare pour savoir si l'on peut sortir: */sortie = ((car == 's') || (car == 'S'));

    }

    while (sortie==0);return 0;

    }

    Notez que la touche ENTREE utilise pour la saisie du caractre est elle-mme traitecomme un caractre entr et provoque donc aussi laffichage de la phrase Appuyez surS pour sortir qui saffiche donc deux fois.

    un nombre entier vaut la valeur logique vraie si ce nombre est diffrent de 0. un nombre entier vaut la valeur logique faux si ce nombre est gal 0. || est un ou logique , donc au niveau de la ligne :

    sortie=((car=='s')||(car=='S'));

    lorsque car vaudra 's' ou 'S', sortie vaudra 1 cest--dire Vrai. Dans tous lesautres cas, sortie vaudra 0, soit la valeur Faux.Ds lors, les deux extraits de programme suivants sont quivalents :

    sortie = ((car == 's') || (car == 'S'));

    if ((car == 's') || (car == 'S'))sortie=1;

    elsesortie=0;

    Pour stopper un programme qui boucle, il faut presser simultanment sur les touches CTRL+ C (break).

    Vous pouvez tester cette possibilit en excutant le programme suivant :

    #include int main () {

    int i=1;do {printf(" i=%d \n",i);

    i=i+1;}while (i>0); /* Test toujours vrai ! */return 0;

    }

    Exercice n5.2 Sortir de la boucle

    Transformez lexemple prcdent afin que lon sorte de la boucle uniquement quandlutilisateur a saisi le nombre 10.

    La saisie dun nombre ne se fait pas par getchar mais par scanf.

    38 Mise au point

    5 5 Oprateur modulo

  • 8/6/2019 Le C en 20h

    41/177

    5.5 Oprateur modulo

    Loprateur qui donne le reste de la division entire (oprateur modulo) est not % en C. Ainsi,10%2 vaut 0 car la division entire de 10 par 2 donne 5 et il ny a pas de reste. En revanche,10%3 vaut 1 car la division entire de 10 par 3 donne 3 et il reste 1.

    Par exemple :

    int z;z=10%2;printf("10 modulo 2=%d\n",z);

    z=10%3;printf("10 modulo 3=%d\n",z);

    va nous afficher :

    10 modulo 2=010 modulo 3=1

    5.6 Nombres pseudo-alatoires

    Voici un petit exemple de programme qui permet dobtenir des nombres pseudo-alatoiresentre 0 et 99 :

    #include #include // sert pour les fonctions srand et rand#include

    int main() {int nb_alea=0;

    /* Initialisation du gnrateur de nombresbase sur la date et l'heure */

    srand (time (NULL));

    nb_alea = rand() % 100;printf ("Nombre alatoire : %d\n",nb_alea);return 0;

    }

    srand (time (NULL)) permet dinitialiser le gnrateur de nombres pseudo-alatoire. Nous reviendrons sur ce point par la suite.

    rand() renvoie un nombre entier compris entre 0 et RAND MAX. rand()%100 est donc le reste de la division entire dun nombre pseudo-alatoire

    (ventuellement trs grand) par 100, cest dire un nombre compris entre 0 et 99

    #include

    #include

    int main() {

    5.7 Corrigs des exercices du chapitre 39

    /* i f i */

  • 8/6/2019 Le C en 20h

    42/177

    /* Pour notre information */

    printf ("RAND_MAX : %ld\n", RAND_MAX);

    return 0;

    }

    Exercice n5.3 Deviner un nombre

    En vous aidant de ce qui a t fait prcdemment, ralisez un petit jeu qui :

    1. Initialise un nombre entre 0 et 99.2. Tente de faire deviner ce nombre lutilisateur en lui indiquant si le nombre

    trouver est plus petit ou plus grand que sa proposition.

    Voici un exemple de dialogue avec lordinateur :

    Entrez votre nombre: 50

    Cest plus!

    Entrez votre nombre: 25

    Cest moins!

    ...

    Gagn!!!

    5.7 Corrigs des exercices du chapitreCorrig de lexercice n5.1 Plus grand ou plus petit que

    #include

    int main () {int nb_choisi = 33;int nb_saisi = 0;

    printf ("Votre nombre : ");

    scanf ("%d",&nb_saisi);

    if (nb_choisi < nb_saisi)printf ("Mon nombre est plus petit.\n");

    else {if (nb_choisi == nb_saisi)printf ("C'est exactement mon nombre.\n");

    elseprintf ("Mon nombre est plus grand.\n");

    }

    return 0;}

    40 Mise au point

    Corrig de lexercice n5 2 Sortir de la boucle

  • 8/6/2019 Le C en 20h

    43/177

    Corrig de lexercice n5.2 Sortir de la boucle

    #include #include

    int main () {int valeur=0;

    do {printf ("Votre nombre : ");scanf ("%d",&valeur);

    }while (valeur != 10);

    return 0;

    }

    Corrig de lexercice n5.3 Deviner un nombre

    #include #include /* pour les valeurs alatoires */#include

    int main () {int nb_hasard = 0;

    int votre_nb = 0;

    srand (time (NULL));nb_hasard = rand () % 100 ;/* Nombre entre 0 et 100 */

    do {printf("Votre nombre : ");scanf("%d",&votre_nb);

    if (nb_hasard < votre_nb)printf ("\nMon nombre est plus petit\n");

    else {if (nb_hasard > votre_nb)printf ("\nVotre nombre est plus grand\n");

    }}while (votre_nb != nb_hasard);

    printf ("Trouv\n");

    return 0;}

    Chapitre

  • 8/6/2019 Le C en 20h

    44/177

    Chapitre

    6

    Et les Shadoks pompaient : je

    pompe donc je suis

    Les Shadoks est une srie tlvise danimation franaise en 208 pisodes de 2 3 minutes,cre par Jacques Rouxel, produite par la socit AAA (Animation Art-graphique Audiovisuel)et diffuse entre le 29 avril 1968 et 1973 (trois premires saisons) et partir de janvier 2000(quatrime saison) sur Canal+ et rediffuse sur Cartoon Network

    6.1 Objectifs

    Vous trouverez beaucoup dexercices dans ce chapitre o plusieurs petites aides de program-mation seront donnes notamment en ce qui concerne lincrmentation et la dcrmentationdune variable.

    41

    42 Et les Shadoks pompaient : je pompe donc je suis

    6.2 Boucle While

  • 8/6/2019 Le C en 20h

    45/177

    6.2 Boucle While

    De la mme faon que :

    do {} while(condition);

    il est possible dutiliser :

    while(condition) {}

    char car = ' ';while ((car != 's') && (car != 'S')) {car = getchar ();

    }

    Donne seule, la ligne : while(condition); signifie que tant que condition est vraie,on revient la mme ligne.

    Si la condition est toujours vraie, on tombe alors dans un puits (le programme restebloqu). Sinon, on passe immdiatement la ligne/instruction suivante.

    6.3 Et les Shadoks apprenaient que reprendre quivaut ap-prendre

    Ce nest quen essayant continuellement que lon finit par russir En dautres termes Plusa rate et plus on a de chances que a marche (http ://www.lesshadoks.com).

    Exercice n6.1 Touche-touche

    Traduisez en langage C, compltez avec les variables ncessaires, compilez, excutez,comprenez :

    FaireSaisir une touche

    Tant Que (touche != S) et (touche != s)

    Exercice n6.2 Saisir un nombre

    Traduisez en langage C, compltez avec les variables ncessaires, compilez, excutez,comprenez :

    FaireSaisir un nombre

    Tant Que (nombre != 10)

    Notez que la saisie dun nombre ne se fait pas par la fonction getchar() mais par la

    fonction scanf (reportez-vous la section 3.4 pour plus de prcisions).

    6.4 Fonction toupper() 43

    6.4 Fonction toupper()

    http://www.lesshadoks.com/
  • 8/6/2019 Le C en 20h

    46/177

    pp ()

    Le problme de la comparaison de la minuscule et de la majuscule de lexercice 1 peut tre

    contourn par lutilisation de la fonction toupper qui transforme un caractre minuscule enmajuscule. Pour lutiliser, il faut inclure le fichier den-tte ctype.h par : #include .

    La fonction toupper sutilise de la faon suivante :

    #include #include

    int main () {char car;char car_min;

    car_min = 'a';car = toupper (car_min);

    printf ("%c",car);

    return 0;}

    Ce programme affichera : A

    6.5 tant qu'en emporte le Shadok

    Exercice n6.3 Recommencez ! (a)

    crivez le programme : Tant que je ne tape pas un nombre impair compris entre 1 et10 je recommence la saisie dun nombre.

    Exercice n6.4 Recommencez ! (b)

    crivez le programme : Tant que je ne tape pas une voyelle je recommence la saisiedune touche.

    6.6 Et les Shadoks continuaient pomper pour obtenir le rsultat

    Dans les exercices qui suivent, la notion de compteur intervient. Un compteur est une variablenumrique que lon dcrmente (-1) ou incrmente (+1) suivant nos besoins.

    Par exemple :

    int i;i=1;

    i=i+1;

    printf("i vaut: %d",i); // affichera 2

    En effet, lorsque nous crivons i=1, lordinateur range la valeur 1 dans la case mmoire dsi-gne par i. Lorsque nous demandons : i=i+1, lordinateur commence par prendre connaissance

    44 Et les Shadoks pompaient : je pompe donc je suis

    de la valeur de i en mmoire (ici 1) et lui ajoute 1. Le rsultat est stock dans la case mmoire

  • 8/6/2019 Le C en 20h

    47/177

    associe i. Finalement, i vaudra 2.

    Pour gagner du temps, le langage C nous permet de remplacer une expression comme : i=i+1

    par lexpression suivante : i++ qui fera exactement la mme chose.

    int i;

    i++; /* Incrmente le compteur i */i--; /* Dcrmente le compteur i */

    Dans les exemples prcdents, le nombre de caractres entrs peut donc tre comptabilis enajoutant 1 une variable chaque fois quune touche est frappe.

    Exercice n6.5 Recommencez ! (c)

    crivez le programme : Tant que je nai pas saisi 10 nombres, je recommence la saisiedun nombre.

    Exercice n6.6 Recommencez ! (d)

    crivez le programme : Tant que je nai pas saisi 10 caractres, je recommence la saisie

    dun caractre.

    Dans les exercices qui prcdent, de petites difficults peuvent surgir Nous vous invitonsdonc vous pencher plus rapidement sur la solution.

    6.7 Dans le clan des Shadoks, on trie, voyelles, chiffres premiers

    Exercice n

    6.7 Recommencez ! (e)crivez le programme : Tant que je nai pas saisi 10 voyelles, je recommence la saisie

    dune touche. Vous prendrez soin dindiquer lutilisateur combien de voyelles il lui reste entrer.

    Exercice n6.8 Recommencez ! (f)

    crivez le programme : Tant que je nai pas saisi 10 chiffres premiers (2,3,5 ou 7), jerecommence la saisie dun chiffre. Vous prendrez soin dindiquer lutilisateur combien

    de chiffres premiers il lui reste entrer.

    6.8 Incrmentations, pr-incrmentations

    Nous avons vu quincrmenter dsignait la mme chose quaugmenter la valeur dune variablede 1 :

    i++;

    i=i+1;

    Il y a cependant une nuance subtile.

    6.8 Incrmentations, pr-incrmentations 45

    x=i++ Copie dabord la valeur de i dans x et incrmente i aprsi Copie dabord la aleur de i dans et dcrmente i aprs

  • 8/6/2019 Le C en 20h

    48/177

    x=i-- Copie dabord la valeur de i dans x et dcrmente i aprsx=++i Incrmente i dabord puis copie le contenu de i dans xx=--i Dcrmente i dabord puis copie le contenu de i dans x

    Table 6.1 - Incrmentation / Dcrmentation

    Pour bien comprendre, tudions le programme suivant :

    #include

    int main () {int n=5;int x;

    x=n++;

    printf ("x: %d n: %d\n",x,n);

    return 0;}

    Celui-ci retourne le rsultat suivant :

    x: 5 n: 6

    Analysons ce qui se passe lors de lapplication de la ligne (x=n++) :

    1. on affecte n x, donc x va contenir la valeur 52. on augmente n de 1, donc n vaudra 6

    On parlera dans ce cas dincrmentation post-fixe

    Voici un autre exemple :#include

    int main () {int n=5;

    int x=0;

    x=++n;

    printf ("x: %d n: %d\n",x,n);

    return 0;

    }

    Celui-ci retourne le rsultat suivant :

    x: 6 n: 6

    Analysons ce qui se passe lors de lapplication de la ligne(x=++n) :

    1. on augmente n de 1, donc n vaudra 6

    2. on affecte n x, donc x va contenir la valeur 6

    On parlera dans ce cas dincrmentation pr-fixe

    46 Et les Shadoks pompaient : je pompe donc je suis

    6.9 Corrigs des exercices du chapitre

  • 8/6/2019 Le C en 20h

    49/177

    Corrig de lexercice n6.1 Touche-touche

    #include

    int main () {char car = '\0';printf("Tapez 's' ou 'S' pour arrter ...\n");do {car = getchar ();

    }while ((car != 's') && (car != 'S'));return 0;

    }

    Corrig de lexercice n6.2 Saisir un nombre

    #include

    int main () {int nbre = 0;printf("Tapez 10 pour arrter ...\n");do {scanf ("%d", &nbre);

    }while (nbre != 10);return 0;}

    Corrig de lexercice n6.3 Recommencez ! (a)

    #include

    int main () {int nbre = 0;

    printf("Tapez un chiffre impair pour arrter ...\n");while ((nbre!=1) && (nbre!=3) && (nbre!=5) && (nbre!=7) && (nbre!=9))scanf("%d", &nbre);

    return 0;}

    ou bien :

    #include

    int main () {int nbre = 0;

    printf("Tapez un chiffre impair pour arrter ...\n");while ((nbre < 0) || (nbre >= 10) || (nbre%2==0))scanf("%d", &nbre);

    return 0;}

    6.9 Corrigs des exercices du chapitre 47

    Corrig de lexercice n6.4 Recommencez ! (b)

  • 8/6/2019 Le C en 20h

    50/177

    #include #include

    int main () {char car = '\0';

    printf("Tapez une voyelle pour arrter ...\n");

    while ((car != 'A') && (car != 'E') && (car != 'I') &&(car != 'O') && (car != 'U') && (car != 'Y')){

    car = getchar ();

    car = toupper (car);}return 0;

    }

    Corrig de lexercice n6.5 Recommencez ! (c) [Il conviendrait dans cet exercice devrifier que lutilisateur a bien entr uniquement des nombres et pas aussi des caractres.Le lecteur intress pourra consulter la documentation de scanf et essayer dutiliser lavaleur que renvoie cette fonction pour rgler ce problme.]

    #include

    int main () {int nbre = 0;int nb_nbre = 0;

    printf("Tapez 10 nombres pour arrter ...");

    do {scanf("%d",&nbre);

    nb_nbre ++;

    }while (nb_nbre != 10);

    return 0;}

    Corrig de lexercice n6.6 Recommencez ! (d)

    Prenez soin de lire lexemple dexcution et son explication :

    #include

    int main () {char car = '\0';int nbre = 0;

    printf("Tapez 10 caractres pour arrter ...");

    do {car = getchar ();

    nbre ++;printf("j'ai lu (%c) nbre=%d\n",car,nbre);

    }while (nbre != 10);

    48 Et les Shadoks pompaient : je pompe donc je suis

    return 0;

  • 8/6/2019 Le C en 20h

    51/177

    }

    Voici un exemple dexcution :Tapez 10 caractres pour arrter ... 123456789j'ai lu (1) nbre=1j'ai lu (2) nbre=2

    j'ai lu (3) nbre=3j'ai lu (4) nbre=4j'ai lu (5) nbre=5

    j'ai lu (6) nbre=6j'ai lu (7) nbre=7j'ai lu (8) nbre=8

    j'ai lu (9) nbre=9j'ai lu () nbre=10

    Lutilisateur a donc tap 123456789 suivi de la touche entre, il a donc bien tap 10caractres. Ce que montre laffichage de la dernire ligne avec la parenthse ouvrantesur une ligne et la parenthse fermante sur la ligne suivante.

    Vous pouvez faire dautres essais

    Corrig de lexercice n6.7 Recommencez ! (e)#include #include

    int main () {char car;int nb_nbre = 10;

    printf("Tapez encore %d voyelles pour arrter...\n",nb_nbre);do {car=getchar();

    car=toupper(car);if (car=='A' || car=='E' || car=='I' || car=='O' || car=='U') {nb_nbre--;

    printf("Tapez encore %d voyelles pour arrter...\n",nb_nbre);}

    }while (nb_nbre != 0);

    return 0;

    }

    Corrig de lexercice n6.8 Recommencez ! (f)

    #include #include

    int main () {int nb_nbre = 10;

    int nbre;

    printf("Tapez encore %d chiffres premiers...\n",nb_nbre);

    6.10 retenir 49

    do {scanf("%d",&nbre);

  • 8/6/2019 Le C en 20h

    52/177

    if (nbre==2 || nbre==3 || nbre==5 || nbre==7) {nb_nbre--;

    printf("Tapez encore %d chiffre(s) premier(s) pour arrter...\n", nb_nbre);

    }

    }while (nb_nbre != 0);

    return 0;}

    6.10 retenirVoici un exemple de programme qui rsume ce qui a t vu dans ce chapitre. Ce programme

    doit afficher lcran tous les nombres pairs infrieurs 100 :

    #include

    int main () {int i = 0;while ( i!=100) {

    if (i%2==0) /* reste de la division de i par 2 */printf("%d ",i);

    /* pas de else ni de {} ici, c'est inutile...*/

    i++;}return 0;

    }

    Voici une autre version (meilleure) :

    #include

    int main () {int i = 0;while ( i!=100) {printf("%d ",i);

    i+=2;}return 0;

    }

    Enfin, noubliez pas le tableau :

    x=i++ Copie dabord la valeur de i dans x et incrmente i aprsx=i-- Copie dabord la valeur de i dans x et dcrmente i aprsx=++i Incrmente i dabord puis copie le contenu de i dans xx=--i Dcrmente i dabord puis copie le contenu de i dans x

    Table 6.2 - Incrmentation / Dcrmentation (bis)

  • 8/6/2019 Le C en 20h

    53/177

    Chapitre

  • 8/6/2019 Le C en 20h

    54/177

    7

    Boucles

    7.1 Et les Shadoks pdalrent pendant 15 tours

    Afin deffectuer un certain nombre de fois une tche, nous utilisons linstruction for de lafaon suivante (avec i, une variable de type entier (int par exemple)) :

    for (i=point de dpart; i

  • 8/6/2019 Le C en 20h

    55/177

    }

    signifie que lon va excuter instr pour i variant de 0 14 inclus (

  • 8/6/2019 Le C en 20h

    56/177

    #include int main () {

    int i;int j;for (i=0; i0; j--)printf("Je suis dans la boucle j, j vaut %d\n",j);

    }

    return 0;}

    Exercice n7.1 toiles

    En utilisant une double boucle, crire un programme qui affiche une toile, passe laligne, affiche deux toiles, passe la ligne, affiche trois toiles jusqu cinq toiles afindobtenir ceci :

    *

    *****

    ****

    *****

    7.4 Et les Shadoks ftrent Nol

    7.4.1 Affichage des ramures du sapin

    Exercice n7.2 Sapin

    laide dune double boucle, ralisez un cne pour dessiner le haut du sapin sur 10lignes.

    Vous devriez obtenir ceci :

    *

    ***

    *****

    *******

    *********

    ***********

    *************

    ***************

    *****************

    *******************

    54 Boucles

    Instructions :

    sur la ligne no 1, afficher 9 espaces puis 1 toile ;l li ffi h i il

  • 8/6/2019 Le C en 20h

    57/177

    sur la ligne no 2, afficher 8 espaces puis 3 toiles ;

    sur la ligne no

    3, afficher 7 espaces puis 5 toiles ; sur la ligne no i, afficher 10-i espaces puis 2*i-1 toiles.

    Nous obtenons donc par exemple pour laffichage des toiles sur la ligne i :

    for (j=0; j

  • 8/6/2019 Le C en 20h

    58/177

    huit colonnes

    7.6 Corrigs des exercices du chapitre

    Corrig de lexercice n7.1 toiles

    #include #include

    int main () {

    int i;int j;for (i=1; i

  • 8/6/2019 Le C en 20h

    59/177

    return 0;

    }

    Corrig de lexercice n7.3 Tronc

    Vous ajoutez ceci :

    ...for (i=1; i

  • 8/6/2019 Le C en 20h

    60/177

    Retenez l quivalence entre les deux programmes suivants :

    for (i=1; i

  • 8/6/2019 Le C en 20h

    61/177

    Chapitre

  • 8/6/2019 Le C en 20h

    62/177

    8

    Pointeurs et fonctions

    8.1 Objectifs

    Dans ce chapitre, nous manipulerons deux notions essentielles du langage C : les pointeurs etles fonctions

    8.2 Binaire, octets

    8.2.1 Binaire

    Lordinateur ne comprend que des 0 et des 1. On dit quil travaille en base 2 ou binaire (toutsimplement parce que ce systme de numration est particulirement adapt la technologielectronique utilise pour construire les ordinateurs). Au contraire des machines, les humainsprfrent gnralement la base 10, cest dire le systme dcimal.

    La table 8.1 donne lcriture binaire et dcimale de quelques nombres.

    Nous voyons dans cette table que le nombre 7 est donc reprsent par trois symboles 1 quise suivent : 111.

    59

    60 Pointeurs et fonctions

    Binaire Dcimal

    0 01 1

  • 8/6/2019 Le C en 20h

    63/177

    1 110 211 3100 4101 5110 6111 71000 81001 9

    1010 10... ...11111111 255

    Table 8.1 - quivalences entre lcriture binaire et lcriture dcimale

    Chacun de ces 1 et 0 sappelle un bit (contraction de langlais binary digit :chiffre binaire). Par exemple, le nombre 1010001 est compos de 7 bits.

    Un ensemble de huit bits conscutifs (chacun pouvant prendre la valeur 0 ou 1),sappelle un octet (byte en anglais).

    11110000 reprsente un octet10101010 reprsente un octet 100011101 ne reprsente pas un octet

    8.2.2 Compter en base 2, 3, 10 ou 16

    Vous avez lhabitude de compter en base 10 (dcimal). Pour cela, vous utilisez dix chiffres de0 9.

    Pour compter en base 2 (binaire), on utilisera deux chiffres : 0 et 1.

    Pour compter en base 3, on utilisera 3 chiffres : 0, 1 et 2.

    La base 16 (base hexadcimale) est trs utilise en informatique et notamment en langageassembleur. Mais compter en hexadcimal ncessite davoir 16 chiffres ! La solution est decomplter les chiffres habituels de la base 10 par des lettres de lalphabet comme le montre letableau 8.2.

    8.3 Variables : pointeurs et valeurs 61

    Base 16 Base 10

    0 01 1

  • 8/6/2019 Le C en 20h

    64/177

    2 23 34 45 56 67 78 89 9

    A 10B 11C 12D 13E 14F 15

    Table 8.2 - Base 16 et base 10

    Dans la pratique, afin de ne pas faire de confusion entre le nombre 10 (en dcimal) et ce mmenombre en hexadcimal, on prcde ce dernier par le prfixe 0x :

    int i1=10;int i2=0x10;

    printf("i1=%d i2=%d",i1,i2);

    Ce programme affichera i1=10 i2=16.

    8.3 Variables : pointeurs et valeurs

    8.3.1 Variables et mmoire

    Une variable est une zone mmoire disponible pour y ranger des informations. Par exemple,dans le cas dune variable car dclare par char car;, la zone mmoire disponible sera de1 octet (exactement une case mmoire). En revanche, une variable de type int utilisera aumoins 4 octets (la valeur exacte dpend du compilateur), cest dire 4 cases mmoires.

    prsent, reprsentons-nous la mmoire comme une unique et longue rue remplie demaisons. Chaque case mmoire est une maison. Chaque maison porte un numro, cest ce quipermet de dfinir son adresse postale. Cette adresse est unique pour chaque maison dans la rue.De manire analogue, pour une case mmoire, on parlera dadresse mmoire.

    62 Pointeurs et fonctions

    Par exemple, ce petit programme va afficher ladresse mmoire dune variable de typecaractre.

    #include

  • 8/6/2019 Le C en 20h

    65/177

    #include

    int main () {char c='A';printf ("c contient %c et est stock %p\n",c,&c);return 0;

    }

    Lexcution nous donne, par exemple :

    c contient A et est stock 0xbf8288a3

    Le format %p permet dafficher une adresse en hexadcimal.

    Vous pouvez essayer le programme prcdent, mais vous naurez probablement pas lamme adresse mmoire que dans lexemple.

    8.3.2 Pointeurs

    Pour manipuler les adresses mmoire des variables, on utilise des variables dun type spcial :le type pointeur. Une variable de type pointeur est dclare ainsi :

    type* variable;

    Lespace aprs * peut tre omis ou plac avant, peu importe.

    Cest le signe * qui indique que nous avons affaire un pointeur. Lindication qui prcde *renseigne le compilateur sur le type de case pointe, et comment se comporteront certainesoprations arithmtiques1. Si v est un pointeur vers un int, et que nous dsirons modifierlentier point, nous crirons :

    *v = valeur;

    *v peut tre interprt comme contenu de ladresse mmoire pointe par v .

    Lisez le programme suivant ainsi que les explications associes.#include

    int main () {char car='C';char * ptr_car; /* Variable de type pointeur */

    printf("Avant, le caractre est : %c\n",car);ptr_car = &car; /* ptr_car = adresse de car */

    1. Ajouter 1 un pointeur sur un int revient ajouter 4 ladresse, alors quajouter 1 un pointeur surun char revient najouter que 1 ladresse.

    8.3 Variables : pointeurs et valeurs 63

    *ptr_car = 'E'; /* on modifie le contenu de l'adresse mmoire */

    printf("Aprs, le caractre est : %c\n\n",car);

    printf("Cette modification est due :\n");

    printf("Adresse de car : %p\n",&car);

  • 8/6/2019 Le C en 20h

    66/177

    p ( p , );

    printf("Valeur de ptr_car : %p\n",ptr_car);

    return 0;}

    Voici ce que cela donne avec notre rue borde de maisons :

    ptr car = &car;ptr car contientladresse postale deMonsieur car

    *ptr car = E;

    On entre chezMonsieur car et ony dpose lecaractre E

    printf ("%c",car);On va regarder cequil y a chezMonsieur car pourlafficher lcran

    Table 8.3 - Pointeurs et valeurs

    On supposera que la variable car est stocke ladresse 0x0100 ; la variable ptr car eststocke ladresse 0x0110.

    Reprenons les deux premires lignes dexcution du programme :

    char car='C';char* ptr_car;

    La mmoire ressemble alors ceci :

    Nom de la variable car ptr car

    Contenu mmoire C ?Adresse mmoire (0x) 100 110

    Table 8.4 - Stockage de variables (a)

    Nous mettons ? comme contenu de ptr car car cette variable na pas encore t initialise.Sa valeur est donc indtermine.

    64 Pointeurs et fonctions

    Le programme se poursuit par :

    printf("Avant, le caractre est : %c\n",car);ptr_car = &car; /* ptr_car = adresse de car */

  • 8/6/2019 Le C en 20h

    67/177

    Il y aura donc affichage lcran de Avant, le caractre est : C puis la mmoire seramodifie comme ceci :

    Nom de la variable car ptr carContenu mmoire C 100

    Adresse mmoire (0x) 100 110

    Table 8.5 - Stockage de variables (b)

    ptr car nest donc quune variable, elle contient la valeur 100 (ladresse de la variable car).Finalement, la ligne :

    *ptr_car = 'E'; /* on modifie le contenu de l'adresse mmoire */

    conduit modifier la mmoire comme suit :

    Nom de la variable car ptr car

    Contenu mmoire E 100Adresse mmoire (0x) 100 110

    Table 8.6 - Stockage de variables (c)

    Prenez le temps de comprendre tout ce qui prcde avant de passer la suite.

    8.3.3 Exercice dapplicationExercice n8.1 Intelligent

    Ralisez un programme quivalent qui change une valeur numrique (int) de 10 35.

    Notons que, dans la pratique, lorsque lon dclare un pointeur, il est plus prudent delinitialiser :

    #include

    int main () {char car='C';char * ptr_car=NULL;

    printf("Avant, le caractre est : %c\n",car);

    ptr_car = &car; /* ptr_car = adresse de car */*ptr_car = 'E'; /* on modifie le contenu de l'adresse mmoire */printf("\nAprs le caractre est : %c\n",car);/*on a modifi car*/

    return 0;

    }

    8.4 Fonctions 65

    La constante NULL vaut 0. Or un programme na pas le droit daccder ladresse 0. Dans lapratique, crire prt car=NULL signifie que ladresse mmoire pointe est pour linstant invalide.

    On peut se demander quoi servent les pointeurs ? ! En effet, ceci a lair compliqu alors quelon pourrait faire bien plus simple.

  • 8/6/2019 Le C en 20h

    68/177

    p p p

    Ainsi tout le travail effectu par le programme prcdent se rsume au code suivant :

    #include int main () {

    char car='C';

    printf("Avant, le caractre est : %c\n",car);

    car='E';

    printf("\nAprs le caractre est : %c\n",car);/*on a modifi car*/

    return 0;}

    Nous verrons par la suite que dans certains cas, on ne peut pas se passer des pointeurs,notamment pour certaines manipulations au sein des fonctions

    8.4 Fonctions

    Une fonction est un petit bloc de programme qui limage dune industrie va crer, faire oumodifier quelque chose. Un bloc de programme est mis sous la forme dune fonction si celui-ciest utilis plusieurs fois dans un programme ou simplement pour une question de clart. Dela mme manire que nous avions dfini la fonction main, une fonction se dfinit de la faonsuivante :

    (

  • 8/6/2019 Le C en 20h

    69/177

    03. int maximum (int valeur1, int valeur2) {04. int max;05. if (valeur1

  • 8/6/2019 Le C en 20h

    70/177

    /* Fonction affichant un caractre */void affiche_car (char car) {printf ("%c",car);

    }

    int main () {char c;int i;

    printf("Veuillez entrer un caractre:");

    scanf("%c",&c);

    for (i=0; i

  • 8/6/2019 Le C en 20h

    71/177

    #include

    int val = 0;int val_retour = 0;

    void carre () {val_retour = val * val;

    }

    int main () {val = 2;

    carre ();

    printf("Le carr de 2 est %d\n", val_retour);

    return 0;}

    Les variables val et val retour sont des variables globales. On constate que le programmedevient rapidement illisible et difficile vrifier

    Le conseil retenir est de ne pas utiliser de variable(s) globale(s) lorsquil est possible de senpasser.

    8.4.3 Utilisation et modification de donnes dans les fonctions

    Lappel dune fonction peut seffectuer laide de paramtres.Ces paramtres figurent dans les parenthses de la ligne de titre de la fonction.

    Par exemple :

    #include

    void affiche_Nombre (int no) {no=no+1;

    printf ("Le nombre no est : %d\n",no);}

    int main (){

    int a=12;affiche_Nombre (a);

    printf("Le nombre a est : %d\n",a);return 0;

    }

    Dans le cas qui prcde, lors de lappel de fonction, cest le contenu de a (cest dire 12)qui est envoy dans la fonction, et qui se retrouve donc stock dans no. Le nombre 12 existedonc en deux exemplaires : une fois dans la variable a de main et une fois dans la variable no

    de affiche Nombre. Puis on ajoute 1 dans no (mais pas dans a), et on laffiche. On voit doncapparatre :

    8.4 Fonctions 69

    Le nombre no est : 13

    La procdure se termine alors et la variable no est dtruite. On revient dans la fonction mainqui affiche le contenu de a qui vaut encore 12 On voit donc apparatre :

  • 8/6/2019 Le C en 20h

    72/177

    Le nombre a est : 12

    Il faut donc retenir que les paramtres dune fonction sont passs par valeur et que modifierces paramtres ne modifie que des copies des variables dorigine.

    Pour pouvoir modifier les variables dorigine, il ne faut plus passer les paramtres par valeur,mais par adresse, en utilisant les pointeurs, comme cest le cas dans lexemple qui suit.

    #include

    void avance_Position (int* pointeur_int) {*pointeur_int = *pointeur_int + 2;

    }

    int main () {int x=0;

    printf("Position de dpart : %d\n",x);

    avance_Position (&x);

    printf("Nouvelle position : %d\n",x);

    return 0;}

    Imaginons que pointeur int se trouve en mmoire ladresse 20 et x ladresse 10 :

    Nom de la variable x pointeur intContenu mmoire

    Adresse mmoire (0x) 10 20

    Table 8.7 - Stockage de variables (d)

    prsent, droulons le programme principal :1. int x=0; : dclaration et initialisation de x 02. Avance Position (&x); : appel de la fonction Avance Position (&x); avec la valeur

    10 (ladresse de x) en paramtre

    3. void Avance Position (int* pointeur int) : on lance cette fonction et pointeur intvaut donc 10

    4. * pointeur int = (* pointeur int) + 2; : (*pointeur int) pointe sur la variablex. Lancienne valeur de x va tre crase par sa nouvelle valeur : 0+2

    70 Pointeurs et fonctions

    Nom de la variable x pointeur intContenu mmoire 0 10

    Adresse mmoire (0x) 10 20

    Table 8 8 Stockage de variables (e)

  • 8/6/2019 Le C en 20h

    73/177

    Table 8.8 - Stockage de variables (e)

    5. printf("Nouvelle position :%d",x); : on se retrouve avec 2 comme valeur.

    Nous devons utiliser des pointeurs pour pouvoir modifier certaines variables en dehors delendroit o elles sont dclares. On dit gnralement quune fonction nest pas capable de mo-difier ses arguments. Lusage des pointeurs devient dans ce cas ncessaire Ainsi, le programme

    suivant affichera 2 et non 4.#include

    void calcule_double (int x){x=x+x ;

    }

    int main () {int i=2;calcule_double(i);

    printf("i vaut prsent :%d",i); /* il vaut toujours 2 !!! */

    return 0;}

    Pour rendre le programme fonctionnel en utilisant les pointeurs, il faudrait crire :

    #include

    void calcule_double (int * p_i){*p_i=*p_i+*p_i;

    }

    int main () {int i=2;calcule_double(&i);

    printf("i vaut prsent :%d",i);return 0;

    }

    Nanmoins, la bonne pratique (celle qui donne les programmes les plus simples comprendre

    et les plus faciles dboguer) serait dcrire :#include

    int calcule_double (int a){a=a+a;return a;

    }

    int main () {int i=2;

    i=calcule_double(i);printf("i vaut prsent :%d",i);

    8.4 Fonctions 71

    return 0;}

    Observez attentivement les trois exemples qui prcdent et soyez sr davoir bienl ffi h 2 l l d ffi h 4

  • 8/6/2019 Le C en 20h

    74/177

    Observez attentivement les trois exemples qui prcdent et soyez sr d avoir biencompris pourquoi le premier affiche 2 alors que les deux suivants affichent 4.

    Exercice n8.2 Encore un

    Modifiez le programme prcdent afin davoir disposition une fonction qui prend enparamtre un pointeur vers un entier et modifie lentier point en lui ajoutant 1.

    Ce type dopration sur les pointeurs est dangereux :

    int* x;*x++;

    augmentera ladresse de x (on va chez le voisin) et non sa valeur. Pour cela il faut crire :

    (*x)++;

    Ceci est une faute courante, prenez garde

    Exercice n8.3 Mon beau sapin

    Reprenez le programme du sapin de Nol du chapitre prcdent. crivez deux fonc-tions :

    ramure (int clignes) qui dessine la ramure du sapin sur clignes de hauteur, tronc (int pos t) qui dessine le tronc en position pos t (pos t blancs avant le

    tronc).

    Puis utilisez ces deux fonctions pour dessiner le sapin sur n lignes.

    8.4.4 Prototypes des fonctions

    Dans la pratique, lorsquon souhaite crire un programme qui contient de nombreuses fonc-tions, on essaie de prsenter le code de manire propre et structure. Ainsi, plutt que cetteversion :

    #include

    int max (int x, int y) {if (x

  • 8/6/2019 Le C en 20h

    75/177

    printf( min : %d\n ,min(i1,i2));return 0;

    }

    on lui prfrera la version suivante o les prototypes des fonctions disponibles figurent endbut de code (un peu comme une table des matires) :

    #include

    /* PROTOTYPES : */int max (int x, int y);int min (int x, int y);

    int max (int x, int y) {if (x

  • 8/6/2019 Le C en 20h

    76/177

    Corrig de l exercice n 8.2 Encore un

    #include

    void ajoute_un (int* pointeur_int) {*pointeur_int = *pointeur_int + 1;

    }

    int main () {int i=10;

    printf ("i=%d\n",i);ajoute_un (&i);printf ("i=%d\n",i);

    return 0;}

    Corrig de lexercice n8.3 Mon beau sapin

    #include #include

    // Dessin de la ramure du sapinvoid ramure (int clignes) {

    int i=0, j=0;

    for (i=1; i

  • 8/6/2019 Le C en 20h

    77/177

    8.6.1 Les diffrentes bases de numration

    Il est souhaitable de retenir que :

    compter en base 2 (binaire) revient nutiliser que des 0 et des 1 ; un octet est form de 8 bits : 11110101 ; la base 10 est celle quon emploie tous les jours ; en base 16 (base hexadcimale), des lettres sont utilises en plus des 10 chiffres (0, 1, 2, 3,

    4, 5, 6, 7, 8, 9, A, B, C, D, E, F).

    8.6.2 Pointeur

    Un pointeur est une variable faite pour contenir une adresse mmoire, souvent ladresse duneautre variable.

    8.6.3 Structure dun programme C

    Pour finir, voici deux programmes qui reprennent lessentiel de ce qui a t vu :

    #include

    int main () {int i=100;int * pointeur_sur_i=NULL;

    pointeur_sur_i=&i;

    *pointeur_sur_i=200;printf ("i vaut prsent %d\n",i);

    return 0;}

    Le programme prcdent revient stocker 200 dans la variable i.

    #include

    /* Prototypage */void avance_Position (int* x);

    void avance_Position (int* x) {(*x)+=2;

    }

    int main () {int i=0;int x=0;

    printf("Position de dpart : %d\n",x);

    for (i = 0; i

  • 8/6/2019 Le C en 20h

    78/177

  • 8/6/2019 Le C en 20h

    79/177

    Chapitre

    9

  • 8/6/2019 Le C en 20h

    80/177

    9Tableaux et chanes de caractres

    9.1 Objectifs

    En C, une chane de caractres est quivalente un tableau de caractres. Ce chapitre introduitces deux notions (chanes et tableaux) tout en vous faisant approcher de la gestion de la mmoire.

    9.2 Tableaux

    9.2.1 Dfinition

    Un tableau est un ensemble dlments rangs en mmoire dans des cases conscutives (voirTable 9.1). Un tableau peut tre constitu de plusieurs lignes et colonnes. Nous nutiliseronsdans un premier temps que les tableaux une seule ligne.

    Notez que les cases dun tableau sont numrotes partir de 0 en langage C.

    77

    78 Tableaux et chanes de caractres

    Numro de case 0 1 2 3 4 5 6 7Contenu A B C D E F G H

    Table 9.1 - Tableau de caractres

  • 8/6/2019 Le C en 20h

    81/177

    9.2.2 Dclaration

    Un tableau se dclare de la manire suivante :

    [];

    /* Dclaration d'un tableau de 10 caractres */char tab_char [10];

    /* Dclaration d'un tableau de 10 entiers */int tab_int [10];

    9.2.3 Utilisation

    On accde une case du tableau en mettant le nom du tableau, suivi dun crochet ouvrant [ puis un numro de case et un crochet fermant : ] . Cela donne, par exemple :

    /* dclarations */int tab_int[10]; /* tableau de 10 cases (0 9) d'entiers */char tab_char[10]; /* tableau de 10 cases (0 9) de caractres */

    /* utilisation */

    tab_char[3]='C'; /* Initialisation de la case 3 (la quatrime) de tab_char */

    tab_int[6]=10; /* Initialisation de la case 6 (la septime) de tab_int */

    tab_int[7]=tab_int[6] * 2; /* La case 7 (la huitime) contiendra donc 20 (10*2) */

    Noubliez pas que le compilateur ne vrifie pas que vous utilisez le tableau dans seslimites. Il vous est donc possible dcrire lextrieur de votre tableau, donc chez levoisin. Cest lun des bugs les plus courants de la programmation en C.

    9.3 Chanes de caractres

    Les chanes de caractres sont des tableaux de caractres suivis du 0 (zro ; ne pas confondreavec le caractre O de Oh la la par exemple) qui est considr lui aussi comme un caractre.Une chane scrit donc : contenu utile de la chane + valeur 0.

    9.3 Chanes de caractr