Séries des exercices
Transcription
Séries des exercices
Atelier de programmation 1 Première partie 1 Séries des exercices Atelier de programmation 1 Série1 : Introduction, Les bases du langage C Rappel du cours Comparons d'abord la définition du programme en C avec celle en langage algorithmique. HELLO_WORLD en langage algorithmique programme HELLO_WORLD | (* Notre premier programme en C *) | écrire "hello, world" fprogramme HELLO_WORLD en C #include <stdio.h> |main() |/* Notre premier programme en C */ |{ | printf("hello, world\n"); | return 0; |} Les noms des fonctions et des variables en C sont composés d'une suite de lettres et de chiffres. Le premier caractère doit être une lettre. Le symbole '_' est aussi considéré comme une lettre. * L'ensemble des symboles utilisables est donc: {0,1,2,...,9,A,B,...,Z,_,a,b,...,z} * Le premier caractère doit être une lettre (ou le symbole '_') - voir aussi Remarques -. * C distingue les majuscules et les minuscules, ainsi: 'Nom_de_variable' est différent de 'nom_de_variable' La fonction main est la fonction principale des programmes en C: Elle se trouve obligatoirement dans tous les programmes. L'exécution d'un programme entraîne automatiquement l'appel de la fonction main. Exercice 1 : Ecrire un programme qui affiche une date sous la forme jj/mm/aa en utilisant les fonctions de la librairie standard C. Exercice 2 : Qu'affichent les instructions suivantes: Atelier de programmation 1 int x = 9; int y = x + 10; printf("%d:%d:%d y", x, y, y ); a) 9:19:19:19 b) 9:19:19 y c) %d:%d:%d y Exercice 3 : Ecrire un programme qui affiche la taille des types suivants : char, int, float, double, short et long. Exercice 4 : Ecrire un programme qui affiche les 4 lignes suivantes : '/' = / '\' = \ ''' = ' '"' = " Exercice 5 : Ecrire un programme en C qui permet de calculer l’air et le périmètre d’un carré. Atelier de programmation 1 Correction de la Série1 Exercice 1 : #include ‘’stdio.h’’ Void main() { /* declaration des variables*/ Int j,m,a; /* saisie des donnees*/ printf("enter le jour"); scanf(”%i”,&j); printf("enter le mois"); scanf(”%i”,&m); printf("enter l’annee "); scanf(”%i”,&a); /* affichage du resultat */ printf(”la date est %2i/%2i/%2i”, j,m,a); } Exercice 2: Le programme affiche “9:19:19 y” Pour afficher un ensemble de variables il faut toujours mettre leurs types dans un message (exemple %i %c ou %f), et puis les citer dans l’ordre Exercice 3: #include ‘’stdio.h’’ Void main() { printf("\nTaille des types:\n"); printf(" char : %d\n", sizeof(char)); printf(" int : %d\n", sizeof(int)); printf(" float : %d\n", sizeof(float)); printf(" double : %d\n", sizeof(double)); Atelier de programmation 1 printf(" short : %d\n", sizeof(short)); printf(" long : %d\n", sizeof(long)); } Exercice 4 : #include ‘’stdio.h’’ Void main() { printf("\'/\' = / \n"); printf("\'\\\' = \\ \n"); printf("\'\'\' = \' \n"); printf("\'\"\' = \" \n"); } Exercice 5 : #include ‘’stdio.h’’ Void main() { float c, Perimetre, Aire ; printf("Donner le cote du carre") ; scanf("%f", &c) ; Perimetre=4*c ; Aire=c*c; printf("Le perimetre est %f", Perimetre); printf("L’aire est %f", Aire); } Atelier de programmation 1 Série 2: Les structures conditionnelles Rappel du cours On appelle structure conditionnelle les instructions qui permettent de tester si une condition est vraie ou non. La structure alternative en langage algorithmique si (<expression logique>) alors <bloc d'instructions 1> sinon <bloc d'instructions 2> finssi * Si l'<expression logique> a la valeur logique vrai, alors le <bloc d'instructions 1> est exécuté * Si l'<expression logique> a la valeur logique faux, alors le <bloc d'instructions 2> est exécuté La structure alternative en C les 'conditions' en C peuvent être des expressions quelconques qui fournissent un résultat numérique. La valeur zéro correspond à la valeur logique faux et toute valeur différente de zéro est considérée comme vrai. if ( <expression> ) <bloc d'instructions 1> else <bloc d'instructions 2> Switch : Selon valeur expression faire L'instruction switch permet de faire plusieurs tests de valeurs sur le contenu d'une même variable. Ce branchement conditionnel simplifie beaucoup le test de plusieurs valeurs d'une variable, car cette opération aurait été compliquée (mais possible) avec des if imbriqués. Sa syntaxe est la suivante : switch (Variable) { case Valeur1 : Liste d'instructions; break; case Valeur2 : Liste d'instructions; break; Default Liste d'instructions; } Atelier de programmation 1 Les parenthèses qui suivent le mot clé switch indiquent une expression dont la valeur est testée successivement par chacun des case. Lorsque l'expression testée est égale à une des valeurs suivant uncase, la liste d'instructions qui suit celui-ci est exécutée. Le mot clé break indique la sortie de la structure conditionnelle. Le mot clé default précède la liste d'instructions qui sera exécutée si l'expression n'est jamais égale à une des valeurs. N'oubliez pas d'insérer des instructions break entre chaque test, ce genre d'oubli est difficile à détecter car aucune erreur n'est signalée... En effet, lorsque l'on omet le break, l'exécution continue dans les blocs suivants ! ` Exercice 1 : Ecrire un programme qui calcule, le maximum de 2 entiers a et b et qui affiche le résultat à l’écran. Exercice 2 : Ecrire un programme qui détermine si un entier x est pair. Exercice 3 : On veut écrire un programme en C qui simule le traitement du jeu suivant : On a deux joueurs. Chaque joueur saisit un entier entre 0 et 6 Le programme calcule alors leur somme. Si la somme correspond au code ASCII d’une lettre voyelle le premier joueur obtient (26*code ASCII) points, le deuxième 10 points. Si la somme correspond au code ASCII d’un caractère numérique pair, le premier joueur obtient 10 points et le deuxième (26*code ASCII) points. Dans tous les autres cas, le joueur qui a donne la valeur la plus grande comme nombre de points. Le vainqueur est celui qui a obtenu le nombre de points le plus grand. Le programme affichera comme résultat le vainqueur ainsi que son nombre de points. Exercice 4 : Ecrire un programme C qui perm et d'effectuer les opérations simples (+, -, *, /). programme donnerait par exemple 5 + 11 = 15. Exercice 5 : Ecrire un programme qui permet de vérifier si une date est valide ou pas. On suppose que le jour, le mois et l’année sont des entiers, et (1900< année <2050). Atelier de programmation 1 Correction de la série 2 Exercice 1: #include ‘stdio.h’ void main( ) { int a,b; printf("Entrez un entier a: "); scanf("%d", &a); printf("Entrez un entier b: "); scanf("%d", &b); if(a>b) printf("\nLe maximum est: %d", a) ; else if(b>a) printf("\nLe maximum est: %d", b) ; else printf("\nles deux valeurs sont egales, Le maximum est %d", a ) ; } Exercice 2: #include ‘stdio.h’ void main( ) { int a; printf("Entrez un entier a: "); /* l’operateur modulo % retourne le reste d’une division entière*/ if(x%2==0) printf("\nL’entier est pair ") ; else printf("("\nL’entier est impair ") Atelier de programmation 1 } Exercice 3: #include ‘stdio.h’ void main( ) { int valJ1,valJ2,som,nbpoints1,nbpoints2; do{ printf("1er joueur :\n Donner un entier :"); scanf("%i",&valJ1); }while(valJ1<0||valJ1>61); do{ printf("\n 2eme joueur :\n Donner un entier :"); scanf("%i",&valJ2); }while(valJ2<0||valJ2>61); som=valJ1+valJ2; //conversion en miniscule if(som=='A'||som=='E'||som=='I'||som=='O'||som=='U'||som=='Y' ) som=som+'a'-'A'; switch(som) { case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': nbpoints1=26*som; nbpoints2=10; break; case '0': case '2': case '4': Atelier de programmation 1 case '6': case '8': nbpoints1=10; nbpoints2=26*som; break; default: if(valJ1>valJ2) nbpoints1=som; else if(valJ2>valJ1) nbpoints2=som; else { nbpoints1=valJ1; nbpoints2=valJ2; } } if (nbpoints1>nbpoints2) printf("Joueur1 est le vainqueur avec un score=%i ",nbpoints1); else if(nbpoints2>nbpoints1) printf("Joueur2 est le vainqueur \n score=%i",nbpoints2); else printf("Partie nulle "); } Exercice 4 #include ‘stdio.h’ void main( ) { float x,y,res; char op; int ind=0; printf("Donner le 1er operande :"); Atelier de programmation 1 scanf("%f",&x); printf("Donner l'operateur :"); scanf("%c",&op); printf("Donner le 2eme operande :"); scanf("%f",&y); switch(op) { case '+': res=x+y; break; case '-': res=x-y; break; case '*': res=x*y; break; case '/': if(y!=0) res=x/y; else { printf("diviseur nul ind=1 ; } break; default: printf("operateur erronee’’) ; } Exercice 5 : #include ‘stdio.h’ void main( ) { int jour, mois, annee, valide=1; do{ Atelier de programmation 1 printf("donner le jour"); scanf("%i", &jour); printf("donner le mois"); scanf("%i", &mois); printf("donner l'annee"); scanf("%i", &annee); if((annee<1900)&&(annee>2050)) valide=0; else { switch(mois) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: if(jour>31) valide=0; break; case 4: case 6: case 9: case 11: if (jour>30) valide=0; break; case 2: if ((jour>29)&&(((annee%4==0)&&(annee%100!=0))||( annee%400==0))) valide=0; else if((jour!=28)&&(!((( annee%4==0)&&(annee%100!=0))||(annee%400==0))) ) valide=0; break; Atelier de programmation 1 default: valide=0; } if (valide==0) printf("date invalide, saisissez une autre date"); else printf("date valide"); } } while (valide==0); } Atelier de programmation 1 Série 3: Les Structures répétitives Rappel du cours En C, nous disposons de trois structures qui nous permettent la définition de boucles conditionnelles: la structure : while while ( <expression> ) <bloc d'instructions> * Tant que l'<expression> fournit une valeur différente de zéro, le <bloc d'instructions> est exécuté. * Si l'<expression> fournit la valeur zéro, l'exécution continue avec l'instruction qui suit le bloc d'instructions. * Le <bloc d'instructions> est exécuté zéro ou plusieurs fois. la structure : do – while do <bloc d'instructions> while ( <expression> ); Le <bloc d'instructions> est exécuté au moins une fois et aussi longtemps que l'<expression> fournit une valeur différente de zéro. la structure : for Le plus souvent, for est utilisé comme boucle de comptage (le nombre d’itérations est connu au préalable) : for ( <init.> ; <cond. répétition> ; <compteur> ) <bloc d'instructions> <init> cette instruction est évaluée une fois avant le passage de la boucle. Elle est utilisée pour initialiser les données de la boucle. <cond> est évaluée avant chaque passage de la boucle. Elle est utilisée pour décider si la boucle est répétée ou non. <compteur> cette instruction est évaluée à la fin de chaque passage de la boucle. Elle est utilisée pour réinitialiser les données de la boucle. Atelier de programmation 1 Exercice 1 : Écrire un programme qui affiche la table de multiplication d’un entier n. Par exemple, pour n=4, la fonction affichera : 1x4=4 2x4=8 3 x 4 = 12 4 x 4 = 16 … 10 x 4 = 40 Exercice 2 : Ecrire la un programme qui permet d’afficher un ensemble d’étoiles sous cette forme (ici n vaut * ** *** **** ***** **** *** ** * Exercice 3 : Ecrire un programme qui affiche le minimum, le maximum et la moyenne d'une suite d'entiers positifs entrés au clavier. On arrêtera la saisie quand le nombre -1 est entré, comme dans l'exemple suivant : Entrez un entier positif : 5 Entrez un entier positif : 2 Entrez un entier positif : 3 Entrez un entier positif : -1 La valeur minimum est : 2 La valeur maximum est : 5 La moyenne de ces 3 entiers vaut 3.333333 Exercice 4 : Ecrire un programme en C qui affiche tous les nombres premiers compris entre [10…99]. Il existe Atelier de programmation 1 de nombreuses façons de savoir si un nombre est de la "taille" du nombre. Pour lintervalle [10,99]. il suffit de tester si le nombre est divisible par 2, 3, 5, 7. Atelier de programmation 1 Correction de la Série 3 Exercice 1 : #include ‘stdio.h’ void main( ) { int I,n; printf (“donner un entire n’’) ; scanf(“%i“, &n) ; for (i=1; i<=10; i++) { printf("%d x %d = %d\n", i, n, i*n); } } Exercice 2 : #include ‘stdio.h’ void main( ) { int I,n; int j; printf (“donner un entire n’’) ; scanf(“%i“, &n) ; for (i=1; i<=n; i++) { for (j=1; j<=i; j++) printf("*"); printf("\n"); } Atelier de programmation 1 for (i=n-1; i>=1; i--) { for (j=1; j<=i; j++) printf("*"); printf("\n"); } } Exercice 3 : #include ‘stdio.h’ void main( ) { int sum = 0; int count = 0; int min = INT_MAX; int max = INT_MIN; int x=0; while (x!=-1) { printf("Entrez un entier positif: "); scanf("%d", &x); if (x !=-1) { sum +=x; count++; if (x<min) min = x; if (x>max) max= x; } } float avg = 0; Atelier de programmation 1 if (count>0) avg=(float)sum/count; printf("La valeur minimum est : %d \n", min); printf("La valeur maximum est : %d \n", max); printf("La moyenne de ces %d entiers vaut avg); } Exercice 4 : #include ‘stdio.h’ void main( ) { for(int i=10; i<100; i++) { if((i%2!=0)&&(i%3!=0)&&(i%5!=0)&&(i%7!=0)) printf("%i \n", i); } } : %f \n", count, Atelier de programmation 1 Série 4 : Les Tableaux Un tableau (uni-dimensionnel) est une variable structurée formée d'un nombre entier N de variables simples du même type, qui sont appelées les composantes du tableau. Le nombre de composantes N est alors ladimension du tableau. Déclaration de tableaux en C <TypeSimple> <NomTableau>[<Dimension>]; Initialisation Lors de la déclaration d'un tableau, on peut initialiser les composantes du tableau, en indiquant la liste des valeurs respectives entre accolades. Float B[5] = {10.1, 2.5, 3.8, 4.0, 5.6}; int C[] = {1, 0, 0, 1, 1, 1, 0, 1, 0, 1}; En déclarant un tableau par: int A[5]; nous avons défini un tableau A avec cinq composantes, auxquelles on peut accéder par: A[0], A[1], ... , A[4] - l'accès au premier élément du tableau se fait par T[0] - l'accès au dernier élément du tableau se fait par T[N-1] Exemple d’affectation de valeurs main() { int A[5]; int I; /* Compteur */ for (I=0; I<5; I++) scanf("%d", &A[I]); return 0; } Exercice 1: Ecrire un programme qui permet de fusionner deux tableaux triés dans le sens croissant dans un nouveau tableau. Ce dernier doit de même être trié. Exemple : Atelier de programmation 1 Exercice 2: Soit un tableau contenant une liste de N nombres entiers positifs, dont la valeur est comprise entre 1 et 100. Ecrire un programme en C qui calcule le nombre d’occurrences de chaque valeur Contenue dans le tableau sachant qu’elle peut apparaitre plusieurs fois. a) Ecrire une première version qui n’utilise qu’un seul tableau. b) b) Ecrire une seconde version qui utilise deux tableaux. Le premier contiendra les données et le deuxième les occurrences de chaque nombre entier. NB : On peut utiliser l’entier a traiter comme indice du deuxième tableau Atelier de programmation 1 Correction de la série 4 Exercice 1 : #include <stdio.h> Void main() { /* Déclarations */ /* Les tableaux et leurs dimensions */ int A[50], B[50], FUS[100]; int N, M; int IA, IB, IFUS; /* indices courants */ /* Saisie des données */ printf("Dimension du tableau A (max.50) : "); scanf("%d", &N ); printf("Entrer les éléments de A dans l'ordre croissant :\n"); for (IA=0; IA<N; IA++) { printf("Elément A[%d] : ", IA); scanf("%d", &A[IA]); } printf("Dimension du tableau B (max.50) : "); scanf("%d", &M ); printf("Entrer les éléments de B dans l'ordre croissant :\n"); for (IB=0; IB<M; IB++) { printf("Elément B[%d] : ", IB); scanf("%d", &B[IB]); } /* Affichage des tableaux A et B */ Atelier de programmation 1 printf("Tableau A :\n"); for (IA=0; IA<N; IA++) printf("%d ", A[IA]); printf("\n"); printf("Tableau B :\n"); for (IB=0; IB<M; IB++) printf("%d ", B[IB]); printf("\n"); /* Fusion des éléments de A et B dans FUS */ /* de façon à ce que FUS soit aussi trié. */ IA=0; IB=0; IFUS=0; while ((IA<N) && (IB<M)) if(A[IA]<B[IB]) { FUS[IFUS]=A[IA]; IFUS++; IA++; } else { FUS[IFUS]=B[IB]; IFUS++; IB++; } /* Si IA ou IB sont arrivés à la fin de leur tableau, */ /* alors copier le reste de l'autre tableau. while (IA<N) { FUS[IFUS]=A[IA]; IFUS++; IA++; } while (IB<M) { FUS[IFUS]=B[IB]; */ Atelier de programmation 1 IFUS++; IB++; } /* Edition du résultat */ printf("Tableau FUS :\n"); for (IFUS=0; IFUS<N+M; IFUS++) printf("%d ", FUS[IFUS]); printf("\n"); } Exercice2: a) #include ‘stdio.h’ void main( ) { int tab[100], nb=0,nbreElement=0,i,j, trouve, occurence=0; while ((nb!=-1)&&(nb<100)) { printf("entrez un entier positif ( scanf("%d",&nb); if (nb>=0) tab[nbreElement++]=nb; } for(i=0;i<nbreElement;i++) { trouve =0; j=0; while((j<i)&&(trouve==0)) { if (tab[i]==tab[j]) trouve=1; else j++; } Atelier de programmation 1 if(trouve==0) { occurence=1; for(j=i+1;j<nbreElement;j++) { if (tab[i]==tab[j]) occurence ++; } printf("%d: %d occurence(s) \n",tab[i],occurence); } } } b) #include ‘stdio.h’ void main( ) { int tab[100],tab_Occ[100], nb=0,nbreElement=0,i,j,occurence=0; while ((nb!=-1)&&(nb<100)) { printf("entrez un entier positif , (-1 pour finir)"); scanf("%d",&nb); if (nb>=0) { tab[nbreElement]=nb; nbreElement++; } } for(i=0;i<100; i++) { tab_Occ[i]=0; } for(i=0;i<nbreElement;i++) { tab_Occ[tab[i]]=tab_Occ[tab[i]]+1; } Atelier de programmation 1 for(j=0;j<100; j++) { if (tab_Occ[j]!=0) printf("%d: %d occurence(s) } } } Atelier de programmation 1 Série5: les chaines de caractères Il n'existe pas de type spécial chaîne ou string en C. Une chaîne de caractères est traitée comme un tableau à une dimension de caractères (vecteur de caractères). Il existe quand même des notations particulières et une bonne quantité de fonctions spéciales pour le traitement de tableaux de caractères. Déclaration de chaînes de caractères en C char <NomVariable> [<Longueur>]; Lors de la déclaration, nous devons indiquer l'espace à réserver en mémoire pour le stockage de la chaîne. La représentation interne d'une chaîne de caractères est terminée par le symbole '\0'. Ainsi, pour un texte de n caractères, nous devons prévoir n+1 octets. En général, les tableaux sont initialisés par l'indication de la liste des éléments du tableau entre accolades: char CHAINE[] = {'H','e','l','l','o','\0'}; Pour le cas spécial des tableaux de caractères, nous pouvons utiliser une initialisation plus confortable en indiquant simplement une chaîne de caractère constante: char CHAINE[] = "Hello"; Les fonctions prédéfinies strlen(<s>) fournit la longueur de la chaîne sans compter le '\0' final strcpy(<s>,<t>) copie <t> vers <s> strcat(<s>, <t>) ajoute <t> à la fin de <s> compare <s> et <t> lexicographiquement et fournit un strcmp(<s>,<t>) résultat: négatif zéro positif si <s> précède <t> si <s> est égal à <t> si <s> suit <t> Exercice 1 : Écrire un programme qui recherche une sous-chaîne de caractères dans une chaîne de caractères. Par exemple, si la chaîne de caractères contient la valeur "programme d'ordinateur" et que la souschaîne recherchée est "gramme d'or", la procédure de recherche doit indiquer que la sous-chaîne existe et l'indice retourné doit être égal à 3. Atelier de programmation 1 Exercice 2 : Un mot est dit Palindrome s'il se lit de la même manière dans le sens de lecture de droite à gauche que dans le sens de gauche à droite. Par exemple, les mots "LAVAL" et "ADA" ''engage le jeu que je le gagne '' sont des palindromes. Écrire un programme qui dit si une chaîne donnée est un palindrome. Exercice 3 : Ecrire un programme qui permet de nettoyer un tableau de caractères en éliminant les espaces superflus: chaque fois que l'on trouve une suite d'espaces, il faudra les éliminer tous sauf un. Sachant que le premier caractère du tableau et le dernier caractère sont différents du caractère espace. Exercice 4 : Ecrire un programme en C qui permet de saisir deux chaines de caractères ch1 et ch2 et de déduire si elles sont équivalentes. Deux chaines sont dites équivalentes si elles contiennent les mêmes lettres mais pas nécessairement dans le même ordre. a) On suppose qu’une chaine ne peut pas contenir la même lettre deux fois b) On suppose qu’une chaine peut contenir la même lettre plusieurs fois Exemple : a) ch1= azerty, ch2= yterza (équivalente) b) ch1= aazerty, tazeryy (non équivalentes) Atelier de programmation 1 Correction de la série 5 Exercice 1 : #include "stdio.h" #include "string.h" void main(int argc, char* argv[]) { char ch[100], sch[100]; int i,j,pos,stop,existe; printf("donner la chaine \t"); gets (ch); printf("donner la sous chaine \t"); gets (sch); i=0; existe=0; while ( (i<strlen(ch)- strlen(sch)+1) && (!existe)) { j=0; pos=i; stop=0; while ( (j<strlen(sch)) && (!stop)) { if (ch[i]!=sch[j]) stop=1; else { i++; j++; } } if (!stop) existe=1; else i=pos+1; } if (existe) printf("%s existe dans %s a la position: %d \n\n", sch, ch, pos); else Atelier de programmation 1 printf("%s n'existe pas dans %s \n\n",sch,ch); } Exercice2 : #include "stdio.h" #include "ctype.h" // toupper #include "string.h" int main(int argc, char* argv[]) { char chaine [50]; int taille,i,continuer=1; printf("entrer le mot a verifier:\t"); gets(chaine); taille=strlen(chaine); i=0; while((i<taille-1)&&(continuer==1)) { if (toupper(chaine[i])==toupper(chaine[(taille-1)])) { i++; taille--; } else { if (chaine[i]==' ') i++; else if (chaine[(taille-1)]==' ') taille--; else continuer=0; Atelier de programmation 1 } } if(chaine[i]==chaine[(taille-1)]) printf("cette chaine est un palindrome!!\n"); else printf("cette chaine n'est pas un palindrome!!!\n"); return 0; } Exercice 3 : #include "stdio.h" #include "string.h" void main(int argc, char* argv[]) { char ch[100]; int i,j,N; printf("donner la chaine \t"); gets(ch); i=0; N=strlen(ch); while (i< (N-1)) // car le dernier caractere ne peut pas etre un espace { if ((ch[i]==' ') && (ch[i+1]==' ')) { for (j=i+1; j<(N-1); j++) {ch[j]=ch[j+1];} N--; Atelier de programmation 1 ch[N]='\0'; // lors du décalage de la chaîne, le dernier c persiste d’ou on doit mettre fin a la chaine } else i++; } printf("La chaine de caracteres devient %s \n", ch); } Exercice4: #include "stdio.h" #include "string.h" Void main() { char ch1[10], ch2[10]; int egaux=1, i=0; printf("saisir ch1"); scanf("%s", ch1); printf("saisir ch2"); scanf("%s", ch2); if(strlen(ch1)!=strlen(ch2)) egaux=0; else { while((egaux==1)&&(i<strlen(ch1))) { int j=0,trouve=0; while((j<strlen(ch2)) && (trouve==0)) { if (ch1[i]==ch2[j]) trouve=1; else j++; Atelier de programmation 1 } if(trouve==0) egaux=0; i++; } } if(egaux==1) printf("deux chaines equivalentes"); else printf("non equivalentes"); } b) #include "stdio.h" #include "string.h" Void main() { char ch1[10], ch2[10]; int egaux=1, i=0, occ1,occ2; printf("saisir ch1"); scanf("%s", ch1); printf("saisir ch2"); scanf("%s", ch2); if(strlen(ch1)!=strlen(ch2)) egaux=0; else { while((egaux==1)&&(i<strlen(ch1))) { occ1=0; occ2=0; Atelier de programmation 1 for(int j=0;j<strlen(ch2); j++) { if (ch1[i]==ch1[j]) occ1++; if (ch1[i]==ch2[j]) occ2++; } if(occ1!=occ2) egaux=0; i++; } } if(egaux==1) printf("deux chaines equivalentes"); else printf("non equivalentes"); } Atelier de programmation 1 Série 6 : Les matrices Rappel du cours En C, un tableau à deux dimensions A est à interpréter comme un tableau (uni-dimensionnel) de dimension L dont chaque composante est un tableau (uni-dimensionnel) de dimension C. On appelle L le nombre de lignes du tableau et C le nombre de colonnes du tableau. L et C sont alors les deux dimensions du tableau. Un tableau à deux dimensions contient donc L*C composantes Déclaration de tableaux à deux dimensions en C <TypeSimple> <NomTabl>[<DimLigne>][<DimCol>]; Initialisation Lors de la déclaration d'un tableau, on peut initialiser les composantes du tableau, en indiquant la liste des valeurs respectives entre accolades. A l'intérieur de la liste, les composantes de chaque ligne du tableau sont encore une fois comprises entre accolades. Pour améliorer la lisibilité des programmes, on peut indiquer les composantes dans plusieurs lignes. Exemples short A[3][2] = {{1, 2 }, {10, 20 }, {100, 200}}; Accès à un tableau à deux dimensions en C <NomTableau>[<Ligne>][<Colonne>] les indices du tableau varient de 0 à L-1, respectivement de 0 à C-1. Exercice 1 Écrire un programme permettant de transposer une matrice carrée (tableau à double dimension). Exemple: Exercice 2 : 1 2 3 4 5 6 7 8 9 ==> 1 4 7 2 5 8 3 6 9 Atelier de programmation 1 Écrire un programme qui permet d'effectuer la multiplication de deux matrices A et B avec respectivement les dimensions m x n et n x p. Noter que le nombre de colonnes de A doit être égal au nombre de lignes de B. Le résultat de la multiplication est une matrice C de dimensions m x p avec n cij = aik x bkj k=1 1 2 4 7 8 3 X 1 2 0 2 3 4 3 1 = 7 10 6 4 25 36 21 15 17 28 9 19 Exercice 3 : Un carré magique est un arrangement de nombres avec n lignes et n colonnes. La somme des valeurs dans chaque ligne, colonne et diagonale est la même. Par exemple, le carré suivant est magique. 16 9 2 7 6 3 12 13 11 14 5 4 1 8 15 10 1) Écrire un programme qui permet de déterminer si un carré est magique. 2) Une autre condition pour un arrangement de nombres avec n lignes et n colonnes d'être un vrai carré magique est qu'il doit contenir tous les entiers 1, 2, ..., n2. Améliorer votre programme pour qu'il vérifie également cette condition Atelier de programmation 1 Correction de la série 6 Exercice1: #include "stdio.h" Void main() { int mat[100][100], int i=0, j,x; int trouve=0, prod=1; // Saisir la taille de la matrice, une seule dimension car la matrice est carrée do{ printf("Donnez un nbre de lignes de la matrice \n"); scanf("%i",&n); }while ((n>=100)||(n<1)); /*Remplissage de la matrice*/ for (i=0;i<n;i++) { for (j=0;j<n;j++) { printf ("ligne %d, colonne %d : ",i+1,j+1); scanf ("%d",&A[i][j]); } Atelier de programmation 1 } for(i=0;i<n;i++) { for(j=0;j<i;j++) { if(i!=j) { x=mat[i][j]; mat[i][j]=mat[j][i]; mat[j][i]=x; } } } } Exercice2: #include "stdio.h" Void main() { int i,j,k,m,n,p; int A[100][100],B[100][100], C[100][100]; /* Saisie dimension matrice A*/ do{ printf("Donnez un nbre de ligne de A \n"); Atelier de programmation 1 scanf("%i",&m); }while ((m>=100)||(m<1)); do{ printf("Donnez un nbre de colonne de A \n"); scanf("%i",&n); }while ((n>=100)||(n<1)); /* Saisie dimension matrice B*/ // on connait déjà son nombre de ligne qui est le nbre de colonne de A do{ printf("Donnez un nbre de colonne de B \n"); scanf("%i",&p); }while ((p>=100)||(p<1)); /*Remplissage de la premiere matrice*/ for (i=0;i<m;i++) { for (j=0;j<n;j++) { printf ("ligne %d, colonne %d : ",i+1,j+1); scanf ("%d",&A[i][j]); } } /*Remplissage de la seconde matrice*/ for (i=0;i<n;i++) { for (j=0;j<p;j++) Atelier de programmation 1 { printf ("ligne %d, colonne %d : ",i+1,j+1); scanf ("%d",&B[i][j]); } } /*Initialisation de la matrice résultante*/ for (i=0;i<m;i++) { for (j=0;j<p;j++) { C[i][j]=0; } } /*Calcul de la matrice résultante*/ for (i=0;i<m;i++) { for (j=0;j<p;j++) { for (k=0;k<n;k++) { C[i][j]=A[i][k]*B[k][j]+C[i][j]; } } } /*Affichage de la matrice résultante*/ Atelier de programmation 1 printf ("\nProduit matriciel :\n"); for (i=0;i<m;i++) { for (j=0;j<p;j++) { printf ("ligne %d,colonne %d : ",i+1,j+1); printf ("%d\n",C[i][j]); } } } Exercice 3 : 1) #include "stdio.h" void main() { int n,magique,somL=0,somC=0,somD=0,somAD=0,som=0,i,k,j; int tab[100][100] ; do { printf ("Donnez taille du carre"); scanf("%d",&n) ; }while ((n<1)||(n>=100)); for (i=0;i<n;i++) { for (j=0;j<n;j++) Atelier de programmation 1 { printf ("ligne %d, colonne %d : ",i+1,j+1); scanf ("%d",&tab[i][j]); } } magique=1; i=0 ; do { if (i==0) { for(j=0 ;j<n ;j++) { somD=somD+tab[j][j]; somAD=somAD+tab[j][n-j-1]; } if (somD!=somAD) magique=0; else som=somD; } if (magique==1) { somL=0; for(k=0 ;k<n ;k++) somL=somL+tab[i][k] ; if (somL!=som) magique=0 ; else { somC=0; for(k=0 ;k<n ;k++) Atelier de programmation 1 somC=somC+tab[k][i] ; if (somC!=som) magique=0; else i++; } } }while((i<n)&&(magique==1)); if (magique==1) printf("Carre magique"); else printf("oooopss !! Rien de magique") ; } 2) k=1; int continuer=1; while ((k<=n*n)&& (continuer==1)) { i=0;int trouver=0; while ((i<n) && (trouver==0)) { j=0; while (j<n && trouver==0) { if( tab[i][j]==k) trouver=1; Atelier de programmation 1 else j++; } if (trouver==0)i++; } if (trouver==1)k++; else continuer=0; } if (magique==1&&(k==(n*n)+1)) printf("Carre magique"); else printf("oooopss !! Rien de magique"); } Atelier de programmation 1 Série 7 : les fonctions Rappel du cours La structuration de programmes en sous-programmes se fait en C à l'aide de fonctions. Nous avons déjà utilisé des fonctions prédéfinies dans des bibliothèques standard (printf de <stdio>, strlen de <string>, pow de <math>, etc.). Dans ce chapitre, nous allons découvrir comment nous pouvons définir et utiliser nos propres fonctions Définition d'une fonction en C Dans la définition d'une fonction, nous indiquons: - le nom de la fonction - le type, le nombre et les noms des paramètres de la fonction - le type du résultat fourni par la fonction - les données locales à la fonction - les instructions à exécuter <TypeRés> <NomFonct> (<TypePar1> <NomPar1>, <TypePar2> <NomPar2>, ... ) { <déclarations locales> <instructions> } Exemple illustratif Exemple Avant de parler des détails, penchons-nous sur un exemple. Dans le programme suivant, la fonction main utilise les deux fonctions: - ENTREE qui lit un nombre entier au clavier et le fournit comme résultat. La fonction ENTREE n'a pas de paramètres. - MAX qui renvoie comme résultat le maximum de deux entiers fournis comme paramètres. #include <stdio.h> main() { /* Prototypes des fonctions appelées */ int ENTREE(void); int MAX(int N1, int N2); /* Déclaration des variables */ int A, B; /* Traitement avec appel des fonctions */ A = ENTREE(); B = ENTREE(); printf("Le maximum est %d\n", MAX(A,B)); } Atelier de programmation 1 int ENTREE(void) { int NOMBRE; printf("Entrez un nombre entier : "); scanf("%d", &NOMBRE); return NOMBRE; } /* Définition de la fonction MAX */ int MAX(int N1, int N2) { if (N1>N2) return N1; else return N2; } Ecrire un programme permettant de gérer un tableau d’entier en offrant les fonctionnalités suivantes Ecrire une fonction void saisieClav( int tab[], int *N) qui permet de permet de faire le remplissage d’un tableau de taille n Ecrire une fonction void saisieAlea( int tab[], int *N) qui permet de remplir un tableau aléatoirement par des entiers appartenant à [0 100]. Ecrire une fonction void affichage(int tab[], int N) qui permet d’afficher le contenu d’un tableau Ecrire une fonction int max(int tab[], int N) qui retourne le maximum dans un tableau d’entier Ecrire une fonction int min(int tab[], int N) qui retourne le minimum dans un tableau d’entier Ecrire une fonction int modifier(int tab[], int *N, int ind) qui permet de modifier le contenu de la case d’indice ind (par une nouvelle valeur). La fonction retourne 0 si l’indice est erroné et 1 sinon. 7. Ecrire une fonction int recherche(int tab[], int N, int x) qui permet chercher un entier dans un tableau et retourner sa positon (0 s’il n’existe oas). 8. Ecrire une fonction int ajout(int tab[], int *N, int x, int pos) qui permet d’ajouter un entier a une position donnée . la fonction retourne 1 si l’ajout est effectué avec succès, 0 sinon. Atelier de programmation 1 9. Ecrire une fonction int suppression(int tab[], int *N, int x) qui permet de supprimer un entier donné d’un tableau la fonction retourne 1 si la suppression est effectuée avec succès, 0 sinon. 10. Ecrire une fonction void tri(int tab[], int N) permet de trier les éléments du tableau dans le sens croissant. 11. Ecrire une fonction int comparaison(int t1[], int N1, int t2[], int N2) qui retourne le nombre des valeurs de t1 qui apparaissent dans t2 (On ne prend pas le nombre d’occurrence en considération) 12. Ecrire une fonction char menu() qui permet d’afficher un menu présentant 11 choix correspondant au 11 fonctions présentées ci-dessus et retourne le choix de l’utilisateur. 1. La saisie d’un tableau au clavier 2. Le remplissage d’un tableau d’une manière aléatoire 3. L’affichage du contenu du tableau 4. La détermination du minimum 5. La détermination du maximum 6. La modification d’une case étant donné son indice 7. La recherche d’un entier x 8. L’ajout d’un entier à une position donnée 9. La suppression d’un entier x donné s’il existe 10. Le tri du tableau 11. La comparaison de deux tableaux Ecrire un programme principal qui affiche le menu ci-dessous et qui effectue le traitement adéquat selon le choix de l’utilisateur. Le traitement se répète tant que le choix de l’utilisateur n’est pas de quitter l’application Atelier de programmation 1 Correction de la série 7 Corrigé #include <stdio.h> #include <stdlib.h> #include <time.h> void saisieClav( int tab[], int *N); void saisieAlea( int tab[], int *N); void affichage(int tab[], int N); int max(int tab[], int N); int min(int tab[], int N); int modifier(int tab[], int *N, int ind); int recherche(int tab[], int N, int x); int ajout(int tab[], int *N, int x, int pos); int suppression(int tab[], int *N, int x); void tri(int tab[], int N); int comparaison(int t1[], int N1, int t2[], int N2); char menu(); void main() { char choix; int T1[100],T2[100],ind,x,pos,N1,N2; int res; do{ choix=menu(); switch(choix) { case 'a': saisieClav(T1,&N1); break; case 'b': saisieAlea(T1,&N1); Atelier de programmation 1 printf("Remplissage effectué avec succès....\n"); break; case 'c': printf("La liste des elements du tableau :\n"); affichage(T1,N1); break; case 'd': printf("Le plus grand entier du tableau :\n"); max(T1,N1); break; case 'e': printf("Le plus petit entier du tableau :\n"); min(T1,N1); break; case 'f': printf("donner l'indice à modifier : "); scanf("%d",&ind); res=modifier(T1,&N1,ind); if(res) printf("modification effectuée avec succès....\n"); else printf("La modification a échouée....\n"); break; case 'g': printf("donner l'entier à chercher : "); scanf("%d",&x); res=recherche(T1,N1,x); if(res) printf("L'entier %d existe à la position %d\n",x,res); else printf("L'entier %d n'appartient pas au tableau....\n",x); break; case 'h': Atelier de programmation 1 printf("donner l'entier à ajouter : "); scanf("%d",&x); printf("donner la position d'ajout : "); scanf("%d",&pos); res=ajout(T1,&N1,x,pos); if(res) printf("Ajout effectué avec succès....\n"); else printf("L'ajout a echoué....\n"); break; case 'i': printf("donner l'entier à supprimer : "); scanf("%d",&x); res=suppression(T1,&N1,x); if(res) printf("Suppression effectuée avec succès....\n"); else printf("La suppression a echouée....\n"); break; case 'j': tri(T1,N1); printf("Les elements du tableau triés :\n"); affichage(T1,N1); break; case 'k': printf("Saisie du 2éme tableau :\n"); saisieClav(T2,&N2); res=comparaison(T1,N1,T2,N2); if(res==N1 &&N1==N2) printf("Les 2 tableaux contiennent les memes valeurs...\n"); else if(res==N1) printf("Toutes les valeurs de t1 ont été identifiées...\n"); else Atelier de programmation 1 printf("Les 2 tableaux ne contiennent pas les memes valeurs...\n"); break; } system("pause"); system("cls"); }while(choix!='l'); printf("a+\nFin de l'application....\n\n"); char menu() { char choix; printf("selectionner un choix [a..l]\n"); printf("a. Saisie d’un tableau au clavier\n"); printf("b. Remplissage d’un tableau d’une manière aléatoire\n"); printf("c. Affichage du contenu du tableau\n"); printf("d. Détermination du minimum\n"); printf("e. Détermination du maximum\n"); printf("f. Modification d’une case étant donné son indice\n"); printf("g. Recherche d’un entier x\n"); printf("h. Ajout d’un entier à une position donnée\n"); printf("i. Suppression d’un entier x donné s’il existe\n"); printf("j. Tri du tableau\n"); printf("k. Comparaison de deux tableaux\n"); printf("l. Quitter\n"); do{ choix=getchar(); fflush(stdin); }while(choix<'a'||choix>'l'); return choix; } Atelier de programmation 1 void saisieClav( int tab[], int *N) { int i; printf("donner le nombre des elts : "); scanf("%d",N); for(i=0;i<*N;i++) { printf("donner l'elts n° %d ",i+1); scanf("%i",&tab[i]); } } void saisieAlea( int tab[], int *N) { int i; srand(time(NULL)); printf("donner le nombre des elts : "); scanf("%d",N); for(i=0;i<*N;i++) tab[i]=rand()%101; } void affichage(int tab[], int N) { int i; printf("\n\n"); for(i=0;i<N;i++) printf("%5d",tab[i]); printf("\n\n"); } int max(int tab[], int N) { int max=tab[0],i; for(i=1;i<N;i++) if(tab[i]>max) max=tab[i]; return max; } Atelier de programmation 1 int min(int tab[], int N) { int i; int min=tab[0]; for(i=1;i<N;i++) if(tab[i]<min) min=tab[i]; return min; } int modifier(int tab[], int *N, int ind) { int res=1,x; if(ind<0||ind>=*N) { printf("L'indice est erroné\n"); res=0; } else { printf("donner la nouvelle valeur : "); scanf("%d",&x); tab[ind]=x; } return res; } int recherche(int tab[], int N, int x) { int trouve=0,i=0; while(i<N && !trouve) { if(tab[i]==x) trouve=i+1;//la position i++; } return trouve; } Atelier de programmation 1 int ajout(int tab[100], int *N, int x, int pos) { int succe=1,i; if (*N==100) { printf("Tableau saturé\n"); succe=0; } else if((pos<1) || (pos > *N+1)) { printf("position erronée\n"); succe=0; } else { for(i=*N;i>pos-1;i--) tab[i]=tab[i-1]; tab[pos-1]=x; (*N)++; } return succe; } int suppression(int tab[], int *N, int x) { int succe=1,i,pos; if (*N==0) { printf("Tableau vide\n"); succe=0 ; } else { pos=recherche(tab,*N,x); if(!pos) Atelier de programmation 1 { printf("L'element %d n'appartient pas au tableau...\n",x); succe=0; } else { for(i=pos-1;i<*N-1;i++) tab[i]=tab[i+1]; (*N)--; } } return succe; } void tri(int tab[], int N) { int i,j,temp; for(i=0;i<N-1;i++) for(j=i+1;j<N;j++) if(tab[j]<tab[i]) { temp=tab[i]; tab[i]=tab[j]; tab[j]=temp; } } int comparaison(int t1[], int N1, int t2[], int N2) { int nbident=0,i,res; for(i=0;i<N1;i++) { res=recherche(t2,N2,t1[i]); if(res) nbident++; } return nbident; } Atelier de programmation 1 Deuxième partie 2 Devoirs surveillés Atelier de programmation 1 Devoir surveillé n° 1 (2009-2010) Exercice 1 (12 pt): Ecrire un programme qui permet de remplir deux tableaux d’entiers T1 et T2, chacun de taille égale à n. Ensuite, on doit permuter les valeurs des deux tableaux, de sorte qu’on obtienne à la fin les n valeurs minimales dans le premier tableau et les n valeurs maximales dans le deuxième. Les permutations seront faites comme suit : - Trouver la valeur maximale (max) dans T1 - Trouver la valeur minimale (min) dans T2 - Si max>min permuter les deux cases Le programme se termine lorsqu’il n’y a plus de permutations possibles. Exemple : T1 5 10 80 7 5 2 2 4 2 11 4 2 80 11 7 10 T2 Exercice 2 (8 pt): Ecrire un programme qui permet de calculer le nombre d’occurrences de tous les bigrammes qui figurent dans un tableau de caractères. Le bigramme doit être composé de deux lettres différentes. Le tableau est saisi par l’utilisateur, et les valeurs des cases ne doivent pas changer au cours du programme. Exemple : a b b Le programme affichera : le bigramme ab figure 3 fois le bigramme bc figure 2 fois le bigramme cr figure 1 fois le bigramme ra figure 1 fois le bigramme ca figure 1 fois c r a b b c a b Atelier de programmation 1 Correction du devoir surveillé n° 1 Exercice1 : #include "stdafx.h" #include "stdio.h" int main(int argc, char* argv[]) { int t1[100],t2[100]; int i,x,n,max,min; do scanf("%i",&n); while(n>100 || n<0); printf("\n saisir t1"); for(i=0;i<n;i++) scanf("%i",&t1[i]); printf("\n saisir t2"); for(i=0;i<n;i++) scanf("%i",&t2[i]); do { max=0;min=0; for(i=1;i<n;i++) { if(t1[i]>t1[max]) max=i; if(t2[i]<t2[min]) min=i; } if(t1[max]>t2[min]) { x=t1[max]; t1[max]=t2[min]; t2[min]=x; Atelier de programmation 1 } } while(t1[max]>t2[min]); printf("t1=\n"); for(i=0;i<n;i++) printf("%i ",t1[i]); printf("\nt2=\n"); for(i=0;i<n;i++) printf("%i ",t2[i]); return 0; } Ex2 : #include "stdafx.h" #include "stdio.h" int main(int argc, char* argv[]) { char t[100]; int i,n,j,occ,trouve; do scanf("%i",&n); while(n>100 || n<0); printf("\n saisir t1"); scanf("%s",t); for(i=0;i<n-1;i++) { if(t[i]!=t[i+1]) { j=0; trouve=0; while(j<i-1 && trouve==0) { if( (t[j]==t[i])&& (t[j+1]==t[i+1])) { Atelier de programmation 1 trouve=1; } j++; } if(trouve==0) { j=i+2; occ=1; for(j=i+2; j<n-1;j++ ) { if( (t[j]==t[i])&& (t[j+1]==t[i+1])) { occ++; } } printf("\n %i",t[i],t[i+1],occ); } } } return 0; } le nbr d'occ de %c %c est Atelier de programmation 1 Devoir surveillé n° 2 (2009-2010) Exercice 1 (12 pt): Ecrire un programme qui permet de saisir un tableau de caractères et puis d’ordonner les lettres de telle sorte qu’on aura une suite de syllabes. Chaque syllabe est composée d’une consonne et d’une voyelle. On suppose que le tableau ne contient que des lettres de l’alphabet. Chaque case d’indice impair doit contenir une consonne, sinon on doit parcourir le reste du tableau et permuter cette case avec la première consonne trouvée. Chaque case d’indice pair doit contenir une voyelle, sinon on doit parcourir le reste du tableau et permuter cette case avec la première voyelle trouvée. Ce processus s’arrêtera lorsqu’on trouve plus de permutations possibles ou lorsqu’on termine tout le tableau. Exemple : b r a s T e o i f b a r e T o s i f Exercice 2 (8pt): Ecrire un programme qui permet de saisir un tableau d’entiers. Après avoir terminé la saisie, on doit parcourir le tableau et afficher les éléments isolés. Un élément est qualifié comme non isolé s’il est égal à la somme de deux autres entiers existants dans le même tableau. Exemple : 5 2 8 14 Le programme affichera seulement: 2, 14, 3, 88 Car 5 = 2+3 8 = 5+3 10= 8+2 3 10 88 2 Atelier de programmation 1 Correction du de devoir surveillé n° 2 Exercice 1 #include "stdafx.h" #include "stdio.h" #include "string.h" int main(int argc, char* argv[]) { char t[100]; int i,n,j,trouve,x; printf("\n saisir t1"); scanf("%s",t); n=strlen(t); for(i=0;i<n;i++) { if(i%2==0) { if(t[i]=='a' || t[i]=='i' t[i]=='o'|| t[i]=='y') || t[i]=='e'|| { j=i,trouve=0; while(j<n && trouve==0) { if(t[j]!='a' && t[j]!='i' && t[j]!='e'&& t[j]!='o' && t[j]!='y') { trouve=1; x=t[i]; t[i]=t[j]; t[j]=x; } j++; Atelier de programmation 1 } } } if(i%2==1) { if(t[i]!='a' && t[i]!='i' && t[i]!='e'&& t[i]!='o' && t[i]!='y') { j=i,trouve=0; while(j<n && trouve==0) { if(t[j]=='a' || t[j]=='i' || t[j]=='e'|| t[j]=='o'|| t[j]=='y') { trouve=1; x=t[i]; t[i]=t[j]; t[j]=x; } j++; } } } } for(i=0;i<n;i++) printf("%c ",t[i]); return 0; } Exercice 2 #include<stdio.h> #include<stdlib.h> Atelier de programmation 1 int main() { int t[100], stop,n; do { printf("donner la taille du tabelau"); scanf("%i", &n); }while ((n<=0)||n>100)); for(int i=0;i<n;i++) { printf(donner une entier); scanf("%i", &t[i]); } for(int i=0;i<n;i++) { stop=0; while (j<n)&&(stop==0) { while (k<n)&&(stop==0) { if((j!=i) && (k!=i) && t[k]+t[j]==t[i]) { stop=1 } else k++; } j++; Atelier de programmation 1 } if(stop==0) // t[i] est isole printf("%i est un entier isolé") } } Atelier de programmation 1 Devoir surveillé n° 3 (2011-2012) Exercice 1 (6 points): Ecrire un programme qui permet de: - Saisir un tableau T d’entiers positifs, - Effacer les éléments égaux à l’entier V du tableau T, - Afficher le nouveau tableau T. Exercice 2 (5 points): Ecrire un programme qui permet de saisir un caractère « car » et d’indiquer qu’il s’agit d’une lettre de l’alphabet ou non. Dans le premier cas, si le caractère « car » est une lettre de l’alphabet, le programme doit afficher s’il s’agit d’une voyelle ou d’une consonne. Exercice 3 (9 points): On se propose d’écrire un programme en C permettant à l’utilisateur de créer son propre dictionnaire de la manière suivante: • L’utilisateur donne le nombre de mot à saisir • L’insertion de chaque nouveau mot se fait de manière qu’il soit placé selon l’ordre alphabétique • On ne doit pas accepter l’existence du même mot plus qu’une seule fois • A la fin, il faut afficher le dictionnaire obtenu Exemple : Pour n=3 Mot1= belle b e l l e \0 b a l l o n b e l l e \0 a r b r e \0 b a l l o n b e l l e \0 Mot 2= ballon \0 Mot 3= Arbre \0 Atelier de programmation 1 Correction du devoir surveillé n° 3 Exercice 1: (6pts) #include "stdio.h" int main(int argc, _TCHAR* argv[]) { int T[100]; int n,i,j, val,existe=0; do{ printf("Donnez le nombre d'éléments"); scanf("%i",&n); }while(n<1||n>100); for(i=0;i<n;i++) { printf("Donnez le %i ème élément ", i+1); do{ scanf("%i",&T[i]); if(T[i]<0) printf("Saisie incorrecte! Tapez un nombre strictement positif"); }while(T[i]<0); } printf("Donnez une valeur à supprimer"); scanf("%d",&val); for(i=0;i<n;i++) { if(T[i]==val) { existe=1; for(j=i;j<n-1;j++) T[j] = T[j+1]; n--; } } if (!existe) Atelier de programmation 1 printf("Impossible de supprimer"); else { printf("Aprés suppression, le tableau devient: \n"); for(i=0;i<n;i++) printf("%i\t",T[i]); } return 0; } Exercice 2: (5pts) #include "stdio.h" int main(int argc, _TCHAR* argv[]) { char car; printf("Donnez un caractère"); scanf("%c",&car); if((car>='a' && car<='z')||(car>='A'&&car<='Z')) { if(car=='o'||car=='i'||car=='e'||car=='a'||car=='u'||car =='y'||car=='O'||car=='I'||car=='E'||car=='A'||car=='U'| |car=='Y') printf("Lettre voyelle"); else printf("Lettre consonne"); } else printf("le caractère saisi n'est pas une lettre de l'alphabet français"); return 0; } Exercice 3: (9pts) #include "stdio.h" #include "string.h" int main(int argc, _TCHAR* argv[]) { const int Tmax = 100; Atelier de programmation 1 char dic[Tmax][10], Tmp[10]; int i,j,k,n,ind,stop,trouve; do{ printf("Donnez le nombre de mots"); scanf("%i",&n); }while (n<1 || n>Tmax); printf("Inserez le mot 1:"); fflush(stdin); fgets(dic[0],10,stdin); for(i=1;i<n;i++) { Do { printf("Inserez le mot %i: ", i+1); fflush(stdin); fgets(Tmp,10,stdin); j=0; trouve=0; stop=0; while(j<i && !stop && !trouve) { if(strcmp(Tmp, dic[j])==0) trouve=1; else{ if(strcmp(Tmp,dic[j])<0) { stop=1; ind=j; } else j++; } Atelier de programmation 1 } }while(trouve); if(stop) { for(k=i;k>ind;k--) strcpy(dic[k],dic[k-1]); strcpy(dic[ind],Tmp); } else strcpy(dic[i],Tmp); } printf("\n****************Le dictionnaire**************\n"); for(i=0;i<n;i++) printf("%s \n", dic[i]); return 0; } Page 70 Atelier de programmation 1 Devoir surveillé corrigé n° 4 (2012-2013) Exercice1 : (12 pts) Soit T un tableau d’entiers distincts de taille logique N, et soit M une matrice d’entiers distincts de taille (N x N), sachant que N est comprise entre 1 et 100. On se propose de tester si tous les éléments de T apparaissent dans M dans le même ordre d’apparition dans T et d’afficher un message selon le résultat du test. Ecrire un programme en C qui permet de saisir le tableau T et la matrice M et d’afficher le message correspondant au résultat du test. NB : En remplissant la matrice, vous n'êtes pas censé de faire le contrôle de saisie. Exemple : Soit la matrice M (3,3) suivante : 1 10 5 4 9 6 11 2 7 1 5 9 Le tableau T1 existe dans la matrice 5 1 9 Le tableau T2 n’existe pas dans la matrice 1 3 4 Le tableau T3 n’existe pas dans la matrice Page 71 Atelier de programmation 1 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char *argv[]) { int t[100]; int M[100][100]; int n, i, j, k, stop, trouve, w; // saisie de la taille logique entre 1 et 100 1.5 pt avec contrôle de saisie ; 0.5 pt sans contrôle do{ printf("donner une taille logique N"); scanf("%i",&n); }while((n<1)||(n>100)); // remplissage d’un tableau d’entiers distincts 2.5 pt si on vérifie la redondance ; 1 pt sinon for(i=0;i<n;i++) {do{ printf ("donner une valeur"); scanf("%i",&t[i]); j=0; stop=0; while((j<i)&&(stop==0)) { if(t[j]==t[i]) stop=1; else j++; } }while(stop==1); } Page 72 Atelier de programmation 1 //remplissage d’une matrice 1 pt for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf ("donner une valeur matrice"); scanf("%i",&M[i][j]); } } //affichage de la matrice for(i=0;i<n;i++) { for(j=0;j<n;j++) {printf("%i \t", M[i][j]); } printf("\n"); } //Recherche par ordre i=0;j=0;k=0; stop=0; while((i<n)&&(stop==0))// Parcours du tableau 1.5 pt {trouve=0 ; // Pour chaque valeur de t on continue la recherche à partir des indices de la valeur précédente while((j<n)&&(trouve==0))//j est l'indice des lignes de la matrice 0.75 pt {if(k>=n) k=0;// On ne réinitialise l’indice des colonnes à 0 que si on parcourt toutes les colonnes de la matrice pour un indice courant d’une ligne et pour chaque valeur de t . 0.5 pt Page 73 Atelier de programmation 1 while((k<n) && (trouve ==0)) 0.75 pt { if(M[j][k]==t[i]) 1.5 pt trouve=1; k++; } if(k>=n) 1 pt j++;// on ne passe à la ligne suivante que si on termine toutes les colonnes } if(trouve==0) 0.5 pt stop=1; else i++; } if((stop==0)) 0.5 pt { printf("le tableau existe dans la matrice"); } else { printf("le tableau n'existe pas dans la matrice"); } system("PAUSE"); return EXIT_SUCCESS; } Page 74 Atelier de programmation 1 Exercice 2: (8 pts) Etant donné un mot, on se propose de le codifier où chaque lettre du mot sera précédé de son nombre d’occurrences successives (égal à 1 ou 2). Par exemple le mot assassin son code sera la chaine 1a2s1a2s1i1n. Ecrire un programme C qui demande à l’utilisateur de saisir une chaine et d’afficher son code. #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char *argv[]) { char t[100]; int l, occ, i; printf("donner le mot\n"); 1 pt, on peut aussi utiliser les fonctions scanf et gets fflush(stdin); fgets(t, 100, stdin); l=strlen(t)-1; 1 pt pour l’initialisation des variables et leur déclaration occ=1; i=0; while((i<l-1)) 1 pt si on s’arrête à l-2 (à la position de l’avant dernier caractère ) ; 0.5pt sinon { if(i==(l-2)) 1 pt pour le traitement des deux derniers caractères s’ils sont identiques {if(t[i]==t[i+1]) {occ=2; Page 75 Atelier de programmation 1 printf("%d%c", occ, t[i]); } Else 1 pt pour le traitement des deux derniers caractères s’ils sont différents { occ=1; printf("%d%c", occ, t[i]); printf("%d%c", occ, t[i+1]); } i++; } else { if(t[i]==t[i+1]) 1.5 pt pour le traitement des autres caractères au milieu du tableau s’ils sont identiques {occ=2; printf("%d%c", occ, t[i]); i=i+2; } Else 1.5 pt pour le traitement des autres caractères au milieu du tableau s’ils sont différents {occ=1; printf("%d%c", occ, t[i]); i=i+1; } } } system("PAUSE"); return EXIT_SUCCESS; } Page 76 Atelier de programmation 1 Troisième partie 3 Les Projets Page 77 Atelier de programmation 1 Projet N.1 (2009-2010) HEURISTIQUE PLUS PROCHE VOISIN POUR LE PROBLÈME DU VOYAGEUR DE COMMERCE Description du problème : Définition du problème du voyageur de commerce Étant donné un ensemble fini de villes, il s'agit de trouver le plus court chemin qui relie toutes ces villes, en passant une seule fois par chaque ville. • Pour un problème de N villes, on disposera d'une matrice (MATRICE_DISTANCE N*N) de distances donnant la distance entre chaque couple de villes. • Il est à noter que cette distance est symétrique, c'est-à- dire distance(villea, villeb) = distance(villeb, villea) Méthode de résolution : Heuristique (méthode) du plus proche voisin Il ne s'agit pas ici de trouver le meilleur chemin possible, mais essayer de trouver un bon chemin. L'idée est de lancer plusieurs voyageurs (NB_VOYAGEUR), chacun commençant à partir d'une ville différente. Dans son parcours chaque voyageur se dirige vers la ville la plus proche qu'il n'a pas encore visitée. Une fois tous les voyageurs auront terminé leurs parcours, le chemin le plus court sera affiché ainsi que sa distance parcourue Chaque voyageur devra donc enregistrer la liste des villes parcourus. On utilisera une autre matrice(NB_VOYAGEUR * N) avec N le nombre de villes. Chaque ligne de cette matrice contient la séquence des villes parcourues par le voyageur. Travail demandé : On vous demande d’écrire les programmes suivants : • Init_Matrice Distance (MATRICE_DISTANCE), qui réinitialise la matrice distance avec les distances réelles des villes tunisiennes. • Placer_Voyageurs (NB_VOYAGEUR), qui permet de placer aléatoirement un nombre de voyageurs sur des villes différentes • Afficher_Meilleur_Parcours, qui affiche la séquence des villes qui correspond à la distance minimale. Page 78 Atelier de programmation 1 • Une interface graphique, permettant à l’utilisateur de placer les voyageurs sur la carte de la Tunisie, et d’afficher leurs parcours est souhaitable. • En l’absence d’interface graphique, l’utilisateur doit avoir la possibilité de saisir le nombre de voyageur PARTIE 2 CALCUL DE LA MATRICE DE CO-OCCURRENCE Dans le domaine de traitement d’images, chaque image est représentée par une matrice de niveau de gris. Chaque case de la matrice est relative à un pixel (point) de l’image. Par exemple, cette image de 4*4 pixels est représentée par la matrice suivante (où le blanc par exemple est codé par la valeur 3): Il est possible d’étudier quelques caractéristiques concernant l’image initiale à partir de cette matrice. Pour cela, il faut calculer ce qu’on appelle la Matrice de Co-occurrences. Cette matrice est de taille Ng*Ng (Ng étant le nombre de niveaux de gris figurant dans l’image). Dans ce qui suit on ne traite que les images ayant les 4 niveaux de gris 0,1,2,3. Pour le calcul de la matrice de co-occurrence, les paramètres généralement utilisés sont : d : la distance entre les 2 pixels (en général c’est égal à 1) θ : l'angle de la droite reliant ces 2 pixels (en général on utilise θ = 0° càd les deux voisins horizontaux (celui de droite et celui de gauche)). Dans la suite on va considérer (d = 1 et θ = 0° ) La première étape pour le calcul de matrice de co-occurrences, est de calculer la matrice relative aux voisins de droite (MVD) et la matrice relative aux voisins de gauche (MVG). C'est-à-dire qu’on doit Page 79 Atelier de programmation 1 étudier toutes les combinaisons entre les niveaux de gris. Dans notre exemple, on a 16 combinaisons possibles (4*4) qui sont : (0,0) (0,1) (0,2) (0,3) (1,0) (1,1) (1,2) (1,3) (2,0) (2,1) (2,2) (2,3) (3,0) (3,1) (3,2) (3,3) Les deux matrices MVD et MVG de l’exemple ci-dessus sont les suivants : La valeur 2 (dans la cellule (1,2)) de MVD veut dire qu’il existe 2 cas dans la matrice M où un pixel=0 à un voisin droit =1 (cad les cases (1,2), (2,2) de M). La valeur 3 (dans la cellule (3,3)) de MVG veut dire qu’il existe 3 cas où un pixel=2 a un voisin gauche =2 (cad le pixel (3,3), (3,4), (4,2) de M). Une fois les deux matrices de voisinage calculées, la deuxième étape est de symétriser (cad faire la somme des deux matrices MVD et MVG). Dans notre exemple la matrice symétrisée (MS) est : La dernière étape est la normalisation où on doit diviser la matrice symétrisée (MS) par la somme de ses éléments (de telle sorte que la nouvelle somme soit égale à 1). Dans notre exemple, on divise par 24, et la matrice de co-occurrence (MC) est : Page 80 Atelier de programmation 1 Travail demandé : Soit M la matrice de niveaux de gris, voici l’algorithme principal qui permet de calculer la matrice de co occurrences. Algorithme CalculCoOccurrence M, MDV, MDG, MS, MC (Tableau [1..4, 1..4] d’entiers) Début GenererMatriceGris (M) CalculMatriceVoisins (M, MVD, MVG) SymétrisationMatrice (MVD, MVG, MS) NormalisationMatrice (MS, MC) Fin On vous demande d’écrire les programmes suivants : • GenererMatriceGris (M) : pour la première version on vous propose saisir M • CalculMatriceVoisins permet de calculer les matrices des voisins MVD et MVG à partir de la matrice M • SymétrisationMatrice permet de calculer la matrice MS à partir des matrices MVD et MVG • NormalisationMatrice a comme entrée la matrice MS et permet de calculer la matrice de cooccurrences M. Page 81 Atelier de programmation 1 Projet N.2 (2011-2012) Jeux Motus & Morpion Dans ce projet on se propose d'implémenter deux jeux : Jeu Motus : Un joueur J1 propose un mot masqué. Un deuxième joueur J2 doit le deviner tout en suggérant des mots. A chaque fois que le joueur J2 choisit un mot, le programme l’informe des lettres bien placées, des lettres mal placées et celles qui n’appartiennent pas au mot recherché. Le nombre de tentatives est limité. Lorsque l’utilisateur saisit un mot différent du mot recherché, un décompte est effectué jusqu'à l’échec. On fixe le temps de réponse du joueur J2. Exemple : Il a 10 minutes pour trouver le mot sinon il perd. Jeu du Morpion : Pour jouer au morpion il faut être à deux joueurs. Chaque joueur possède un symbole, à savoir : • X pour le joueur 1 • O pour le joueur 2. Les joueurs inscrivent tour à tour leur symbole sur une grille 3x3. Chaque joueur va à tour de rôle inscrire son symbole sur l'une des 9 cases encore vide de la grille. La partie se termine quand : un des joueurs arrive le premier à aligner trois symboles identiques horizontalement ou verticalement ou en diagonale. Partie nulle. Le score est donc calculer de la façon suivante : Si le joueur 1 aligne trois X en premier, alors il gagne 1 point. Si le joueur 2 aligne trois O en premier, alors il gagne 1 point. En cas de match nul, leur score reste inchangé. A la fin de chaque partie, on demande aux joueurs s’ils veulent rejouer. Le score de la dernière partie jouée s’additionne au score final. Exemple : Page 82 Atelier de programmation 1 On vous demande d'écrire un programme en C permettant aux utilisateurs de : 6. Choisir de jouer l’un des jeux 7. Jouer le jeu motus 8. Jouer le jeu du morpion Nota : Pour mieux comprendre le principe de jeux Motus&Morpion, veuillez visiter les sites suivant : http://motus.absolu-puzzle.com/index.php http://www.jeuxjeuxjeux.fr/jeu/morpion/tic+tac+toe+2.html Page 83 Atelier de programmation 1 Projet N.3 (2012-2013) Gestion de prêt de livre Dans ce projet on se propose d'implémenter une application pour la gestion de prêt de livres d’une bibliothèque. Un livre est caractérisé par numéro, un titre et le nombre d’exemplaires existants. Pour la gestion des livres on propose de définir 3 tableaux : T_Nlivre pour les numéros des livres, T_Titre pour les titres des livres et T_ Nbr_exp pour les nombres d’exemplaires des livres. T_NLivre N_livre N_livre2 … … Titre 2 … … N_livre2 … … 1 T_Titre Titre 1 T_Nbr_exp N_livre 1 Pour la gestion des emprunts des livres on utilisera pour cela un tableau d’entier à deux dimensions comme la montre la figure suivante: Date_d’empreint N_CIN N_livre J1 M1 A Date_de retour prevue J2 M2 A2 … … … … 1 ….. ….. … … Page 84 Atelier de programmation 1 Comme la matrice ci-dessous le montre un emprunt est caractérisé par le Numéro de CIN (N_CIN) de l’emprunteur le Numéro de livre (N_livre) , la date de l’emprunt (j 1/M1/A1) et la date de retour prévue ((j2/M2/A2). On vous demande d'écrire un programme C permettant à l'utilisateur de 1. saisir un emprunt en vérifiant sa validité. Pour qu'un emprunt soit valide il faut que le livre soit disponible. 2. supprimer un emprunt en précisant la N_CIN et le N_livre. Il est à préciser que la suppression doit effectuer un décalage dans les tableaux afin d'éviter le gaspillage de mémoire. 3. supprimer un ensemble d’emprunts en précisant une date d’emprunt et une date de retour prévue. Tous les emprunts appartenant à cette période doivent être supprimés 4. afficher l'ensemble des emprunts respectifs à une date de retour prévue. 5. Afficher le nombre d’exemplaire encore disponible pour le chaque livre. 6. Afficher le livre le plus emprunté dans un période donnée. 7. Afficher l’emprunteur le plus fidèle pour la bibliothèque. Remarque : Il est conseillé de remplir les données sur les livres pendant la déclaration des tableaux. Page 85 Atelier de programmation 1 Quatrième partie 4 Sujets Des Examens Page 86 Atelier de programmation 1 Examen corrigé N°1 Session principale 2009/2010 Que contiennent X, Y, Z et T à la fin de la fonction main () ? int main (); int F1 (int *A, int * B, int * C, int *D); void F2 (int K, int L, int M, int N); int main () { int X, Y, Z, T; X= 1; Y = 2; Z = 3; T = 4; Y = F1 (&X, &Y, &Z, &T); return (0); } int F1 (int *A, int * B, int * C, int *D) { *B = 5+*B; F2 (*A, *B, *C, *D); *A = *C; return (8); } void F2 (int K, int L, int M, int N) { K = 10; M = 21; L = K + L; N = N; } Réponse : X=3,Y=8, Z=3,T=4; Exercice 2 (16 points) a. Ecrire une fonction SaisirMatrice qui permet de saisir les dimensions L et C d’une matrice M et de la remplir par des entiers saisis (L et C ne doivent pas dépasser 100). b. Ecrire la fonction EstPointCol qui rend 1 si un élément donné d’une matrice d’entiers (défini par son numéro de ligne et son numéro de colonne) est un "point col". Et qui rend 0 sinon. On appelle "point col" d’une matrice, l’élément qui est à la fois maximum sur sa ligne et minimum sur sa colonne. c. Ecrire une fonction TousPointsCols qui affiche les coordonnées (numéro de ligne et numéro de colonne) de tous les points cols de la matrice M. d. Ecrire un programme principal qui permet d’appeler les fonctions écrites en a., et en c. Exemple : Les points cols de la matrice ci-après sont : (0, 3) et (3, 3). Page 87 Atelier de programmation 1 Réponse : a. void SaisirMatrice(int M[][100], int * L, int *C) { int i, j; do { printf ("Donnez L : ") ; scanf ("%d", L) ; } while (*L <= 0) || (*L>=100) do { printf ("Donnez C : ") ; scanf ("%d", C) ; } while (*C <= 0) || (*C>=100) // Saisie de la matrice for (i=0 ; i < *L; i++) { for (j=0 ; j < *C; j++) { printf ("Donnez M[%d][%d] : ", i, j) ; scanf ("%d", &M[i][j]) ; } } } b. int EstPointCol (int M[][100], int A, int B, int L, int C) { int Max, Min, i, j, trv ; Max = M[A][B] ; Min = M[A][B] ; j =0 ; trv = 0 ; while ((j < C) && (!trv)) { if (M [A][j] > Max) trv = 1 ; else j++ ; } i = 0 ; Page 88 Atelier de programmation 1 while ((i < L) && (!trv)) { if (M[i][B] < Min) trv = 1 ; else i++ ; } return (!trv) ; } c. void TousPointsCol (int M[][100], int L, int C) { int i, j, n; // Rechercher les points cols n = 0 ; for (i=0 ; i < L; i++) { for (j=0 ; j < C; j++) { if (EstPointCol (M, i, j, L, C)) { if (n==0) {printf ("Les points cols de cette matrice sont : ") ;} printf ("(%d, %d), ", i, j) ; n ++ ; } } } if (n ==0) printf ("Cette matrice ne contient pas de points cols") ; } d. int main() { int M [100][100]; int L, C; SaisirMartice (M, &L, &C) ; TousPointsCol (M, L, C) ; return (0) ; } Page 89 Atelier de programmation 1 Examen corrigé N°2 Session de contrôle 2009/2010 Exercice 1: (8 points) Soit un tableau d’entiers. On appelle un entier « valable » tout entier strictement supérieur aux entiers qui le précèdent dans le tableau. Écrire une fonction en C qui permet de compter le nombre d’entiers « valables » dans un tableau d’entiers reçu en paramètre. int NombreValables (int T [ ], int N) { int i, N, S, R ; float M ; S = T [0] ; R = 0 ; for (i=1 ; i < N ; i++) { M = (float) (S) / (float) (i) if ((float)(T [i]) > M) R = R + 1 ; S = S + T [i] ; } return (R) } Exercice 2 : (12 points) Écrire une fonction en C qui permet de dire si deux matrices sont "fausses jumelles". Deux matrices sont dites "fausses jumelles" si elles contiennent exactement les mêmes entiers (avec les mêmes nombres d’apparitions) même si l’ordre des entiers n’est pas le même. Exemple : Les deux matrices suivantes sont dites "fausses jumelles". int FaussesJumelles(int** M1, int NL1, int NC1, int** M2, int NL2, int NC2) { Page 90 Atelier de programmation 1 int int int int for T1 [2][100], T2 [2][100]; n1=0,n2=0; fs=1; i=0,j=0; (i=0;i<NL1*NC1;i++) T1[1][i]=0; for(i=0;i<NL1;i++) { for(j=0;j<NC1;j++) { int x=M1[i][j]; int traite=0; int k=0; while(!traite&& k<n1) { if (x==T1[0][k]) { traite = 1; T1[1][k]=T1[1][k]+1; } else k++; } if(!traite) { T1[0][n1]= x; n1++; } } } for (i=0;i<NL2*NC2;i++) { T2[1][i]=0; } for(i=0;i<NL2;i++) { for(j=0;j<NC2;j++) { int x=M2[i][j]; int traite=0; int k=0; while(!traite&& k<n2) { if (x==T2[0][k]) { traite = 1; T2[1][k]=T2[1][k]+1; } else k++; } if(!traite) Page 91 Atelier de programmation 1 { T2[0][n2]= x; n2++; } } } Page 92 Atelier de programmation 1 Références C. Delannoy. Le livre du C, premier langage. Eyrolles, 2002. A. Zribi, Z. Elouedi. Apprendre à programmer par l'exemple. CPU, 2006. R. Malgouyres, F. Feschet, Z. Zrour. Algorithmique et structures de données en C 2011. Introduction a la programmation en ansi-c, http://www.ltam.lu/cours-c/ Page 93