Vous êtes sur la page 1sur 28

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Plan des TP
Les TP durent 3 heures et se font sur machine. Un compte rendu de TP sera relev en fin de sance. Ce compte rendu se fera sous OpenOffice (copie des sources des programmes et des copies d'cran d'excution). A la fin des 7 sances de TP,vous aurez un partiel de TP d'une dure de 3 heures ou vous programmerez seul. Vous aurez donc 2 notes de TP: une note de sance qui sera la moyenne des notes des 7 sances (coeff 1/3) une note de partiel (coeff 2/3). Pour chaque TP (except le premier TP), la prparation est obligatoire. Un compte rendu de TP devra tre remis l'enseignant en debut de sance. Plan des TP TP1 TP2 TP3 TP4 TP5 TP6 TP7 Premiers programmes Rsolution d'quation du second degr Algorithmique 1 Algorithmique 2 Tableaux et chanes de caractres Les fonctions Chane de compilation, fonctions et pointeurs 1 2 18 25 29 33 37 43

TP1

Premiers programmes
Thmes
Programmation sous Visual C++ , notion de projet, d'excutable Utilisation du dbuggeur. Oprations arithmtiques et logiques. Rgles de programmation. Premiers programmes, utilisation de puts, printf, putchar, boucle for. Utilisation de l'aide, excution d'un programme d'exemple. Introduction la boucle for.

Prparation
Lire les documents ressources en fin de TP.

Rgles de programmation :
Tous les programmes que vous allez crire vont tre sauvs dans un fichier ayant comme nom TPi_exoj.c avec i le numro du TP et j le numro de l'exercice. Tous les fichiers du tp1 seront sauvs dans le rpertoire i1/tp1 sous votre compte (i1/tp2 pour le tp2 etc). Chaque programme devra avoir un en-tte dans lequel devra figurer le nom du fichier, l'auteur, la description du programme et la date de cration ( et peut-tre de modification).
//************************************************************************ // // File........: nom_du_fichier.c // // Author(s)...: NOM_AUTEUR // // Description.: but du programme ( dtailler) // // CREATION : 05/09/2006 MODIFICATION : // //************************************************************************* #include <stdio.h> #include <stdlib.h> int main(void) { // le programme system("PAUSE"); return 0; }

Travail faire : Prise en main de Visual C++ en mode console


Crer le rpertoire i1 sous votre compte. Lancer Visual Studio. 08/08/2007 JLS page 1/56 08/08/2007 JLS page 2/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Crer un nouveau projet tp1 (Fichier, Nouveau, Projet).

A partir de l, VC++ a cr un rpertoire tp1 et plac les fichiers permettant la gestion du projet. Pour crer un excutable, il faut placer dans le projet un fichier source (xxx.c) avec l'extension ".c" contenant le code de l'application. Pour cela , clic droit sur fichier source, Ajouter, Nouvel lment,

Dcocher "Crer le rpertoire pour la solution"

Dans la fentre suivante, le fichier ajouter se nomme tp1_exo1.c o se trouvera le code du premier exercice. Cliquer sur Ajouter.

Le fait de crer un nouveau projet va crer automatiquement le rpertoire tp1. Dans la fentre suivante, dans paramtres de l'application choisir Application console et projet vide.

On obtient alors un fichier vide. Recopier le fichier modle vu prcdemment et modifier l'en-tte.

08/08/2007

JLS

page 3/56

08/08/2007

JLS

page 4/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Placer la place du commentaire les lignes suivantes :


int n1=5; int nRes=6; printf(" j'ai une valeur a afficher :%d\n",n1); printf(" j'ai deux valeurs a afficher :%d et %d puts ("operations aritmetiques"); nRes=n1*3; printf("%d*2=%d\n",n1,nRes); nRes=n1/2; printf("%d/2=%d\n",n1,nRes); nRes=n1%2; printf("%d%2=%d\n",n1,nRes); nRes=n1-2; printf("%d-2=%d\n",n1,nRes); puts ("operations logiques"); nRes=n1&0x07; printf("%d&2=%d\n",n1,nRes); nRes=n1|0x07; printf("%d|2=%d\n",n1,nRes); nRes=n1^0x07; printf("%d^2=%d\n",n1,nRes); puts ("fin du programme");

\n",n1,nRes);

programme placer

Lancer le programme. Clic sur la flche verte Une fentre s'affiche , cocher la case "Ne plus afficher cette boite de dialogue"., puis clic sur oui.

------ Dbut de la gnration : Projet : tp1, Configuration : Release Win32 -----Compilation en cours... tp1_exo1.c dition des liens en cours... Gnration de code en cours Fin de la gnration du code Incorporation du manifeste en cours... Le journal de gnration a t enregistr l'emplacement "file://g:\iut_courant\i1\programmes_2007_2008\tp1\Release\BuildLog.htm" tp1 - 0 erreur(s), 0 avertissement(s) ========== Gnration : 1 a russi, 0 a chou, 0 mis jour, 0 a t ignor ==========

1) Analyser chaque ligne affiche et expliquer le rsultat obtenu (Complter le tableau ci-dessous). OPERATION 08/08/2007 JLS page 5/56 08/08/2007 JLS RESULTAT page 6/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

nRes=n1*3 nRes=n1/2; nRes=n1%2; nRes=n1-2; nRes=n1&0x07; nRes=n1|0x07; nRes=n1^0x07;

l'erreur se situe ici !

Deuxime erreur : non dclaration d'une variable. Toutes les variables doivent tre dclares avant d'tre utilises. Quel message donne le compilateur fasse ce type d'erreur ? Remplacer la ligne int n1=5; par n1=5;

Trouver les erreurs de compilation


Nous allons ici voir comment le compilateur peut aider trouver les erreurs faites lors de la saisie du code. Pour cela nous allons faire un certain nombre d'erreurs classiques :
Premire erreur : oubli du point virgule. Deuxime erreur : non dclaration d'une variable. Troisime erreur : problme de l'apostrophe dans le "printf". Quatrime erreur : appel une fonction inconnue . Cinquime erreur : oubli de la fonction "system".

Gnrer la solution (F7) : Vous obtenez la ligne suivante :


.\tp1_exo1.c(18) : error C2065: 'n1' : identificateur non dclar

Premire erreur : l'oubli du point virgule. Enlever le point virgule la fin de l'instruction : nRes=n1*3 Puis lancer le programme Le programme affiche le mme rsultat qu'auparavant !!! Cela est tout simplement du au fait que lorsque vous lancez le programme, VC++ fait 2 oprations :
appel au compilateur qui gnre le fichier excutable, puis lancement de l'excutable (avec le chargement des dll permettant l'excution du programme).

D'autres erreurs la suite de cette erreur sont vues par le compilateur. Ces erreurs sont dues la premire erreur et ne doivent donc pas tre corriges. Il faut toujours traiter les erreurs de compilation dans l'ordre et ne pas hsiter aprs avoir trait la premire erreur refaire une gnration de code. Il est possible qu'un certain nombre d'erreurs disparaissent alors !!!

Dans les 2 cas , l'affichage des informations issues de ces 2 tapes se fait dans la fentre "sortie" ( ALT+2 ou dans le menu ,Affichage, Sortie). Vous ne voyez donc que les informations issues du lancement de l'excutable , les informations issues du compilateur sont masques. Si le compilateur rencontre une erreur dans le fichier tp1_exo1.c, il est incapable de gnrer le fichier excutable et c'est l'ancien excutable qui est lanc. Vous avez donc l'impression que votre programme fonctionne alors que c'est l'ancien excutable qui est lanc! Pour vrifier que la compilation s'est bien passe, il faut visualiser les messages issus du compilateur: Pour cela dans la fentre "sortie" choisir "Afficher la sortie partir de Gnrer" pour avoir les messages issus de la compilation. Vous auriez pu plus simplement faire un F7 (Gnrer la solution) qui permet de lancer le compilateur sans lancer l'excution la suite. Par la suite il sera prfrable de choisir cette solution qui a l'avantage de ne pas masquer les messages d'erreurs issus du compilateur.

troisime erreur : problme de l'apostrophe dans le printf Remplacer printf("%d-2=%d\n",n1,nRes); par


printf("%d-2=%d\n,n1",nRes);

Gnrer la solution
Vous obtenez la ligne suivante : .\tp1_exo1.c(31) : warning C4313: 'printf' : conflit entre '%d' dans la chane de format et l'argument 2 de type 'char [12]'

Il faut lire attentivement le message issu du compilateur. Ce message n'est pas un message d'erreur mais un Warning (avertissement). Un avertissement permet de donner une information au programmeur mais sans bloquer la gnration du code. Le compilateur gnre l'excutable. Par contre l'affichage du rsultat est incohrent. 2) Lancer le programme et donner le rsultat affich par cette ligne de code. Conclure sur l'importance des Warnings. Quatrime erreur : appel une fonction inconnue. Remplacer system("PAUSE"); par systeme("PAUSE");

Vous obtenez la ligne suivante :


.\tp1_exo1.c(25) : error C2146: erreur de syntaxe : absence de ';' avant l'identificateur 'printf'

Ainsi qu'un marqueur vert sur la ligne ayant un problme : 08/08/2007 JLS page 7/56 08/08/2007 JLS page 8/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Gnrer la solution :
Vous obtenez les lignes suivantes :
.\tp1_exo1.c(42) : warning C4013: 'systeme' non dfini(e) ; extern retournant int pris par dfaut Compilation en cours... tp1_exo1.c .\tp1_exo1.c(42) : warning C4013: 'systeme' non dfini(e) ; extern retournant int pris par dfaut dition des liens en cours... tp1_exo1.obj : error LNK2001: symbole externe non rsolu _systeme

Le compilateur gnre un warning la ligne 42.Dans cet avertissement le compilateur informe que la fonction "systeme" n'est pas dfinie (dans les fichiers de dclaration #include""). Aprs la compilation, l'diteur de lien vient assembler le code gnr par tp1_exo1.c avec le code des fonctions appeles (printf, puts, systeme). C'est l'diteur de lien qui stoppe la gnration du code, puisqu'il ne trouve pas dans la bibliothque des fonctions disponibles le code de la fonction systeme. Oubli de la fonction system("PAUSE"); 3) Gnrez la solution. Existe-t-il une erreur de compilation ? Lancer le programme. Que se passe-t-il ? Expliquer et en dduire le rle de la fonction system.

Mettre un point d'arrt (double-clic gauche de la ligne ou l'on veut arrter le code).Un point rouge apparat.

Travail faire : Prise en main du Debug sous Visual C++ en mode console
Nous allons voir un outil trs utilis pour trouver les bugs du programme. Le bug ou bogue informatique est une erreur qui apparat dans un programme. Les erreurs simples sont dtectes par le compilateur, mais les erreurs de conceptions ne peuvent tre dtectes que lors de l'excution du programme. Au moment ou une erreur apparat, il peut tre intressant de stopper le programme juste avant l'arrive de l'erreur et de visualiser les variables. C'est le dbuggeur qui permet de faire cette opration. Dans la zone Explorateur de solution, cliquer sur Proprits (ou projet, Proprits du Projet)

Lancer le programme

Ajouter la fentre des variables locales ou ajouter un espion Ce qui va nous permettre de visualiser directement les variables nRes et n1.

Et modifier dans C/C++ , Optimisation, le niveau d'optimisation du code : Dsactiv. Pour visualiser le Dbug en mode pas pas comme nous voulons le faire, il est important que le code ne soit pas optimis. En effet l'optimisation du code peut amener le compilateur ne pas coder des instructions qui ne sont pas utiles pour la suite du programme.

Excuter le programme en mode pas en pas (F10) et vrifier qu' aprs chaque calcul (flche jaune sur la fonction printf) la variable nRes est bien mise jour. On rappelle qu'une valeur prcde de 0x est en hexadcimal.

08/08/2007

JLS

page 9/56

08/08/2007

JLS

page 10/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Aprs 4 appuis sur la touche F10.

A la question Supprimer ou Enlever, choisir Enlever. En effet, il est important de garder le source tp1_exo1.c crit prcdemment. Tous les fichiers que vous allez cr ne devront pas tre effacs !

Puis clic droit sur fichier source, Ajouter, Nouvel lment et dans Nom: tp1_exo2.c

On peut voir que l'affichage suit bien l'excution en mode pas pas.

nRes a t mise jour (valeur en rouge)

4) En utilisant le dbogueur donner le rsultat des oprations 255 ET 0x80, 0 OU 1 et 0 OU EXC 1.Pour cela modifier le programme tp1_exo1.c et ajouter ces oprations au dbut du programme (le rsultat de l'opration est stock dans nRes). Ne pas pas placer de fonction printf aprs chaque calcul. Faire une copie d'cran. 5) Sans utiliser le dbogueur, afficher les rsultats de ces oprations en ajoutant la fin de chaque calcul l'affichage de la valeur nRes (printf).Faire une copie d'cran dans le compte rendu.

utilisation des fonction d'affichages puts, printf, putchar : tp1_exo2.c


Sous le mme projet retirer le fichier tp1_exo1.c

08/08/2007

JLS

page 11/56

08/08/2007

JLS

page 12/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Copier le modle de la page 2 (Rgles de programmation) et modifier l'en-tte. Chaque nouveau programme devra avoir cet en-tte ! Modifier la description du programme de l'en-tte " tests des fonctions printf, puts, putchar". Rajouter les lignes suivantes dans le programme, puis tester. Complter les commentaires pour chaque ligne.
puts("******************************************"); puts(" test "); //commentaire faire puts(" \ttest \\t "); //commentaire faire puts(" \ntest \\n "); //commentaire faire puts(" \" test \" "); //commentaire faire puts("_________________________________________");

6)

Faire la copie d'cran du rsultat affich dans le compte rendu.

7) Rajouter les lignes suivantes et crire les commentaires chaque ligne. Attention placer les dclarations de variables nVal et f en dbut de programme ! Le compilateur n'accepte pas les dclarations dans le code.
int n = 32; //dclaration et initialisation entier double d=2.34; //dclaration et initialisation rel printf printf printf printf printf printf printf printf printf printf printf ("n vaut %d.\n", n); //commentaire faire ("n vaut %10d.\n", n); //commentaire faire ("n vaut 0x%x.\n", n); //commentaire faire ("hello"); (" hello\n");//commentaire faire ("%s \n","Coucou");//commentaire faire ("%12s \n","Coucou");//commentaire faire ("d vaut %f\n", d); //commentaire faire ("d vaut %e\n", d); //commentaire faire ("d vaut %10.3f\n", d); //commentaire faire ("d vaut %g\n", d); //commentaire faire

08/08/2007

JLS

page 13/56

08/08/2007

JLS

page 14/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

8) Rajouter les lignes suivantes la suite. Donner le caractre ayant le code 0x5F et 0xB3. Donner le rsultat affich par chaque ligne.
int i; // a metre en dbut de code

putchar('_'); putchar(0x5F); putchar('-'); puts(""); for (i=0; i<10; i++) putchar('A'); puts(""); putchar('|'); putchar(0xB3); putchar('\n'); putchar('x'); puts("");

9)

Mettre la copie d'cran du rsultat obtenu sur le compte rendu.

11) Expliquer le rsultat obtenu et complter le tableau suivant. Valeur en dcimal Valeur en hexadcimal lettre affiche 0x30 0x31 ... 0x39 ... 0x41 0x42 ... 0x59 0x5A ... 0x61 0x62 ... 0x7A 12) Modifier le code de la fonction ASCII avec le code ci-dessous . Conclure
int i; for(i=0;i<=127;i++){ printf("%d | 0x%X = %c\n",i,i,i); }

Mon premier programme : tp1_exo3.c


En gardant les mmes rgles que prcdemment : enlever le fichier tp1_exo2.c et le remplacer par un nouveau fichier tp1_exo3.c, avec en-tte et fonction main. 10) b AAA 234 43.5 bbbbbbbbbbbbbbb 2 ET 3 = 2 3 <<1 = 6 Ecrire un programme qui affiche : (utilisation de putchar avec affichage d'un variable caractre note c) (utilisation de puts) (utilisation de printf avec affichage d'une variable de type int note n) (utilisation de printf avec affichage d'une variable de type double note d) (utilisation d'une boucle for, afficher 15 b) (calcul + affichage du rsultat du calcul, variable entire nRes) (calcul + affichage du rsultat du calcul, variable entire nRes)

13) 14)

Existe-t-il une diffrence entre putchar(i) et printf("%c",i) ? Donner le rsultat de la ligne suivante

int n=48; printf("%c = %d",n,n);

Mon deuxime programme : tp1_exo5.c


15) 123456789 En utilisant la boucle for ,crire un programme qui affiche :

Notion de table ASCII : tp1_exo4.c


La notion de table ASCII date du milieu des annes 70 lorsqu'il a fallu transmettre les donnes l'aide de la ligne tlphonique avec le tltexte (tlscripteurs). S'est alors pos le problme du codage des caractres envoys. C'est le code ASCII qui s'est alors impos et qui consistait utiliser un code sur 7 bits pour transmettre les caractres et les caractres de contrles (retour la ligne, tabulation, ...). Ce code a ensuite t utilis pour coder les caractres dans les ordinateurs. Le but du programme que l'on va lancer est de visualiser cette table ASCII. Dans le mme projet, tester le code suivant dans le fichier tp1_exo4.c .
int i; for(i=0;i<=127;i++){ printf("%d | 0x%X =",i,i); putchar(i);puts(""); }

16) En utilisant la boucle for ,crire la suite un programme qui affiche les lettres de l'alphabet : ABCDEFGHIJKLMNOPQRSTUVWXYZ

Le caractre 7 de la table ASCII correspond au bip que vous entendez. On pourra tester avec l'instruction putchar(7).// pour entendre bip.

08/08/2007

JLS

page 15/56

08/08/2007

JLS

page 16/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Ressources :Codage des donnes


TYPES char unsigned char int unsigned int float BASE DECIMALES 100 255 -1 2^32-1 50,25 BASE HEXADECIMALES 0x64 0xFF 0xFFFFFFFF 0xFFFFFFFF 0x4249 0x0000 REPRESENTATIONS BINAIRES 0110 0100 1111 1111
8 fois 1111 8 fois 1111

TP2

Rsolution d'quation du second degr


Thmes
Utilisation des structures de contrles if et for. Diffrences entre les types float et double. Utilisation de l'aide de VC++. Utilisation des fonctions mathmatiques sin, cos, tan, pow et sqrt de la bibliothque <math.h>. Introduction aux pragmas.

0100 0010 0100 1001 0000 0000 0000 0000

Prparation
Pour un nombre rel : 2 types possibles float et double. Les nombres de type float sont cods sur 32 bits dont : 23 bits pour la mantisse 8 bits pour l'exposant 1 bit pour le signe (s) bit de signe : si (s)=0 valeur positive sinon valeur ngative Mantisse code sur 23 bits 1 Mantisse <2 Mantisse = 1 + m12-1 + m22-2+ .. + m232-23 Exposant cod sur 8 bits (-127=00000000 et 128=11111111) Exposant = e727 + e626+ .. + e020 -127 1) Expliquer ce que fait le programme ci-dessous et plus particulirement l'utilisation faite de la fonction printf.
int main (void) { int i; char sz[]="toto"; int nAge=20; double dCompte=123.89; printf("\t|%10s|%5s|%10s|\n","nom","age","valeur"); printf("\t|----------|-----|----------|\n"); printf("\t|%10s|%5d|%10.2f|\n",sz,nAge,dCompte); printf("\t|----------|-----|----------|\n"); while(1); return 0; }

2) Expliquer ce que fait le programme ci-dessous. Pourquoi le deuxime appel la fonction getchar() renvoie toujours l'cran "pas un chiffre" ? Pour rpondre la question on pourra se rappeler que l'utilisateur entre un chiffre suivi d'un retour chariot afin de dbloquer la fonction getchar.
#include <stdio.h> int main (void) { char c; c=getchar(); if(c>='0' && c<='9') puts("un chiffre"); else puts("pas un chiffre"); c=getchar(); if(c>='0' && c<='9') puts("un chiffre"); else puts("pas un chiffre"); while(1); return 0; }

Les nombres de type double sont cods sur 64 bits dont : 52 bits pour la mantisse 11 bits pour l'exposant 1 bit pour le signe

3) Ecrire un programme qui demande l'utilisateur de taper un entier et qui affiche GAGNE si l'entier est entre 56 et 78 bornes incluses PERDU sinon. 08/08/2007 JLS page 17/56 08/08/2007 JLS page 18/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

4) Commenter chaque ligne du programme ci-dessous .Donner les valeurs de CHAR_MIN, CHAR_MAX, INT_MIN, INT_MAX ainsi que la taille d'un int, float et double.
#include #include #include #include <stdio.h> <stdlib.h> <limits.h> <math.h>

Diffrences entre les types float et double 6) Ecrire le programme suivant (tp2_exo6.c). Quelle est la valeur finale de fS ?
#include <stdio.h> #include <stdlib.h> int main(void) { int i ; float fS ; fS = 1000.0 ; for (i=0; i<100000; i++) fS=fS+0.1; printf( "valeur theorique %f et valeur apres calcul %f\n",11000.0,fS); system("PAUSE"); return 0; }

int main(void) { puts("*********************************************************"); puts(" \ttaille en octet, valeur min et max pour chaque type "); puts("*********************************************************"); puts(""); printf("type \t|%10s|%15s|%15s|\n","taille","min","max"); puts("___________________________________________________"); printf("char \t|%10d|%15d|%15d|\n",sizeof(char),CHAR_MIN,CHAR_MAX); printf("short \t|%10d|%15d|%15d|\n",sizeof(short),SHRT_MIN,SHRT_MAX); printf("int \t|%10d|%15d|%15d|\n",sizeof(int),INT_MIN,INT_MAX); printf("long \t|%10d|%15d|%15d|\n",sizeof(long),LONG_MIN,LONG_MAX); printf("float \t|%10d|%15e|%15e|\n",sizeof(float),pow(2,-126),pow(2,+128)); printf("double \t|%10d|%15e|%15e|\n",sizeof(double),pow(2,-1023),pow(2,1023)); puts("___________________________________________________"); system("PAUSE"); return 0; }

7) Rajouter la suite de la boucle for le mme calcul mais cette fois-ci en utilisant la variable dS de type double. Tester. Expliquer ! Calculs trigonomtriques Questions prliminaires : ouvrir math.h dans le rpertoire include. Le fichier math.h est un fichier de dclaration des fonctions mathmatiques utilisables en C. Comme tous les fichiers de dclarations de fonctions celui-ci est plac dans le rpertoire par dfaut des "include".

Travail faire
Comme pour chaque nouveau TP, crer un projet TP2 (Fichier , Nouveau, Projet, Application Console Win32, nom:tp2, puis fentre suivante , paramtres de l'application: projet vide). Pour chaque nouveau programme, ajouter le fichier cr au projet (Fichier source, clic droit, ajouter, nouvel lment et enlever le programme prcdent.

Rechercher la fonction sin. 5) Ecrire un programme tp2_exo5.c qui demande une valeur de dbut, une valeur de fin et qui affiche toutes les valeurs comprises entre dbut et fin sauf celle gale debut+2
_CRTIMP double __cdecl sin (double);

Cette ligne signifie que la fonction sin prend en argument un "double" et renvoie un "double". 8) Les fonctions cos, exp, log10,tan, cosh, sqrt existe-t-elle ? Si oui quel est le but de chacune de ces fonctions De la mme faon rechercher (CTR+F) la ligne contenant PI (ne pas cocher mot entier).
#define M_PI 3.14159265358979323846

9) Quelles sont les valeurs de M_E et M_PI_2 ? L'utilisation du fichier de dclaration peut tre une source d'information pour la comprhension et la dcouverte des fonctions utilisables par le programmeur. Une autre source d'information pour le programmeur est videmment l'utilisation de l'aide (touche F1). Nous allons utiliser l'aide de VC++ express. L'aide de VC++ est trs bien documente et doit tre utilise le plus possible. Taper F1 pour ouvrir la fentre d'aide. Puis rechercher math routines puis math constant.

08/08/2007

JLS

page 19/56

08/08/2007

JLS

page 20/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

L'aide explique qu'il existe des constantes mathmatiques utiles pour le programmeur. Pour pouvoir utiliser ces constantes, le programmeur doit taper les 2 lignes suivantes en dbut de programme :
#define _USE_MATH_DEFINES #include <math.h>

L'aide en plus des explications sur les fonctions mathmatiques vous fournit un exemple (clic sur example). 10) Ecrire un programme qui affiche le cosinus,le sinus et la tangente de 45 . On pourra s'aider de l'exemple et le modifier.

Une autre solution consiste utiliser les pragma ou directives. Ces pragma commencent par # . Dans l'exemple ci-dessous aprs l'insertion de la bibliothque math.h se trouvant dans le rpertoire par dfaut des "include" les lignes suivantes dfinissent M_PI seulement si M_PI n'est pas dfini. Le compilateur C issu du GNU (Linux) gcc possde lui une bibliothque mathmatique math.h dans laquelle M_PI est dfini. Le code ci-dessous permet donc une compilation du programme avec VC++ ou bien avec gcc.
#include <math.h> #ifndef M_PI #define M_PI #endif 3.14159265358979323846

08/08/2007

JLS

page 21/56

08/08/2007

JLS

page 22/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

11) Tester le programme ci-dessous :


#define _USE_MATH_DEFINES #include <math.h> #include <stdio.h> int main() { double dy; printf("log10(%g)=%g\n",10.0,log10(10)); dy=exp(1); printf("exp(%g)=%g\n",1.0,dy); printf("M_E=%g\n",M_E); printf("cos(10)=%g\n",cos(M_PI/180*10)); system("PAUSE"); return 0; }

Rsolution d'quation du second degr On dsire crire un programme de rsolution d'quation du second degr. Ce programme rsout lquation ax2+bx+c=0 o les coefficients a,b,c sont entrs au clavier. Le rsultat est ensuite affich. Pour le calcul de la racine carre, on utilise la fonction sqrt() dfinie dans la bibliothque <math.h>
double dy= sqrt(4.0); // rsultat dy=2.0.

Si le coefficient a est non nul, lorganigramme du programme est le suivant :


d = b2 - 4ac NON OUI

d<0

On dsire crire un programme qui affiche une table de trigonomtrie. Le programme demande initialement les angles de dbut et de fin, ainsi que le pas, le tout en degr. Lorganigramme du programme est le suivant: Algorithme entre de inf, sup, step lire les valeurs de inf, sup et step (en degr) Pour i=inf jusqu' sup (par pas de step) k transformer i en radian calculer puis afficher sin(k),cos(k) et tg(k) FinPour
NON

NON

d==0

OUI

pas de racines relles

deux racines relles x1 = -b - d / 2a x2 = -b + d / 2a

une racine relle x1 = -b / 2a

deg = inf

OUI

deg<sup

14) Ecrire le programme dont le cahier des charges est donn ci-dessus .
calculer les valeurs des sin, cos tg et les afficher ...

15) Modifier le programme pour que celui-ci fonctionne sans aucune restriction sur a, b et c. Faire lorganigramme de ce programme puis l'crire et le tester.

deg = deg + step

Rsultat du programme : On prendra soin d'utiliser les types qui conviennent pour le calcul des cos, sin et tan. 12) Ecrire le programme dont le cahier des charges a t donn ci-dessus. 13) Modifier le code pour que lorsqu'une valeur est suprieure une constante MAX (par exemple 100000) le programme affiche INFINI. 08/08/2007 JLS page 23/56 08/08/2007 JLS page 24/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Travail faire :

TP3

Algorithmique 1
Thmes
Algorithmique de base : utilisation de toutes les structures de contrle. Utilisation des fonctions ceil et floor et pow.

5) En utilisant l'aide de VC++ rechercher la fonction pow. L'aide tant en anglais, expliquer les lignes suivantes tires de l'aide :
The pow function computes x raised to the power of y.

Prparation
1) Donner le rsultat de l'extrait ci-dessous. Expliquer chacun des rsultats affichs l'cran.
int main() { int nA = 2, nB= 0,nRes ; nRes=(5==5)&&(6==2); printf("1:%d\n",nRes); nRes=(5>1)||(6>8); printf("2:%d\n",nRes); nRes=(nA == (nB+2)); printf("3:%d\n",nRes); nB += 4; printf("4:%d\n",nB); nA=5;nB=6; if(nA != nB) puts("5:nA different de nB"); nA %= 2; printf("6:%d\n",nA); if((nA>0)&&(nA<6)) puts("7:nA compris entre 1 et 5"); nA=0; if((nA>0)||(nA<6)) puts("8:nA compris entre 1 et 5"); system("PAUSE"); return 0; }

double pow( double x, double y );


rsultat de l'aide :

2) Evaluer nRes pour n =2 et n=10, on suppose que nRes et n sont des entiers.
nRes= nRes= nRes= nRes= (n==1)||(n>=2); (n==0)||((n>=2)&&(n<9)); (n==1)||(n>=2)||(n<9); (n=1)||((n>=2)&&(n<9));

3) Donner le rsultat affich par l'extrait suivant (n est un entier) et expliquer.


n=3; if (n=5) puts("n=5"); n=3; if (n) puts("n"); if (n<4) puts("n<4");

4) Ecrire un programme qui affiche tous les entiers de 8 jusqu 23 (bornes incluses) en utilisant une structure en for puis en while.

08/08/2007

JLS

page 25/56

08/08/2007

JLS

page 26/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

6) Ecrire un programme qui lit une valeur entire et affiche les 10 premires puissances de cette valeur (prendre la fonction pow() dfinie dans <math.h>.

14) Ecrire un programme qui calcule le carr de la valeur entire saisie par l'utilisateur et l'affiche. Le programme demande une valeur entire, calcule le carr de cette valeur, l'affiche et recommence tant que cette valeur est suprieure 0. Ensuite le programme affiche la somme des carrs calculs. Questions diffrencies : Ne traiter ici qu'une question sur les 3 proposes (questions 15, 16, 17 ). Demander l'enseignant quelle question vous devez traiter. 15) Ecrire un programme qui permet de faire des oprations sur un entier (valeur initiale 0). Le programme affiche la valeur de l'entier puis affiche le menu suivant : 1. Ajouter 1 2. Multiplier par 2 3. diviser par 2 4. Quitter

7) Grce l'aide de VC++ (touche F1) rechercher le but des fonctions ceil et floor. L'aide de la fonction floor fournit un exemple. Recopier et commenter cet exemple dans le compte-rendu. 8) Ecrire un programme qui demande l'utilisateur d'entrer un chiffre virgule et qui arrondit l'entier le plus proche. On utilisera pour cela la fonction floor() pour rcuprer la partie entire du chiffre et on comparera le chiffre virgule la valeur entire trouve + 0.5. Questions diffrencies : Ne traiter ici qu'une question sur les 3 proposes (questions 9, 10, 11 ). Demander l'enseignant quelle question vous devez traiter. 9) Ecrire un programme qui demande lutilisateur de taper 10 entiers et qui affiche leur somme. 10) Ecrire un programme qui demande lutilisateur de taper 10 entiers et qui affiche le plus petit de ces entiers. 11) Ecrire un programme qui demande l'utilisateur de taper un entier N et qui calcule u(N) dfini par : u(0)=3 u(n+1)=3.u(n)+4 Questions diffrencies : Ne traiter ici qu'une question sur les 3 proposes (questions 12, 13, 14 ). Demander l'enseignant quelle question vous devez traiter. 12) Ecrire un programme qui demande l'utilisateur de taper une valeur entire comprise entre 1 et 10 inclus et ce jusqu' ce que l'utilisateur entre une valeur en dehors des limites. Le programme affiche alors la somme de tous les nombres saisis except le dernier (qui tait en dehors des limites). 13) Ecrire un programme qui demande l'utilisateur une lettre et ce tant que la lettre saisie n'est pas une voyelle. Le programme affiche alors le nombre de 'b' entrs par l'utilisateur. L'utilisateur devra saisir une lettre suivie du retour chariot chaque nouveau passage dans la boucle. Utiliser getchar pour lire le caractre. Attention au retour chariot qui est vue comme un caractre!

Le programme demande alors de taper un entier entre 1 et 4. Si l'utilisateur tape une valeur entre 1 et 3, on effectue l'opration, on affiche la nouvelle valeur de l'entier puis on raffiche le menu et ainsi de suite jusqu' ce qu'on tape 4. Lorsqu'on tape 4, le programme se termine. 16) Ecrire un programme qui permet d'afficher le code ASCII de certaines lettres de la table. Le programme affiche le menu suivant : 1. Afficher le code ASCII des chiffres 2. Afficher le code ASCII des lettres minuscules 3. Afficher le code ASCII des lettres majuscules 4. Quitter

Le programme demande alors de taper un entier entre 1 et 4. Si l'utilisateur tape une valeur entre 1 et 3, on affiche les codes ASCII demands puis on raffiche le menu et ainsi de suite jusqu' ce qu'on tape 4. Lorsqu'on tape 4, le programme se termine. 17) Ecrire un programme qui permet d'afficher un certain nombre de calcul sur un entier pralablement saisi par l'utilisateur. Le programme aprs avoir lu la valeur entire n, affiche le menu suivant : 1. Afficher la somme de 1 n 2. Afficher la somme des carr :1 + 2*2 + 3*3 + .. + n*n 3. Afficher si n est pair ou impair 4. Quitter

Le programme demande alors de taper un entier entre 1 et 4. Si l'utilisateur tape une valeur entre 1 et 3, le programme effectue le calcul demand puis raffiche le menu et ainsi de suite jusqu' ce qu'on tape 4. Lorsqu'on tape 4, le programme se termine. La valeur n est saisie une seule fois en dbut de programme.

08/08/2007

JLS

page 27/56

08/08/2007

JLS

page 28/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

TP4

Algorithmique 2
Thme
Programmation avec toutes les structures de contrles. Utilisation des fonctions srand et rand.

4) Que fait le programme suivant si on rentre 12


#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char c1,c2; printf("saisie de 2 caracteres>"); c1=getchar(); c2=getchar(); printf("%c%c\n",c1,c2); printf("saisie de 2 caracteres>"); c1=getchar(); c2=getchar(); printf("%c%c\n",c1,c2); system("PAUSE"); return 0; }

puis 23

? Expliquer.

Prparation
1) Ecrire un programme permettant d'afficher les 10 premiers nombres pairs. Utiliser un boucle for, while et do while.

Rappel sur les oprateurs modulo et ET logique: si a est impair a%2 renvoie 1 et si a est pair a%2 renvoie 0. Si a est impair a&1 renvoi 1 et si a est pair a&1 renvoi 0 (Cf TD3). 2) Que fait le programme suivant si on rentre 12
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char c1,c2; printf("saisie de 2 caracteres>"); scanf("%c%c",&c1,&c2); printf("%c%c\n",c1,c2); printf("saisie de 2 caracteres>"); scanf("%c%c",&c1,&c2); printf("%c%c\n",c1,c2); system("PAUSE"); return 0; }

puis 23

? Expliquer.

5) Donner une solution ce problme en utilisant getchar(). 6) Ecrire un programme qui demande l'utilisateur d'entrer 2 caractres. Si le premier caractre est un 'a' et le deuxime est un 'z' alors sortir du programme et afficher le nombre de mauvaise rponse sinon redemander l'utilisateur d'entrer 2 caractres (ne pas utiliser la fonction strcmp pour ce problme Cf TP7).

Travail faire
Nombre d'Armstrong On dnomme nombre de Armstrong un entier naturel qui est gal la somme des cubes des chiffres qui le composent. Exemple : 153 = 1 + 125 + 27, est un nombre de Armstrong. SOLUTION 1 :
On sait qu'il n'existe que 4 nombres de Armstrong, et qu'ils ont tous 3 chiffres (ils sont compris entre 100 et 500). L'ide consiste donc balayer tous les nombres de 100 500 (1 boucle ) et pour chaque nombre de tester si celui-ci est un nombre d'Armstrong (somme des centaine, dizaine, unit) Pour dcomposer un nombre en centaine, dizaine, unit, il suffit de se rappeler que 153/100 =1 et que 153 %100=53. 53/10=5 et 53%10=3. Donc grace des divisions entires et des restes de divisions (modulo) il est possible de trouver les 3 chiffres (centaine, dizaine et unit) constituant le nombre. Il ne reste plus qu' calculer la somme des cubes de ces 3 chiffres et de tester le rsultat au nombre.

Remarque : comme il a t vu dans le TD2, les fonctions scanf() ou getchar() sont bloquantes.: tant que l'utilisateur n'a pas tap sur le retour chariot, le programme reste bloqu sur la fonction de lecture. Les caractres taps sont placs par le systme d'exploitation dans un buffer qui est lu aprs saisi du retour chariot. Dans ce buffer se trouvent les caractres entrs mais aussi le code ASCII du retour , se trouvent dans le buffer de saisi 3 caractres (et chariot. Ainsi si l'utilisateur entre '1' , '2' suivi de non pas 2 comme on pourrait le supposer). Donc si l'on veut lire 2 caractres il faudra en fait lire les 2 caractres + le retour chariot. 3) Donner une solution ce problme).

SOLUTION 2 Sachant qu'un nombre est crit ijk (i chiffre des centaines, j chiffres des dizaines et k chiffres des units), il suffit simplement d'envisager tous les nombres possibles en faisant varier les chiffres entre 0 et 9 et de tester si le nombre est de Armstrong. (3 boucles for imbriqus). Nombres de Armstrong: 08/08/2007 JLS page 29/56 08/08/2007 JLS page 30/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

153 370 371 407 7) Ecrire le programme qui affiche les nombres d'Armstrong selon la mthode de la solution 1. 8) Ecrire le programme qui affiche les nombres d'Armstrong selon la mthode de la solution 2. Gnration de nombres alatoires La bibliothque standard comprend un gnrateur de nombres pseudo-alatoire et une fonction qui initialise l'amorce de cette srie de nombres: - int rand(void) : retourne un nombre entier pseudo-alatoire compris entre 0 et 32767 - void srand(unsigned int amorce) : donne une valeur initiale rand(). exemple d'une fonction qui remplit alatoirement un tableau de 10 entiers compris entre MIN et MAX
#include #include #include #include <stdio.h> <stdlib.h> <math.h> <time.h>

10) Ecrire un programme permettant de savoir si un nombre est premier (un nombre est premier s'il n'est divisible que par 1 et par lui-mme). Le principe est une boucle for, dans laquelle on calcule n%i avec i variant de 2 n-1. Ds que ce modulo est gal 0, le nombre n'est pas premier( il est au moins divisible par i). Il faut alors sortir de la boucle (break;). Si en sorti de la boucle for, i est gal n cela veut dire que n n'est pas divisible et donc est un nombre premier.

11) Ecrire un programme qui saisit un nombre et affiche tous les nombres premiers infrieurs ou gaux ce nombre.

Remarque :Un nombre pair ne peut pas tre premier. On pourra utiliser ce principe pour rduire les tests de nombre premier.

#define MAX 10 #define MIN 1 int main(void) { int i;int nVal; srand(time(0)); /* utilisation de l'horloge pour initialiser la suite */ for (i=0;i<10;i++) { nVal=rand()%MAX +MIN; // nVal compris entre 1 et N printf("%d ", nVal); } puts(""); system("PAUSE"); return 0; }

9) Faire 20 tirages alatoires de nombres compris entre 0 et 3 et compter le nombre d'occurrence de chaque chiffre. Puis afficher sous forme d'histogramme, afficher le max et le min et la moyenne de la squence.

08/08/2007

JLS

page 31/56

08/08/2007

JLS

page 32/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

TP5

Tableaux et chanes de caractres


Thme
Programmation avec toutes les structures de contrles. Utilisation des tableaux et chanes de caractres. Mthodes de tri de tableau (tri par slection et tri bulle)

Prparation
1) Ecrire un programme qui initialise un tableau d'entier avec les valeurs 2,4,5,6,8,10 au moment de la dclaration du tableau et qui calcule la somme de ce tableau. 2) Ecrire un programme qui initialise une chane de caractre avec la valeur "bBoOnN23" au moment de la dclaration et qui n'affiche avec la fonction putchar que les caractres en minuscule (donc le programme affiche BON); 3) Ecrire un programme qui demande l'utilisateur de saisir 10 entiers stocks dans un tableau ainsi qu'un entier V. Le programme doit rechercher si V se trouve dans le tableau et afficher "V se trouve dans le tableau" ou "V ne se trouve pas dans le tableau".

N=>3 --* --** * --*** ** * FIN DU PROGRAMME

6) Ecrire un programme qui demande l'utilisateur de saisir un entier N . Si le nombre est pair et compris entre 1 et 10 le programme affiche un carr de N*', si le nombre est impair et compris entre 1 et 10 le programme affiche un carr de N#' . Le programme s'arrte si l'utilisateur entre une valeur infrieure 1 ou suprieure 10. Ci-dessous est affich une copie d'cran du programme avec en GRAS la saisie de l'utilisateur.
N=>3 ### ### ### N=>2 ** ** N=>0 FIN DU PROGRAMME

Travail faire
Questions diffrencies : Ne traiter ici qu'une question sur les 3 proposes. Demander l'enseignant quelle question vous devez traiter. 4) Ecrire un programme qui demande l'utilisateur de saisir un entier N et qui affiche un triangle invers de N lignes. Ce programme recommence une nouvelle saisie d'un entier N et affiche le triangle associ jusqu' ce que l'utilisateur entre une valeur nulle ou infrieure 0. Cidessous est affich une copie d'cran du programme avec en GRAS la saisie de l'utilisateur.
N=>1 * N=>2 ** * N=>3 *** ** * N=>0 FIN DU PROGRAMME

Questions diffrencies : Ne traiter ici qu'une question sur les 3 proposes. Demander l'enseignant quelle question vous devez traiter. 7) Ecrire un programme qui demande l'utilisateur de saisir 10 notes comprises entre 0 et 20 qui seront stocks dans un tableau. Le programme doit alors traiter le tableau et compter et afficher le nombre de notes comprises entre 0 et 5,.comprises entre 6 et 10, entre 11 et 15 et entre 16 et 20. 8) Ecrire un programme qui demande l'utilisateur de saisir 10 nombres rels qui seront stocks dans un tableau. Le programme doit alors traiter le tableau et afficher la somme de ces nombres, la moyenne et le nombre minimum de ce tableau. 9) Ecrire un programme qui demande l'utilisateur de saisir 10 caractres qui seront stocks dans un tableau. Le programme doit alors traiter le tableau et compter le nombre de voyelles, de consonnes et de chiffres entres. Questions diffrencies : Ne traiter ici qu'une question sur les 3 proposes. Demander l'enseignant quelle question vous devez traiter.

5) Ecrire un programme qui demande l'utilisateur de saisir un entier N et qui affiche tous les triangles inverss de 1 ligne jusqu' N lignes, chaque triangle tant spar par une ligne de N caractres '-'. Ci-dessous est affich une copie d'cran du programme avec en GRAS la saisie de l'utilisateur.

08/08/2007

JLS

page 33/56

08/08/2007

JLS

page 34/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

10) Ecrire un programme qui demande l'utilisateur d'entrer un phrase (utiliser gets) . Le programme donne la premire lettre et la dernire lettre de la phrase. 11) Ecrire un programme qui demande l'utilisateur d'entrer une phrase et qui compte le nombre d'espace dans la phrase. 12) Ecrire un programme qui demande l'utilisateur de taper une lettre et qui affiche le nombre de fois ou la lettre est dans le mot cach. Mthodes de tri de tableaux : Ne traiter qu'un problme sur 2. Demander l'enseignant lequel vous devez traiter. 13) Ecrire un programme qui demande lutilisateur de taper 4 entiers qui seront stocks dans un tableau. Le programme doit trier le tableau par ordre croissant et doit afficher le tableau. Algorithme suggr : Tri par slection : On cherche l'indice du plus petit lment parmi les indices de 0 4 et on change cet lment avec t[0]. On cherche l'indice du plus petit lment parmi les indices de 1 4 et on change cet lment avec t[1]. On cherche l'indice du plus petit lment parmi les indices de 2 4 et on change cet lment avec t[2]. On cherche l'indice du plus petit lment parmi les indices de 3 4 et on change cet lment avec t[3]. Exemple de traitement : 24 5 5 5 5 24 9 9 100 9 100 9 100 24 24 100 recherche min de 0 n-1 (ici la valeur 5, case 1), permutation de la case 1 et 0 recherche min de 1 n-1,(ici la valeur 9, case 3) permutation de la case 3 et 1 recherche min de 2 n-1, (ici la valeur 24, case 3) permutation de la case 3 et 2 fin du programme : indice courant = n-1

24

100 9

teste case 2 et 3 : 100 > 9 : permutation

On recommence 5 24 9 100 teste case 0 et 1 : pas de permutation 5 5 24 9 9 24 100 teste case 1 et 2 : permutation 100 teste case 2 et 3 :pas de permutation

On recommence 5 9 24 100 teste case 0 et 1: pas de permutation 5 5 9 9 24 24 100 teste case 1 et 2: pas de permutation 100 teste case 2 et 3: pas de permutation

Il n'a pas eu de permutation donc le tableau est tri.

14) Ecrire un programme qui demande lutilisateur de taper 10 entiers qui seront stocks dans un tableau. Le programme doit trier le tableau par ordre croissant et doit afficher le tableau. Algorithme suggr: (tri bulle) On parcourt le tableau en comparant t[0] et t[1] et en changeant ces lments s'ils ne sont pas dans le bon ordre. on recommence le processus en comparant t[1] et t[2],... et ainsi de suite jusqu' t[3] et t[4]. On compte lors de ce parcours le nombre d'changes effectus. On fait autant de parcours que ncessaire jusqu' ce que le nombre d'changes soit nul : le tableau sera alors tri. Exemple de traitement :

24 5

5 24

100 9 100 9

teste case 0 et 1 : 24>5 : permutation teste case 1 et 2 : 24<100 :pas de permutation JLS page 35/56 08/08/2007 JLS page 36/56

08/08/2007

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

TP6

Les fonctions
Thmes
Les fonctions. Variables locales et variables globales. Les chanes de caractres

Prparation
1) Complter le programme ci-dessous. Pour cela crire le code main permettant d'afficher le min, le max et la moyenne de 2 nombres saisis. On utilisera les 3 fonctions dont le code est donn ci-dessous :
#include <stdio.h> // code des fonctions int mini(int ia,int ib) { if(ia>ib) return ib; else return ia; } int maxi(int ia,int ib) { if(ib>ia) return ib; else return ia; } double moyenne(int ia,int ib) { // a complter } // fonction principale int main(void) { int ia,ib; //a complter } }

printf("\n>"); scanf(" %c",&com); switch (com) { case '-': scanf("%d",&n); iMemoire=iMemoire-n; break; case '+': scanf("%d",&n); iMemoire=iMemoire+n; break; case '=': printf("%d",iMemoire); break; case 'z': iMemoire=0; break; case 'q': break; default : printf("?\n"); } } while ( com != 'q' ) ;

Dire ce qu'il se passe lorsque l'utilisateur entre ceci : -2 +3 = z = +3 +3 = q 3) Ajouter les fonctionnalits multiplication et division ce programme. 4) Que se passe-t-il si on remplace l'instruction scanf(" %c",&com); par l'instruction com=getchar() ? Expliquer.

2) tudier le programme suivant :


#include <stdio.h> int main(void) { char com; int iMemoire,n; iMemoire=0; do {

08/08/2007

JLS

page 37/56

08/08/2007

JLS

page 38/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

On dsire dcouper le programme prcdent en fonctions. Pour cela 2 solutions : Utilisation d'une variable globale giMemoire. Utilisation de variables locales seulement. 5) Complter le programme ci-dessous qui utilise une variable globale giMem :
#include <stdio.h> // variables globales int giMem; // dclaration des fonctions void addition(int n); void soustraction(int n); void raz(void); void affiche(void); // fonction principale int main(void) { char com; int n;

6) Complter le programme ci-dessous qui n'utilise pas de variables globales


#include <stdio.h> // dclaration des fonctions // A complter // fonction principale int main(void) { char com; int n, int iMemoire;

do { printf("\n>"); scanf(" %c",&com); switch (com) { case '-': scanf("%d",&n); iMemoire=soustraction(iMemoire,n); break; case '+': scanf("%d",&n); iMemoire=addition(iMemoire,n); break; case '=': afficher(iMemoire); break; case 'z': iMemoire=0; break; case 'q': break; default : printf("?\n"); } } while ( com != 'q' ) ; } // code des fonctions int addition(int iMem,int n) { // a complter } int soustraction(int iMem,int n) { // a complter } void afficher(int iMem) { // a complter }

do { printf("\n>"); scanf(" %c",&com); switch (com) { case '-': scanf("%d",&n); soustraction(n); break; case '+': scanf("%d",&n); addition(n); break; case '=': affiche(); break; case 'z': raz(); break; case 'q': break; default : printf("?\n"); } } while ( com != 'q' ) ; } // code des fonctions void addition(int n) { // A complter } void soustraction(int n) { // A complter } void raz(void) { giMemoire=0; } void affiche(void) { // A complter }

7) Comparer les 2 solutions et conclure .

Travail faire
Nombre parfait: Objectif : On souhaite crire un programme de test de nombres parfaits. Un nombre est dit parfait sil est gal la somme de ses diviseurs, 1 compris. Exemple : 6 = 1+2+3 , est un nombre parfait (1 , 2 et 3 sont des diviseurs de 6) 28=14+7+4+2+1 est un nombre parfait (14, 7 , 4 , 2 et 1 sont des diviseurs de 28) 496 est un nombre parfait 8128 est un nombre parfait JLS page 39/56 08/08/2007 JLS page 40/56

08/08/2007

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Pour savoir si un nombre est parfait ou non, il suffit de prendre toutes les valeurs infrieures ce nombre et incrmenter les valeurs qui sont des diviseurs de ce nombre. Ecrire un programme qui teste si un nombre est parfait . Ecrire le code de 2 faons : 8) solution 1 : code monolithique (sans utilisation de fonctions,) tout le traitement est fait dans la fonction main(). 9) solution 2 : code avec fonction; crire le code de la fonction int isParfait(int n) qui renvoie 1 (vrai) si n est un nombre parfait ou 0 (faux)dans le cas contraire. La fonction main utilise la fonction isParfait pour testerr si le nombre entr est parfait ou non .

Test palindrome Une phrase est dite palindrome si en liminant les blancs entre les mots elle reprsente la mme lecture dans les deux sens : Exemple : "elu par cette crapule" compresser : "eluparcettecrapule" inverser : "eluparcettecrapule" il y a galit entre les 2 chaines de caractres donc la phrase est un palindrome ! 12) Exemple de la fonction inverser : Ecrire les 3 fonctions de compression, inversion et de test d'galit de2 chanes de caractres, puis appeler ces fonctions dans la fonction main pour obtenir le rsultat suivant. La chaine de test sera initialis la dclaration ( prendre "elu par cette crapule"). Utiliser la fonction strcpy pour copier cette chaine (aprs compression) dans la chaine inverser. tester ensuite les 2 chaines (une compress et l'autre compress + invers) et crire palindrome en cas d'galit ou pas un palindrome dans le cas contraire.

10) Amlioration :Tant que l'utilisateur n'a pas entr un nombre parfait, recommencer. Ecrire ce nouveau programme.

Rsultat Travail sur les chaines de caractres On dsire crire le programme suivant :

Ce programme utilise les fonctions mettre_en_majuscule(), longueurChaine( taille de la chaine),nbVoy(nombre de voyelles de la chaines) ,nbLettre (nombre de lettres) ,nbChar(). 11) Ecrire le code de ces fonctions.
int main(void) { char sz[40]; puts("entrer un mot"); gets(sz); mettre_en_majuscule(sz); puts(sz); printf("taille du mot %d\n",longueurChaine(sz)); printf("le nombre de consonne %d\n",nbCons(sz)); printf("le nombre de voyelle %d\n",nbVoy(sz)); printf("le nombre de lettre %d\n",nbLettre(sz)); printf("le nombre de caractere e %d\n",nbChar(sz,'E')); while(1); }

08/08/2007

JLS

page 41/56

08/08/2007

JLS

page 42/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Algorithme suggr :

TP7

Chane de compilation, fonctions et pointeurs


Thmes
Les fonctions. Passages de paramtres par pointeurs. Role du prprocesseur, introduction aux macros. Introduction au langage assembleur. Chane de compilation. Compilation de plusieurs fichiers, notion de projet.

compteur =0 Faire lire chane de caractres si la chane de caractre lue est diffrente "az" incrmenter compteur TantQue (chane de caractre lue est diffrente "az") Afficher "gagne en <compteur> coup"

Rappels sur la chane de compilation : le prprocesseur


Role du prprocesseur : La compilation d'un programme se fait en 2 passes : La premire passe appele prprocesseur a pour but dans le cas des #include de copier le contenu du fichier de dclaration spcifi la place de la directive #include et dans le cas des #define de remplacer les noms (dfinis par la directive #define) par leur valeur. Il est possible aussi de dfinir par le biais de la directive #define des macros qui sont des bouts de codes qui seront placer par le prprocesseur dans le programme la place de la macro. Prenons un exemple : dans le fichier ci-dessous 2 constantes N1 et N2 et 2 macros MAX et MIN sont dfinies. Nous avons aussi plac 2 fonctions max et min pour une comparaison avec les macros. Une nouvelle instruction a aussi t rajoute qui est une spcificit du language C .
(test) ?valeur1:valeur2;

Prparation
1) Ecrire une fonction f ayant en paramtres un tableau iT de taille quelconque et un entier iElem indiquant la taille du tableau. f doit renvoyer par un return le nombre de valeurs comprises entre 0 et 10 dans les iElem premires cases du tableau iTt. Tester cette fonction. 2) Reprendre l'exercice 6 du TP6 sur la machine calculer et modifier l'appel des fonctions soustraction et addition dans la fonction main. Ces fonctions ne renvoient rien et mettent jour la valeur pointe par piMem.
// code des fonctions void addition(int *piMem,int n) { // a complter } void soustraction(int *piMem,int n) { // a complter }

Dans le cas ou le test est vrai alors c'est la valeur1 qui est renvoye sinon c'est la valeur2. Cette instruction permet de remplacer une instruction if et n'existe que dans le langage C ( et donc C++) et a t cr pour permettre d'avoir un code compact comme c'est le cas pour les oprations unaires += -= etc Prenons un exemple : Le bout de code ci-dessous affiche 2 fois "ia=2".
int i=9,ia; ia=(i<0)?0:2; // si i<0 ia prend la valeur 0 sinon 2 printf("ia=%d\n",ia); if(i<0) // si i<0 ia prend la valeur 0 sinon 2 ia=0; else ia=2; printf("ia=%d\n",ia);

Travail faire
3) Ecrire le programme utilisant la fonction strcmp dfinie dans <string.h> permettant de tester 2 chanes de caractres, celle entre par l'utilisateur et "az". Tant que l'utilisateur n'a pas entr les caractres az celui-ci recommence. Ds que la squence a t trouve, le programme donne le nombre d'essais infructueux.

Programme de test permettant de montrer le role du prprocesseur. Exemple : la fonction strcmp renvoie 0 si sz1 est gal sz2 ou une valeur diffrente de 0 dans le cas contraire. Dans l'exemple ci-dessous, le programme affiche "different".
char sz1[20]="za",sz2[20]="az"; if(strcmp(sz2,sz1)==0) puts("identique"); else puts("different");

Chercher dans l'aide(F1) pour plus de dtail.

#include <stdio.h> // mes dfinitions de constantes #define N1 3 #define N2 5 // mes macros #define MAX(x,y) (((x)>(y))?(x):(y)) #define MIN(x,y) (((x)>(y))?(y):(x)) // mes fonctions int max(int ia,int ib) { return ((ia>ib)?ia:ib); }

08/08/2007

JLS

page 43/56

08/08/2007

JLS

page 44/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

int min(int ia,int ib) { if(ia>ib) return ib; else return ia; } // prog principal : test des fonctions min max et macros MIN et MAX int main(void) { printf("MAX:%d\n",MAX(N1,N2)); printf("MIN:%d\n",MIN(N1,N2)); printf("max:%d\n",max(N1,N2)); printf("min:%d\n",min(N1,N2)); system("PAUSE"); return 0; }

Programme aprs passage du prprocesseur : extrait du fichier tp7_exo4.i


// dclaration de printf __declspec(dllimport) int __cdecl printf( const char * _Format, ...);

int max(int ia,int ib) { return ((ia>ib)?ia:ib); } int min(int ia,int ib) { if(ia>ib) return ib; else return ia; } int main(void) { printf("MAX:%d\n",(((3)>(5))?(3):(5))); printf("MIN:%d\n",(((3)>(5))?(5):(3))); printf("max:%d\n",max(3,5)); printf("min:%d\n",min(3,5)); system("PAUSE"); return 0; }

4) Lancer le programme ci-dessus (tp7_exo4.c) et copier le rsultat obtenu dans le compte-rendu. Dans VC++ comme pour tous les compilateurs (gcc, borland C++,..) il est possible de visualiser le fichier cr par le prprocesseur. Sous VC++, ce fichier prend l'extension ".i". Pour visualiser ce fichier nous devons modifier une option du projet. Afficher les proprits du projet

On peut voir dans le programme ci-dessus que toutes les parties de code qui taient en #... ont t enleves. 5) Donner les diffrences entre les 2 fichiers tp7_exo4.c et tp7-exo4.i . Choisir la gnration du fichier aprs passage du prprocesseur 6) Ecrire le code de la fonction main utilisant les 3 directives prprocesseur ci-dessous et permettant de saisir un angle en radian puis l'afficher en degre (utilisation de RADTODEG). saisir un angle en degre et l'afficher en radian (utilisation de PI). saisir une valeur et donner sa valeur absolue (utilisation de ABS). En dduire ensuite le code gnr aprs le passage du prprocesseur.
#define RADTODEG(x) ((x) * 57.29578) #define ABS(x) ((x>0)?x:-x) #define PI 3.14159

Rappels sur la chane de compilation : le compilateur


Puis taper sur F7 (Gnrer la solution ) pour lancer le prprocesseur. Visualiser le fichier. Ce fichier possde un grand nombre de lignes inutiles qui seront traites par le compilateur. Allez en fin de fichier afin de visualiser le code main et le traitement fait par le prprocesseur. VC++ comme tous les compilateurs permet de visualiser un certain nombre de fichiers intermdiaires gnrs par le compilateur. Nous allons visualiser le fichier assembleur (extension .asm) gnr par le compilateur. Le but de cette manipulation est de comprendre la chane de compilation et le rle de chaque outil.

08/08/2007

JLS

page 45/56

08/08/2007

JLS

page 46/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

7) Crer un nouveau programme tp7_exo7.c et l'ajouter au projet tp7 (n'oubliez pas d'enlever l'ancien programme).Le code qui se veut trs simple va permettre de comprendre le travail effectu par le compilateur. tp7_exo7.c
#include <stdio.h> #define N1 3 #define N2 5 int main(void) { int ia,ib=N1,ic=N2; ia=ib+ic; ia=ib-ic; ia=ia<<1; if(ia==1) ib=5; else ib=8; while(1); return 0; }

extrait du fichier test.asm gnr dans le rpertoire RELEASE sous le rpertoire du projet tp7.
; 7 ; 8 : : mov add mov int ia,ib,ic; ia=ib+ic; eax, DWORD PTR _ib$[ebp] eax, DWORD PTR _ic$[ebp] DWORD PTR _ia$[ebp], eax

Ces instructions assembleurs ont un code machine qui est en mmoire RAM. Pour visualiser le code machine , il suffit de regnrer la solution mais cette fois-ci avec l'option Assembly et code machine. 8) Recopier le code assembleur associ la soustraction et au dcalage gauche. En dduire l'instruction assembleur associe la soustraction et au dcalage gauche. Quelle est l'instruction assembleur permettant de faire un test (if) ? Le code ci-dessous a t gnr avec l'option Assembly, code machine et source (/FAcs) dans Fichiers de sortie (compilateur C/C++) dans la fentre propritt du projet. Aprs gnration du projet (F7) le fichier tp7_exo7.cod est gnr dans le rpertoire RELEASE .
0002c 0002f 00032 8b 45 ec 03 45 e0 89 45 f8 mov add mov eax, DWORD PTR _ib$[ebp] eax, DWORD PTR _ic$[ebp] DWORD PTR _ia$[ebp], eax

Pour visualiser le fichier assembleur tp7_exo7.asm il suffit dans le menu Projet, Proprit (Alt + F7) de dsactiver l'optimisation du compilateur (en effet l'optimisation peut amener ne gnrer aucun code assembleur) puis dans fichier de sortie , slectionner "Assembly avec code source" qui permet de gnrer un fichier ayant le code C en commentaire et le code assembleur associ. Le code assembleur gnr est le langage comprhensible par le processeur PENTIUM. Avant l'apparition des langages volus, les programmeurs crivaient leurs programmes en assembleur. Certaines routines du BIOS et certains drivers sont toujours crits en assembleur.

adresse en RAM du programme

code machine en RAM

code assembleur associ au code machine (plus lisible)

Une autre solution pour voir le code assembleur est d'utiliser le dbogueur. Pour cela, mettre un point d'arrt (clic gauche du code stopper). Puis lancer le programme qui s'arrte sur le point d'arrt. Ensuite, il suffit dans le menu Debug, Fentre, afficher le code machine.

08/08/2007

JLS

page 47/56

08/08/2007

JLS

page 48/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

Le code assembleur associ chaque instruction en C apparat.

9) Expliquer pour chacune des 3 instructions assembleurs gnres partir de l'instruction ia=ib+ic; le role du registre d'instruction, de l'ALU, du compteur eip, du registre eax et du registre ebp. 10) Chaque instruction possde un code machine. Donner le code machine de add et sub. Le code machine de ces instructions est sur 16 bits. Or le code machine de ces instructions est sur 24 bits. Le dernier octet donne l'adresse des variables ia, ib et ic qu'il faut rajouter au registre ebp. Il est possible de visualiser la zone mmoire ou se trouve ia, ib et ic. Le compilateur n'est pas le dernier lment permettant de gnrer un excutable. Le Linker qui est appel la suite du compilateur permet de regrouper le code issu de la compilation du ou des fichiers du projet et aussi le code de fonctions utilises et issues de librairies (par exemple printf ou scanf) dj compiles. Afin de montrer le rle du linker , faire l'exercice ci-dessous :

Schma simplifi de la structure PENTIUM + RAM


RAM 0x0000
Dbut du prog

Dcoupe des blocs de fonctions en fichiers


11) Ecrire le code des fonctions marques A COMPLETER.
RAM
ia ib ic

#include <stdio.h> #include <time.h>


Zone de donnes

0x002C 0x002F 0x0032


Bus dadresse

8b 45 ec 03 45 e0 89 45 f8

Zone de programme

Bus De donnes
32 bits Registre dinstruction

Bus dadresse

Bus De donnes

+
ebp
32 bits

// remplir un tab de nEle avec la valeur n. void remplir_tab(int nTab[], int nElem, int n); // saisie du tab par l'utilisateur void saisir_tab(int nTab[], int nElem); // recherche du min du tab de nElem int min_tab(int nTab[], int nElem); // recherche du max du tab de nElem int max_tab(int nTab[], int nElem); // calcul de la moyenne du tab de nElem double moyenne_tab(int nTab[], int nElem); // crer un tab de nEle commenant nMin et finissant nMax void creer_tab_aleatoire(int nTab[], int nEle, int nMin, int nMax); #define N 5 int main(void) { int it1[N]; int it2[N]; int it3[N]; saisir_tab(it3,N); puts("t3"); affiche_tab(it3,N); remplir_tab(it2,N,2); puts("t2"); affiche_tab(it2,N); creer_tab_aleatoire(it1,N,1,19); puts("t1"); affiche_tab(it1,N); printf("min=%d\n",min_tab(it1,N)); printf("max=%d\n",max_tab(it1,N)); printf("moy=%g\n",moyenne_tab(it1,N)); system("PAUSE"); } // code des fonctions void remplir_tab(int nTab[], int nElem, int n) { for(i=0;i<nElem;i++) {

eip
Compteur dinstructions

eax
32 bits 32 bits

Unit arithmtique et logique

ALU
32 bits

Extrait du schma fonctionnel du CPU

08/08/2007

JLS

page 49/56

08/08/2007

JLS

page 50/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

nTab[i]=n; } } void saisir_tab(int nTab[], int nElem) { int i; for(i=0;i<nElem;i++) { printf("t[%d]=",i); scanf("%d",nTab[i]); } } int min_tab(int nTab[], int nElem) { // a complter } int max_tab(int nTab[], int nElem) { // a complter } double moyenne_tab(int nTab[], int nElem) { // a complter } // crer un tableau de nEle lments commenant nMin et finissant nMax void creer_tab_aleatoire(int nTab[], int nEle, int nMin, int nMax) { int i; srand(time(0)); for(i=0;i<nEle; i++) { nTab[i]= nMin+ (int) rand()%(nMax-nMin+1) ; } } void affiche_tab(int nTab[], int nEle) { // a complter }

Dcoupe en fichiers : exemple


Toutes les dclarations de fonctions doivent tre mises dans un fichier xxx.h Le code des fonctions est plac dans le fichier xxx.c Le compilateur doit compiler le fichier main.c et le fichier de bibliothque xxx.c. Les 2 fichiers compils se nomment main.obj et xxx.obj. L'diteur de lien va gnrer le fichier excutable en assemblant le code des fichiers objets xxx.obj et main.obj gnrs par le compilateur.

Dans le projet courant crer le fichier tableau.h ou se trouve toutes les dclarations (ou prototypes) des fonctions.

tableau.h
// remplir un tab de nEle avec la valeur n. void remplir_tab(int nTab[], int nElem, int n); // saisie du tab par l'utilisateur void saisir_tab(int nTab[], int nElem); // recherche du min du tab de nElem int min_tab(int nTab[], int nElem);

08/08/2007

JLS

page 51/56

08/08/2007

JLS

page 52/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

// recherche du max du tab de nElem int max_tab(int nTab[], int nElem); // calcul de la moyenne du tab de nElem double moyenne_tab(int nTab[], int nElem); // crer un tab de nEle commenant nMin et finissant nMax void creer_tab_aleatoire(int nTab[], int nEle, int nMin, int nMax); // afficher le tab de nEle void affiche_tab(int nTab[], int nEle);

Ensuite crer un nouveau fichier tableau.c ; ce fichier va accueillir le code des fonctions sur les tableaux.

Vous devriez avoir dans l'explorateur de projet , Fichiers sources , les 2 fichiers tableau.c et test.c. Ces 2 fichiers vont tre compils .

Fichier test.c
#include <stdlib.h> #include "tableau.h"

Puis ajouter tableau.c dans le projet existant.

#define N 5 int main(void) { int it1[N]; int it2[N]; int it3[N]; saisir_tab(it3,N); puts("t3"); affiche_tab(it3,N); remplir_tab(it2,N,2); puts("t2"); affiche_tab(it2,N); creer_tab_aleatoire(it1,N,1,19); puts("t1"); affiche_tab(it1,N); printf("min=%d\n",min_tab(it1,N));

08/08/2007

JLS

page 53/56

08/08/2007

JLS

page 54/56

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

UNSA/IUT de Nice - dpartement GEII

I1 - TP 1re Anne

printf("max=%d\n",max_tab(it1,N)); printf("moy=%g\n",moyenne_tab(it1,N)); system("PAUSE"); }

fonctions. Crer ensuite la fonction main.c dans laquelle sont appeles et testes les 2 fonctions. 14) Complter le schma ci-dessous :

Fichier tableau.c
// code des fonctions void remplir_tab(int nTab[], int nElem, int n) { for(i=0;i<nElem;i++) { nTab[i]=n; } } void saisir_tab(int nTab[], int nElem) { int i; for(i=0;i<nElem;i++) { printf("t[%d]=",i); scanf("%d",nTab[i]); } } int min_tab(int nTab[], int nElem) { // a complter } int max_tab(int nTab[], int nElem) { // a complter } double moyenne_tab(int nTab[], int nElem) { // a complter } // crer un tableau de nEle lments commenant nMin et finissant nMax void creer_tab_aleatoire(int nTab[], int nEle, int nMin, int nMax) { int i; srand(time(0)); for(i=0;i<nEle; i++) { nTab[i]= nMin+ (int) rand()%(nMax-nMin+1) ; } } void affiche_tab(int nTab[], int nEle) { // a complter }

mes_fonctions.c

main.c ? main.obj librairie (printf)

? mes_fonctions.obj

tp7_exo9.exe

15) Modifier le programme mes_fonctions.c et modifier le nom de la fonction carre en carre_bis. Gnrer la solution (F7) et vrifier que l'erreur vient du linker. Faire une faute dans la fonction carre_bis et vrifier que l'erreur est gnre par le compilateur.

Et s'il reste du temps ? 16) Crer un fonction permettant partir d'un tableau de nElem lment de renvoyer le min et l'indice du minimum. On suppose que le tableau ne possde pas de valeurs en double. Cette fonction sera ajoute au fichier tableau.c

12) Complter le code des fonctions de tableau.c et tester . 13) Crer un nouveau projet. Dans ce projet crer le fichier mes_fonctions.c dans lequel se trouve la fonction carre et cube qui prennent un entier en argument et renvoie le carr ou le cube de cet entier. Crer ensuite le fichier mes_fonctions.h ou se trouve les dclarations de ces 2 08/08/2007 JLS page 55/56 08/08/2007 JLS page 56/56