TP Informatique
TP Informatique
TP Informatique
I1 - TP 1re Anne
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; }
I1 - TP 1re Anne
I1 - TP 1re Anne
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,
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
I1 - TP 1re Anne
I1 - TP 1re Anne
\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
I1 - TP 1re Anne
I1 - TP 1re Anne
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;
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.
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");
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
I1 - TP 1re Anne
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
I1 - TP 1re Anne
I1 - TP 1re Anne
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.
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.
08/08/2007
JLS
page 11/56
08/08/2007
JLS
page 12/56
I1 - TP 1re Anne
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)
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
I1 - TP 1re Anne
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)
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); }
13) 14)
Existe-t-il une diffrence entre putchar(i) et printf("%c",i) ? Donner le rsultat de la ligne suivante
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
I1 - TP 1re Anne
I1 - TP 1re Anne
TP2
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
I1 - TP 1re Anne
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
I1 - TP 1re Anne
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
I1 - TP 1re Anne
I1 - TP 1re Anne
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.
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
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.
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
I1 - TP 1re Anne
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; }
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));
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
I1 - TP 1re Anne
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
I1 - TP 1re Anne
I1 - TP 1re Anne
TP4
Algorithmique 2
Thme
Programmation avec toutes les structures de contrles. Utilisation des fonctions srand et rand.
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
I1 - TP 1re Anne
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
I1 - TP 1re Anne
I1 - TP 1re Anne
TP5
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".
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
I1 - TP 1re Anne
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
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
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
I1 - TP 1re Anne
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.
08/08/2007
JLS
page 37/56
08/08/2007
JLS
page 38/56
I1 - TP 1re Anne
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;
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 }
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
I1 - TP 1re Anne
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
I1 - TP 1re Anne
I1 - TP 1re Anne
Algorithme suggr :
TP7
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"
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");
#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
I1 - TP 1re Anne
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; }
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
08/08/2007
JLS
page 45/56
08/08/2007
JLS
page 46/56
I1 - TP 1re Anne
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.
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
I1 - TP 1re Anne
I1 - TP 1re Anne
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 :
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
ALU
32 bits
08/08/2007
JLS
page 49/56
08/08/2007
JLS
page 50/56
I1 - TP 1re Anne
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 }
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
I1 - TP 1re Anne
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"
#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
I1 - TP 1re Anne
I1 - TP 1re Anne
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
? 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