TP6
This commit is contained in:
parent
1a5e7af515
commit
45f6092d0d
11
TP6/.gitignore
vendored
Normal file
11
TP6/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
bole
|
||||
buginsa
|
||||
exo-bug
|
||||
gdb-tutorial2
|
||||
list
|
||||
listesegf
|
||||
perror
|
||||
prime
|
||||
an
|
||||
boucle
|
||||
scan
|
9
TP6/Makefile
Normal file
9
TP6/Makefile
Normal 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
20
TP6/boucle.c
Normal 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
39
TP6/buginsa.c
Normal 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
27
TP6/exo-bug.c
Normal 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
223
TP6/gdb-tutorial2.c
Normal 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 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);
|
||||
}
|
72
TP6/list.c
Normal file
72
TP6/list.c
Normal 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
53
TP6/listesegf.c
Normal 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
24
TP6/perror.c
Normal 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
48
TP6/prime.c
Normal 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
23
TP6/scan.c
Normal 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;
|
||||
}
|
Reference in a new issue