This commit is contained in:
Geoffrey Frogeye 2017-03-27 15:59:08 +02:00
parent 1a5e7af515
commit 45f6092d0d
11 changed files with 549 additions and 0 deletions

11
TP6/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
bole
buginsa
exo-bug
gdb-tutorial2
list
listesegf
perror
prime
an
boucle
scan

9
TP6/Makefile Normal file
View file

@ -0,0 +1,9 @@
all: $(patsubst %.c,%,$(shell ls *.c))
%: %.c
clang -Wall -Wextra $< -o $@ -g -lm
.PHONY: all clean
clean:
rm *.exe

20
TP6/boucle.c Normal file
View file

@ -0,0 +1,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
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; k<i;k++)
for(l=10; l>j; l--)
for(m=10; m>k; m--) // La comparaison a été inversée
for(n=10; n>0; n--)
compteur++;
return 0;
}

39
TP6/buginsa.c Normal file
View file

@ -0,0 +1,39 @@
/* bug.c, source: Christian NGUYEN */
#include <stdio.h>
#include <stdlib.h>
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;
}

27
TP6/exo-bug.c Normal file
View file

@ -0,0 +1,27 @@
/*exo-bug.c, A.Mine, ENS Ulm*/
#include <stdio.h>
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;
}

223
TP6/gdb-tutorial2.c Normal file
View file

@ -0,0 +1,223 @@
/*gdb-tutorial.c, Matthieu Moy pour ENSIMAG - Modif by LG pour Polytech Lille*/
#include <stdio.h>
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 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 bas !
*/
calcul_et_imprime_fact(10);
/*
Une dernière chose : il arrive que le programme parte dans une
boucle infinie, et on voudrait savoir 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 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);
}

72
TP6/list.c Normal file
View file

@ -0,0 +1,72 @@
/*TP GDB - DDD Programme listes*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
//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;
}

53
TP6/listesegf.c Normal file
View file

@ -0,0 +1,53 @@
/*Source Code From Laure Gonnord*/
/*int list - C implementation*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 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;
}

24
TP6/perror.c Normal file
View file

@ -0,0 +1,24 @@
/*Amelie Lambert pour ensiie*/
#include <stdio.h>
#include <stdlib.h>
#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;
}

48
TP6/prime.c Normal file
View file

@ -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 <stdio.h>
#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);
}
}

23
TP6/scan.c Normal file
View file

@ -0,0 +1,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#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<taille; index++)
tableau[2*index] = index;
return 0;
}