ENS Lyon L-Info PROJ1 2014-2015 TP1 - Introduction au langage C Sujet à terminer pour le dimanche 20 à 2h59, sous forme d une archive.zip contenant votre code source, par email à aurelien.cavelan@ens-lyon.fr. Il s agit d un travail individuel! Le nom de l archive devra être sous la forme prenom.nom-tp1.zip Le langage C Le C est un langage de programmation impératif, généraliste, conçu pour la programmation système. Inventé au début des années 1970 pour réécrire UNIX, C est devenu un des langages les plus utilisés. Le C offre un bon compromis entre haute performances et simplicité. C est un langage à tout faire : calcul intensif, programmation de microcontrôleur, système d exploitation, jeux-videos... Le langage C requiert une certaine connaissance de la machine du fonctionnement de la mémoire dans le système d exploitation. On distingue deux types de fichiers : les fichiers.h qui contiennent les prototypes des fonctions et la documentation, et les fichiers.c qui contiennent les définitions des fonctions (le corps) ainsi que la fonction principale. Hello World hello.c 1 /* Bibliothèque "Standard I/O" (requit pour la fonction printf) */ 2 #include <stdio.h> /* Bibliothèque "Standard" (utile plus tard) */ 4 #include <stdlib.h> 5 /* Fonction hello qui ne renvoie rien */ 7 void hello() 8 { 9 // Affiche du texte 10 printf("hello World!\n"); 11 } 12 1 /* Fonction main, appelée automatiquement au démarrage */ 14 int main() 15 { 1 hello(); 17 // 0 = OK 18 return 0; 19 } Compilation : > g++ -Wall -o hello hello.c -Wall Active la plupart des warnings -o Nom du fichier de sortie Execution : >./hello Au démarrage du programme, la fonction main() est appelée, puis la foncion hello(), qui affiche la chaîne de caractères Hello World!. 1
Syntaxe Syntaxe Exemple if(condition){... } if(a == b){ /* a égale b*/ } if(condition){... } else {... } if(a > b){ /* a>b */ } else { /* a<=b */ } while(condition){... } while(x > 0){ x--; /*... */ } do{... } while(condition); do{ /*... */ x--; } while(x > 0) ; for(init; cond; incr){... } for(int i=0; i<10; i++){ /* utiliser i */ } Table 1 Conditions et boucles Type Taille Fonction bool - Variable boolénne true / false char 8 bits Caractère ASCII (-128 à +128) unsigned char 8 bits Caractère ASCII (0 à 255) int 2 bits Entier (-2 147 48 48 à 2 147 48 47) unsigned int 2 bits Entier (0 à 4 294 97 295) long long 4 bits Grand entier float 2 Nombre flottant simple précision double 4 bits Nombre flottant double précision Table 2 Table des types de base assignation = inférieur < multiplication * égalité == supérieur > division / où inférieur ou égale <= addition + et && supérieur ou égale >= soustraction - Table Table des opérateurs L ami printf et son cousin scanf 1 // Affiche "Cha^ıne: toto" 2 printf("cha^ıne: %s\n", "toto"); 4 // Affiche 1, 17, 19 5 printf("%d, %d, %d\n", 1, 17, 19); 7 int a = ; 8 // Affiche "a contient " 9 printf("a contient: %d\n", a); 10 11 int x; 12 // Demander à l utilisateur de saisir un entier 1 scanf("%d", &x); Pointeurs, Adresses et Tableaux Toute variable possède une adresse et contient une valeur. Ainsi, on peut déclarer une variable qui contient elle-même une adresse : c est un pointeur. 2
1 #include <stdio.h> 2 int main() { 4 int a = ; 5 int b = 5; 7 int *pa = &a; // p pointe sur a 8 9 /* p contient l adresse mémoire de a, quelque chose comme 0x0055... 10 *pa permet d accéder au contenu de la variable pointée (ici a) */ 11 12 // Affiche 1 printf("a = %d\n", *pa); 14 15 pa = &b; // p pointe sur b 1 17 // Affiche 5 18 printf("b = %d\n", *pa); 19 } Un tableau est une suite de cases conscutives en mémoire. Il n existe pas de type tableau : on doit nous-même réserver une zone de la mémoire. Pour déclarer un tableau, on déclare une variable qui pointe sur la première case de notre tableau. 1 // On déclare une variable de type pointeur sur caractère 2 char *str = 0; 4 /* Pour le moment, c pointe sur rien du tout. Essayer d afficher 5 le contenu de l adresse 0 donnera une erreur (accès interdit!) */ 7 // On alloue de la mémoire pour 2 caractères 8 str = (char*)malloc(2 * sizeof(char)); 9 10 // Ça y est! on peut utiliser notre tableau. 11 str[0] = t ; 12 str[1] = o ; 1 str[2] = t ; 14 str[] = o ; 15 str[4] = 0; // 0 est reconnu comme étant la fin de la cha^ıne 1 17 // Affiche "toto" 18 printf("%s\n", str); 19 20 // On libère la mémoire allouée, car on est gentil 21 free(str); 22 2 /* Un autre moyen de créer un tableau de taille fixe */ 24 char fixedstr[2] = "toto!"; 25 int primes[4] = {2,, 5, 7}; 1 Echauffements Échauffement 1 (min). Ecrire une fonction min prenant trois entiers en paramètres et retournant le plus petit des trois. Échauffement 2 (somme). Écrire une fonction naïve prenant en entrée un entier n et retournant la somme des carrés des nombres entiers de 1 à n. Tester sur des exemples. On pourra vérifier la correction du programme en utilisant la forme close : n k 2 = k=1 n(n + 1)(2n + 1). Échauffement (primalité). Écrire une fonction prenant en entrée un entier n et affichant un message indiquant si n est un nombre premier ou non. Tester sur des exemples.
Échauffement 4 (max). Ecrire une fonction max prenant un tableau en paramètre (pointeur sur entier), ainsi qu un entier n (nombre d éléments). Cette fonction doit renvoyer le plus grand nombre du tableau. Afficher le tableau et le résultat pour vérifier. On pourra utiliser le morceau de code suivant dans le main pour remplir le tableau aléatoirement : 1 #include <time.h> 2 // Dans le main: 4 // Initialisation de la fonction random 5 srand(time(0)); 7 // On remplit le tableau avec des entiers aléatoire 8 for(int i=0; i<n; i++) 9 tab[i] = rand()%100; 10 11 // l opérateur \% (modulo) renvoie le reste de la division de a par b. En cas de problème, n hésitez pas à chercher de l aide sur : stackoverflow.com (questions/réponses) fr.openclassrooms.com/informatique/cours/apprenez-a-programmer-en-c (cours) 2 Exercices Exercice 1 (Swap). Écrire une fonction swap qui a comme paramètres deux pointeurs vers deux entiers et qui échange les deux entiers pointés. Tester sur des exemples. Exercice 2 (Palindrôme). Écrire une fonction palindrome qui prend une chaîne de caractères en entré. La fonction renvoie true si la chaîne est un palindrôme, false sinon. Vous pouvez utiliser la fonction strlen pour obtenir la longueur d une chaîne. Exemple de palindrômes : radar, kayak, level, noon... Exercice (Crible d Erathosthène). Écrire une fonction pour reproduire le crible d Erathosthène 1 et affiche à l ecran tous les nombres premiers inférieurs à 1000. Exercice 4 (Produit matriciel). Ecrire un programme qui calcule le produit de deux matrices d entiers. L utilisateur doit introduire les dimensions des matrices et leur contenu. Le produit matriciel sera également affiché ligne par ligne. Une matrice avec m lignes et n colonnes peut être stockée dans un tableau (à une dimension) de taille m n. Les lignes sont alors contigues en mémoire. On peut accéder à la case i de la ligne j de la façon suivante : tab[j * m + i]. Exercice 5 (Tri). Écrire une fonction de tri prenant un tableau et un entier n en paramètre. La fonction doit trier le tableau dans l ordre croissant. Vous devez implémentez au moins le tri par sélection et le tri à bulles : Tri par sélection O(n 2 ). L idée est de chercher le plus petit entier dans le tableau et de l insérer au début (en swapant les deux entiers). Ce nombre est le plus petit, il ne bougera plus. On cherche ensuite le deuxième plus petit entier pour l insérer en deuxième position, et continue jusqu à ce que tous les nombres soient insérés dans l ordre. (cf wikipedia 2 ) Tri à bulles O(n 2 ). L idée est de prendre le premier entier du tableau : si l entier suivant est plus petit que l entier courant, alors on fait remonter l entier courant (comme une bulle) jusqu à ce qu il soit plus petit que le suivant. Si c est le cas on passe à l entier suivant. Une fois arrivé au bout du tableau on recommence au début, et ce jusqu à ce que plus rien ne bouge! (cf wikipedia ) 1. http://fr.wikipedia.org/wiki/crible_d ratosthne 2. http://fr.wikipedia.org/wiki/tri_par_slection. http://fr.wikipedia.org/wiki/tri bulles 4
Bonus : Tri rapide (quick sort) O(n log n). C est l un des algorithme de tri les plus efficace (cf wikipedia 4 ) Il n est pas nécessaire d utiliser un tableau intermédiaire! Vous pouvez utiliser la fonction swap. Exercice (Changement de base). Écrire un algorithme qui prend un entier n en entré et l écrit en base 2. Par exemple pour le nombre 11 il faut obtenir : 1 0 1 1. Bonus : implémentez un algorithme qui effectue la conversion en héxadécimal (base 1). Indice : vous pouvez vous servir d un tableau de caractères pour représenter le système héxadécimal : char hexa[] = "01245789ABCDEF";. Exercice 7 (Approximation de π, méthode de Monte-Carlo). Dans cet exercise on cherche à trouver une approximation de π en utilisant une méthode de type Monte-Carlo, c est-à-dire un algorithme donnant une valeur numérique approchée de π en utilisant des tirages aléatoires. L idée est la suivante : Soit un point P de coordonnées (x, y) où x, y [0, 1]. On tire aléatoirement les valeurs de x et y. Le point P appartient au disque de centre de rayon 1 si et seulement si x 2 + y 2 1. La probabilité que le point P appartienne au disque est donc π/4. En faisant le rapport du nombre de points dans le disque par le nombre de tirages, on obtient une approximation du nombre π/4 si le nombre de tirages est grand. Exercice 8 (BONUS : Tours de Hanoi). Dans cet exercice, on souhaite résoudre une variante du problème des Tours de Hanoi. On dispose de disques, que l on peut empiler sous forme de tours à trois endroits différents, notées A, B et C. Les disques sont de diamètres différents. Initialement, tous les disques sont placés en A et on souhaite déplacer cette tour en C et ceci en un minimum de coups, tout en respectant les règles suivantes : on ne peut pas déplacer plus d un disque à la fois ; on ne peut placer un disque que sur un autre disque de diamètre supérieur ou égal (ou sur un emplacement vide). On suppose que cette dernière règle est également respectée dans la configuration de départ. Si on commence avec une configuration avec 2n disques, avec n diamètres différents (2 disques pour chaque diamètre) situés sur la tour A, vous devez écrire une fonction qui liste les coups nécessaires pour mettre tous les disques sur la tour C. Essayez d afficher l état des tours à chaque coup, comme dans l exemple suivant qui représente la configuration de départ pour n =. Testez pour n = 5. * * *** *** ***** ***** A B C 4. http://fr.wikipedia.org/wiki/tri_rapide 5