From 45f6092d0d1d0235ac6fbed271911f72a8fa1d41 Mon Sep 17 00:00:00 2001 From: Geoffrey Frogeye Date: Mon, 27 Mar 2017 15:59:08 +0200 Subject: [PATCH] TP6 --- TP6/.gitignore | 11 +++ TP6/Makefile | 9 ++ TP6/boucle.c | 20 ++++ TP6/buginsa.c | 39 ++++++++ TP6/exo-bug.c | 27 ++++++ TP6/gdb-tutorial2.c | 223 ++++++++++++++++++++++++++++++++++++++++++++ TP6/list.c | 72 ++++++++++++++ TP6/listesegf.c | 53 +++++++++++ TP6/perror.c | 24 +++++ TP6/prime.c | 48 ++++++++++ TP6/scan.c | 23 +++++ 11 files changed, 549 insertions(+) create mode 100644 TP6/.gitignore create mode 100644 TP6/Makefile create mode 100644 TP6/boucle.c create mode 100644 TP6/buginsa.c create mode 100644 TP6/exo-bug.c create mode 100644 TP6/gdb-tutorial2.c create mode 100644 TP6/list.c create mode 100644 TP6/listesegf.c create mode 100644 TP6/perror.c create mode 100644 TP6/prime.c create mode 100644 TP6/scan.c diff --git a/TP6/.gitignore b/TP6/.gitignore new file mode 100644 index 0000000..5f0e9ad --- /dev/null +++ b/TP6/.gitignore @@ -0,0 +1,11 @@ +bole +buginsa +exo-bug +gdb-tutorial2 +list +listesegf +perror +prime +an +boucle +scan diff --git a/TP6/Makefile b/TP6/Makefile new file mode 100644 index 0000000..b1e7f9d --- /dev/null +++ b/TP6/Makefile @@ -0,0 +1,9 @@ +all: $(patsubst %.c,%,$(shell ls *.c)) + +%: %.c + clang -Wall -Wextra $< -o $@ -g -lm + +.PHONY: all clean + +clean: + rm *.exe diff --git a/TP6/boucle.c b/TP6/boucle.c new file mode 100644 index 0000000..a9c8026 --- /dev/null +++ b/TP6/boucle.c @@ -0,0 +1,20 @@ +#include +#include +#include + + +int main() +{ + int i,j,k,l,m,n; + int compteur = 0; + + for(i=0; i<20;i++) + for(j=10; j>0;j--) + for(k=0; kj; l--) + for(m=10; m>k; m--) // La comparaison a été inversée + for(n=10; n>0; n--) + compteur++; + + return 0; +} diff --git a/TP6/buginsa.c b/TP6/buginsa.c new file mode 100644 index 0000000..3037655 --- /dev/null +++ b/TP6/buginsa.c @@ -0,0 +1,39 @@ +/* bug.c, source: Christian NGUYEN */ + +#include +#include + +void place( int *t, int i, int j) +{ + t [ i ] = j; +} + +void traitement( int n ) +{ int *t; + // unsigned int i; + // On remarque que i passe de 0 à 4294967295 + // Étant donné que i n'est pas signé, on a un underflow + // une solution pourrait être de mettre i en signé, + // ou de le compter dans le sens positif + int i; + t = (int*) malloc(n * sizeof(int )); + for( i = n-1; i >= 0 ; i--) + place( t, i , i*i ) ; + free( t ); +} + +int main ( int argc, char *argv[] ) +{ int n; + + if (argc == 2) + {n = atoi( argv[1] ); + printf("\nbug du -1\n"); + traitement( n ); + printf("done...\n"); + } + else + { + printf("nb arguments should be one"); + } + return 0; +} diff --git a/TP6/exo-bug.c b/TP6/exo-bug.c new file mode 100644 index 0000000..0115e54 --- /dev/null +++ b/TP6/exo-bug.c @@ -0,0 +1,27 @@ +/*exo-bug.c, A.Mine, ENS Ulm*/ +#include +int* p; + +int recherche(int* tab, int element, int nb) +{ + int min = 0, max = nb-1; + while ( min <= max ) { + int mid = (min+max) / 2; + if ( tab[mid] == element ) return 1; /* found */ + if ( tab[mid] < element ) min = mid; + else if (min + 1 <= max) break; // Ajout de cette ligne + else max = mid; + } + return 0; /* not found :( */ +} + +int main() +{ + int x[] = { 1, 5, 8, 9, 12, 16 }; + // p n'est pas initialisé (il est défini ligne 3) + // printf( "%i\n", recherche( p, 1, 1 ) ); + printf( "%i\n", recherche( x, 1, 1 ) ); /* must return 1 */ + printf( "%i\n", recherche( x, 12, 6 ) ); /* must return 1 */ + printf( "%i\n", recherche( x, 3, 6 ) ); /* must return 0 */ + return 1; +} diff --git a/TP6/gdb-tutorial2.c b/TP6/gdb-tutorial2.c new file mode 100644 index 0000000..0c8069d --- /dev/null +++ b/TP6/gdb-tutorial2.c @@ -0,0 +1,223 @@ +/*gdb-tutorial.c, Matthieu Moy pour ENSIMAG - Modif by LG pour Polytech Lille*/ +#include + +void f(void); +void calcul_et_imprime_fact(int n); +int fact(int n); + +/* Ce fichier est un tutorial pas-à-pas pour utiliser le déboggeur gdb. + Un débogueur est un outil précieux pour comprendre ce qui ne va pas + dans vos programmes. Les quelques minutes que vous allez passer à + apprendre à l'utiliser seront largement rentabilisées par la suite ! + + Commencez par le compiler. Pour pouvoir utiliser gdb, il faut + utiliser l'option -g de votre compilateur à la compilation : + + $ clang -g gdb-tutorial3.c -o gdb-tutorial + (clang vous met un warning que vous ignorerez). + + Vous pouvez lancer l'exécutable gdb-tutorial dans gdb en ligne de + commande comme ceci : + + $ gdb ./gdb-tutorial + + Commençons par quelque chose de simple : démarrer le programme. On + tape "run", ou simplement la lettre "r" dans la ligne de commande + gdb (dans votre terminal) L'exécution s'arrete sur un "segmentation + fault à la ligne 50 de ce fichier, on d'y retrouve !*/ + +int main (int argc, char ** argv) { + unsigned i; + int j; + int * ptr = NULL; /* NULL est une adresse invalide, on n'a pas le + droit de déréférencer un pointeur NULL */ + printf ("Bonjour\n"); + printf ("Je vais faire un acces memoire interdit\n"); + /* + La ligne suivante va faire un "Segmentation fault". + + Le déboggeur va s'arrêter sur cette ligne. + */ + *ptr = 0; + /* + Bon, le bug était facile à trouver. Mettez la ligne ci-dessus en + commentaire pour éliminer le problème, recompilez, et lisez la + suite. + On va maintenant faire une execution pas-à-pas. Il faut commencer + par donner à gdb un endroit du code où on veut + s'arrêter : un point d'arrêt. + + Dans la ligne de commande gdb : "break gdb-tutorial3.c:55" + + puis "run" + + */ + printf ("On avance ...\n"); /* mettre le point d'arrêt ici */ + /* + Maintenant, vous devriez avoir votre programme arrêté sur la ligne + qui précède. Tapez "next", ou simplement "n" pour avancer dans + l'execution du programme, plusieurs fois. Petite astuce, après + avoir tapé "n" une fois, il suffit d'appuyer sur Entrée pour + refaire un "next". + */ + printf ("On avance encore ...\n"); + printf ("On avance encore un peu ...\n"); + printf ("On avance encore un peu ...\n"); + printf ("On avance une derniere fois ...\n"); + printf ("Et voila !\n"); + /* + Il y a deux commandes pour executer un programme pas à pas : + - next, pour exécuter complètement l'instruction suivante + - step, "rentre" dans la fonction si l'instruction suivante est un + appel de fonction. + Essayez successivement "step" et "next" sur les lignes suivantes. + Au passage "up" permet de revenir un cran plus haut dans la pile d'exec + */ + f(); /*step 1 fois, puis next pour avancer a l'interieur de f*/ + f(); + f(); + /* + Bon, l'execution pas à pas, c'est bien, mais c'est pénible quand + il y a beaucoup de code à exécuter. Par exemple, la boucle + suivante prendrait trop de temps, on veut la sauter. Pour cela, + poser un point d'arrêt sur la ligne qui suit la boucle (98), puis + faites "continue" (ou juste "c") dans gdb. + */ + j = 0; + for (i = 0; i <= 1000; ++i) { + j = j + i; + } + printf ("Fin de la boucle\n"); /* mettre le point d'arrêt ici */ + /* + On peut bien sûr visualiser le contenu d'une variable, + avec la commande "print", ou simplement "p". On peut + maintenir l'affichage d'une variable avec "display". + + Par exemple, faites maintenant "display i", puis exécutez la + boucle suivante pas à pas. Faites "p j" pour connaitre la valeur + de j. Ensuite mettez un breakpoint apres la boucle (ligne 130) + et "c" pour y aller. + */ + + for (i = 1; i <= 1000; i = i * 2) { + j = j + i; + } + /* + On peut aussi afficher des expressions C un peu plus complexes. + Essayez par exemple + (gdb) p i+j + (gdb) p &i + (gdb) p &j + (gdb) p dire_bonjour("Monsieur") + + (dans le dernier cas, gdb va effectivement appeler la fonction + dire_bonjour, définie plus bas) + + On peut aussi s'amuser un peu avec les pointeurs. Faites: + + (gdb) p &i + $2 = (unsigned int *) 0xbf9bfde8 + + La valeur 0xbf9bfde8, adresse de i, sera a priori différente chez + vous. Affichez maintenant l'expression *(unsigned int *)0xbf9bfde8 + (en remplaçant 0xbf9bfde8 par la valeur que vous avez eu ci-dessus). + Vous devriez avoir 1024, qui est bien la valeur de i. + + Avant de passer à la suite, on va supprimer cette impression de i + display, puis undisplay n avec n le numéro du display concernant i + + */ + printf ("i=%d\n", i); + + /* + Tout ça se complique un peu quand on a des appels de fonctions. + Entrez dans la fonction fact appelée à la ligne suivante avec la + commande "s", on se retrouve là bas ! + */ + calcul_et_imprime_fact(10); + + /* + Une dernière chose : il arrive que le programme parte dans une + boucle infinie, et on voudrait savoir où est cette boucle. + + Rien de plus simple : lancez le programme ("c" pour "continue"), + puis tapez Control-c pour arrêter son execution et reprendre la + main dans gdb (dans votre terminal) + + Utilisez cette technique pour voir la(les)quelle(s) de ces boucles + est/sont une(des) boucle(s) infinie(s). Commentez les boucles infinies et + recompilez avant de passer à la suite. + */ + j = 1; + while (j > 0) { + ++j; + } + + i = 10; + while (i >= 0) { + --i; + } + + i = 0; j = 0; + while (i == j) { + ++i; ++j; + } + /* Voilà, vous avez terminé et vous savez à peu près tout ce que vous + devez savoir pour une utilisation courante. Les plus curieux + pourront lire le manuel de gdb : + http://sourceware.org/gdb/download/onlinedocs/ */ +} + +void f(void) { + printf ("Appel de f()\n"); + printf ("Fin de f()\n"); +} + +void calcul_et_imprime_fact(int n) { + /* + Re-bonjour, + + À ce stade, n doit être égal à 10. Vérifiez avec un "p n". Entrez + dans la fonction fact avec un "step", on s'y retrouve. + */ + int res = fact(n); + printf ("fact(%d) = %d\n", n, res); +} + +int fact(int n) { + //printf ("Calcul de fact(%d)\n", n); + /* + Si c'est la première fois que vous passez ici, n doit être égal à + 10. Vérifiez avec un "p n". Continuez l'exécution pas à pas avec + "step" (et non "next", pour rentrer dans les appels récursifs + successifs de fact). Faites par exemple 5 appels puis lisez le + commentaire suivant. + */ + + /* + Voilà, je suppose que vous en êtes au 5ème appel récursif. Donc, + "n" doit valoir 5. Vérifiez avec "p n". + + Mais dans la pile, il y a toujours les autres appels, avec les + valeurs de "n" comprises entre 10 et 5. Faites "where" pour voir + l'état de la pile. + + Pour naviguer dans la pile, utilisez les commandes "up" et "down". + Par exemple, faites deux fois "up", puis "p n". Vous voyez la + valeur de "n" au 3ème appel, c'est à dire 7. + + Faites deux fois "down", et vous voilà revenu où vous êtiez. + Faites maintenant "finish" pour terminer + l'appel de fonction courant, plusieurs fois, jusqu'à revenir à la fonction + "main" (ligne 167) + */ + if (n <= 1) { + return 1; + } else { + return n * fact(n - 1); + } +} + +void dire_bonjour(char * nom) { + printf("Bonjour, %s\n", nom); +} diff --git a/TP6/list.c b/TP6/list.c new file mode 100644 index 0000000..1b81b2f --- /dev/null +++ b/TP6/list.c @@ -0,0 +1,72 @@ +/*TP GDB - DDD Programme listes*/ + +#include +#include +#include + + +//définition de types +typedef struct Cell { + int key; /*integer cell*/ + struct Cell* nextC; /*ref to the next cell*/ +} Cell; + +typedef Cell* Liste; // alias + + +//insertion en tête +void insertinList(Liste* mylist, int el) +{ + Cell* newCell=(Cell*) malloc(sizeof(Cell)); + newCell->key=el; + *mylist=newCell; +} + +//impression +void printList(Liste mylist) +{ + Cell* p=mylist; + printf("["); + while(p!=NULL) + { + printf("%d",p->key); + if (p->nextC!=NULL) printf(","); + // La ligne suivante avait été oubliée + p=p->nextC; + } + printf("]\n"); +} + +// creation +Liste creeListePositive() +{ + Liste thelist=NULL ; + bool fini = false; + int val; + // initialiser !! + while(!fini) + { + printf("donner un élément >=0, et <0 vous voulez arrêter\n"); + scanf("%d",&val); + if(val>=0){ + insertinList(&thelist,val); + } + else fini = true; + } + return thelist; +} + + +/********* Fonction Principale *********/ +int main(int argc, char *argv[]) +{ + //déclaration + Liste ltest,ltest1; + + //initialisation + ltest1=creeListePositive(); + + //impression + printList(ltest1); + return 0; +} diff --git a/TP6/listesegf.c b/TP6/listesegf.c new file mode 100644 index 0000000..9fd4282 --- /dev/null +++ b/TP6/listesegf.c @@ -0,0 +1,53 @@ +/*Source Code From Laure Gonnord*/ +/*int list - C implementation*/ + +#include +#include +#include + + +// définition du type liste d'entiers. +typedef struct Cell{ + int el; + struct Cell* suivant; +} Cell; + +typedef Cell* Liste; + +void insereEnTete(Liste* pL,int elem) +{ + //creation de la cellule avec l'élément. + Cell* pc = (Cell*) malloc(sizeof(Cell)); + (*pc).el = elem; + (*pc).suivant = *pL; + *pL = pc; +} + +void imprimeListe(Liste l) +{ + Cell* pc = l; + while(pc != NULL) { + printf("%d,",(*pc).el); + pc = (*pc).suivant ; + } + printf("\n"); +} + +int main(){ + Liste maliste; + // maliste n'est pas initialisée + // le dernier élément quand imprimeListe est executé + // est donc indéfini, et le printf ligne 30 essaye + // d'afficher des données non initialisées + + // Cela devrait aller un peu mieux + maliste = NULL; + + insereEnTete(&maliste,4); + insereEnTete(&maliste,42); + insereEnTete(&maliste,2); + + imprimeListe(maliste); + + return 0; +} diff --git a/TP6/perror.c b/TP6/perror.c new file mode 100644 index 0000000..e83c038 --- /dev/null +++ b/TP6/perror.c @@ -0,0 +1,24 @@ +/*Amelie Lambert pour ensiie*/ +#include +#include + +#define SIZE 42 + +int main (void) +{ + int *tab; + int i; + + tab = malloc (SIZE * sizeof(int)); + + // L'instruction suivante était une assignation + if (tab == NULL) { + perror ("malloc()"); + exit (-1); + } + + for (i = 0; i < SIZE; i++) + tab[i] = random(); + + return 0; +} diff --git a/TP6/prime.c b/TP6/prime.c new file mode 100644 index 0000000..81c86ef --- /dev/null +++ b/TP6/prime.c @@ -0,0 +1,48 @@ +/* prime-number finding program +will (after bugs are fixed) report a list of all primes which are +less than or equal to the user-supplied upper bound riddled with errors! */ +#include + +#define MaxPrimes 50 + +int Prime[MaxPrimes], /* Prime[I] will be 1 if I is prime, 0 otherwise */ + UpperBound; /* we will check all number up through this one for + primeness */ + + +void CheckPrime(int K) +{ int J; + /* the plan: see if J divides K, for all values J which are + (a) themselves prime (no need to try J if it is nonprime), and + (b) less than or equal to sqrt(K) (if K has a divisor larger + than this square root, it must also have a smaller one, + so no need to check for larger ones) */ + J = 2; + // On s'arrête avant de dépasser le tableau + while (J < MaxPrimes) { + if (Prime[J] == 1) + if (K % J == 0) { + Prime[K] = 0; + return; + } + J++; + } + + /* if we get here, then there were no divisors of K, so it is + prime */ + Prime[K] = 1; +} + +int main() +{ + int N; + printf("enter upper bound\n"); + scanf("%d",&UpperBound); + + Prime[2] = 1; + for (N = 3; N <= UpperBound; N += 2) + { + CheckPrime(N); + if (Prime[N]) printf("%d is a prime\n",N); + } +} diff --git a/TP6/scan.c b/TP6/scan.c new file mode 100644 index 0000000..927d287 --- /dev/null +++ b/TP6/scan.c @@ -0,0 +1,23 @@ +#include +#include +#include +#define MAXNUM 12 + +/* Pour compiler, rajoutez l'argument "-lm" a l'appel de gcc */ + +int main() +{ + // index était un char, et a va de -128 à 128 + // cependant on doit l'utiliser pour des valeurs beaucoup plus grandes + // il y avait donc overflow + int index; + char * tableau; + double taille = exp(MAXNUM); + tableau = malloc (4*taille*sizeof(char)); + index = 0; + + for(index = 0; index