init projet

This commit is contained in:
2024-10-06 15:32:20 +02:00
commit d449d4b10a
84 changed files with 13546 additions and 0 deletions

BIN
tp3/TP3.tgz Normal file

Binary file not shown.

12
tp3/TP3/.ccls Normal file
View File

@@ -0,0 +1,12 @@
gcc-13
%c -std=std2x
%c -Wall
%c -Wextra
%c -pedantic
%c -Wshadow
%c -Wpointer-arith
%c -Wcast-qual
%c -Wstrict-prototypes
%c -Wmissing-prototypes
%c -Wno-gnu-zero-variadic-macro-arguments
%c -I/opt/homebrew/include/

3640
tp3/TP3/.uncrustify Normal file

File diff suppressed because it is too large Load Diff

37
tp3/TP3/Makefile Normal file
View File

@@ -0,0 +1,37 @@
CC=gcc
# clang 14.0.3 does implement the C23 feature __VA_OPTS__ but issues a spurious
# warning. The -Wno-gnu-zero-variadic-macro-arguments disables this warning.
# This flag is ignored by gcc (which implements __VA_OPTS__ without any warning).
override CFLAGS += -std=gnu2x -MMD -Wall -pedantic -Wextra -Wshadow -Wpointer-arith \
-Wcast-qual -Wstrict-prototypes -Wmissing-prototypes
# For MacOS (assuming recent homebrew)
ifeq ($(shell uname -s), Darwin)
CPPFLAGS+=-I/opt/homebrew/include
LDFLAGS+=-L/opt/homebrew/lib
override CFLAGS += -Wno-gnu-zero-variadic-macro-arguments
endif
SOURCES := $(wildcard *.c)
OBJECTS := $(SOURCES:%.c=%.o)
DEPS := $(SOURCES:%.c=%.d)
# Compilation in debug mode by default, to use gdb and valgrind. Warnings produce an error.
all: CFLAGS += -g -O0 -Werror -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable
all: stackqueue
# Once the program works, optimized mode (and no error in case of warning).
nowerror: CFLAGS += -O3
nowerror: stackqueue
stackqueue: $(OBJECTS)
$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^ $(LDLIBS)
# Include dependancies generated by gcc -MMD.
-include $(DEPS)
# Clean all.
.PHONY: clean
clean:
rm -rf stackqueue *.o *.d TAGS core a.out

19
tp3/TP3/alloc.c Normal file
View File

@@ -0,0 +1,19 @@
/**
* @file alloc.c
* @brief Fonctions d'allocation mémoire.
*/
#include "alloc.h"
void check_null(const char *function, char *file, int line, int n, ...) {
va_list ap;
va_start(ap, n);
for (int i = 0; i < n; i++) {
const void *p = va_arg(ap, void *);
char *s = va_arg(ap, char *);
if (p == NULL)
PRINT_ERROR(KO, "CRITICAL", function, file, line, "%s is NULL.", s);
}
va_end(ap);
}

1
tp3/TP3/alloc.d Normal file
View File

@@ -0,0 +1 @@
alloc.o: alloc.c alloc.h error.h

178
tp3/TP3/alloc.h Normal file
View File

@@ -0,0 +1,178 @@
/**
* @file alloc.h
* @brief Macros et fonctions d'allocation mémoire.
*
* @details Les macros MALLOC(), CALLOC() et REALLOC() définies dans ce fichier
* permettent d'allouer de la mémoire dynamiquement, en vérifiant que
* l'allocation a réussi. En cas d'échec, elles affichent un message d'erreur
* sur la sortie erreur, en indiquant la fonction, le fichier et la ligne où
* l'allocation a échoué, et quittent le programme.
*
* La fonction multiple_free() permet de libérer plusieurs pointeurs en
* un seul appel (mais attention, aucun de ces pointeurs ne doit être `NULL`, et
* tous doivent avoir été alloués dynamiquement avant cette libération).
*
* La macro CHECK_NULL() permet de vérifier qu'un ou plusieurs pointeurs ne sont
* pas `NULL`.
*
* La fonction check_null() n'est pas destinée à être utilisée directement, mais
* est utilisée par la macro CHECK_NULL().
*/
#ifndef ALLOC_H_
#define ALLOC_H_
#include "error.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Macro pour allouer de la mémoire en utilisant la fonction malloc().
* @param p Pointeur à allouer.
* @param num_objects Nombre d'objets à allouer.
*
* @details
* Alloue de la mémoire permettant de stocker `num_objects`, chacun de type
* `*p`.
*
* **Exemple d'utilisation :**
* ```
* int *p;
* MALLOC(p, 10); // Alloue un tableau de 10 int.
* ```
*
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
*
* @attention
* Le pointeur `p` doit avoir été déclaré, mais ne pas pointer vers une zone
* déjà allouée dynamiquement (sous peine de créer une fuite mémoire).
* Si `p` pointe déjà vers une zone allouée dynamiquement, il faut utiliser
* REALLOC.
*
* @see REALLOC()
*/
#define MALLOC(p, num_objects) \
do { \
void *tmp = malloc(sizeof *(p) * (num_objects)); \
if (!tmp) { \
FATAL("Malloc error."); \
} \
(p) = tmp; \
} while (0)
/**
* @brief Macro pour allouer de la mémoire en utilisant la fonction calloc().
* @param p Pointeur à allouer.
* @param num_objects Nombre d'objets à allouer.
*
* @details
* Alloue de la mémoire initialisée à 0, permettant de stocker `num_objects`,
* chacun de type `*p`.
*
* **Exemple d'utilisation :**
* ```
* int *p;
* CALLOC(p, 10); // Alloue un tableau de 10 int, initialisé à 0.
* ```
*
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
*
* @attention
* Le pointeur `p` doit avoir été déclaré, mais ne pas pointer vers une zone
* déjà allouée dynamiquement (sous peine de créer une fuite mémoire).
* Si `p` pointe déjà vers une zone allouée dynamiquement, il faut utiliser
* REALLOC.
*
* @sa REALLOC()
*/
#define CALLOC(p, num_objects) \
do { \
void *tmp = calloc((num_objects), sizeof *(p)); \
if (!tmp) { \
FATAL("Calloc error."); \
} \
(p) = tmp; \
} while (0)
/**
* @brief Macro pour réallouer de la mémoire en utilisant la fonction realloc().
* @param p Pointeur à allouer.
* @param num_objects Nouveau nombre d'objets à allouer.
*
* Ré-alloue la mémoire pointée par un pointeur p, dont la valeur doit avoir été
* retournée précédemment par une fonction d'allocation dynamique (malloc,
* calloc, realloc ou une des macros de ce fichier).
*
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
*
* **Exemple d'utilisation :**
* ```
* int *p;
* MALLOC(p, 10); // Alloue un tableau de 10 int.
* // ...
* REALLOC(p, 20); // Ré-alloue un tableau de 20 int en copiant le tableau
* // précédent en début ce nouveay tableau, et affecte à p
* // l'adresse de la première case de ce tableau.
* ```
*
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
*
* @attention
* Le pointeur `p` doit avoir été déclaré et pointer vers une zone
* déjà allouée dynamiquement.
*
* @sa MALLOC(), CALLOC()
*/
#define REALLOC(p, num_objects) \
do { \
void *tmp = realloc((p), sizeof *(p) * (num_objects)); \
if (!tmp) { \
FATAL("Realloc error."); \
} \
(p) = tmp; \
} while (0)
/**
* @brief Macro permettant de tester si un ou plusieurs pointeurs sont NULL.
* @param n Nombre de pointeurs à tester.
* @param ... Pointeurs à tester, en alternance avec des chaînes de caractères.
*
* Il doit y avoir un pointeur à tester pour chaque chaîne de caractères, et
* inversement.
*
* La chaîne de caractères qui suit chaque pointeur permet de personnaliser le
* message d'erreur.
*
* @details
* **Exemple d'utilisation :**
* ```
* CHECK_NULL(3, p1, "Name1", p2, "Name2", p3, "Name3");
* ```
* Ici, 3 est le nombre de pointeurs à vérifier, et p1, p2, p3 sont les
* pointeurs. Si `p1` et `p3` sont NULL, la macro affichera un message d'erreur
* de la forme :
***
[CRITICAL] Name1 is NULL!\n
[CRITICAL] Name3 is NULL!
***
* @sa check_null()
*/
#define CHECK_NULL(n, ...) \
check_null(__func__, __FILE__, __LINE__, n __VA_OPT__(, ) __VA_ARGS__)
/**
* @brief Ne pas utiliser cette fonction directement, mais à la place la macro
* ::CHECK_NULL(), qui indique dans le message la position de l'erreur dans le
* source.
*
* @sa CHECK_NULL()
*/
void check_null(const char *function, char *file, int line, int n, ...);
#endif // ALLOC_H_

BIN
tp3/TP3/alloc.o Normal file

Binary file not shown.

58
tp3/TP3/error.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef ERROR_H_
#define ERROR_H_
#define ATTENTION "\xe2\x9d\x97"
#define HINT "\xe2\x9c\xa8"
#define OK "\xE2\x9C\x85"
#define KO "\xE2\x9D\x8C"
// In X mode, all messages more severe than X are printed.
// clang-format off
enum debug_level {OFF, CRITICAL, ERROR, WARNING, INFO, DEBUG, TRACE};
enum msg_level {CRITICAL_L, ERROR_L, WARNING_L, INFO_L, DEBUG_L, TRACE_L};
// clang-format on
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL INFO
#endif
// __VA_OPTS__ requires C2x. Clang issues spurious warning.
#define PRINT_ERROR(symbol, name, function, file, line, msg, ...) \
do { \
fprintf(stderr, \
"\n" symbol \
" [" \
name \
"]" \
" - Function %s (%s:%d) -\n " \
msg "\n", \
function, file, line \
__VA_OPT__( , ) __VA_ARGS__); \
} while (0)
#define FATAL(msg, ...) \
do { \
PRINT_ERROR(ATTENTION, "FATAL", __func__, __FILE__, __LINE__, msg __VA_OPT__( , ) __VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
#define PRINT_DEBUG(symbol, name, level, msg, ...) \
do { \
if ((int)DEBUG_LEVEL > (int)level) \
PRINT_ERROR(symbol, name, __func__, __FILE__, __LINE__, msg __VA_OPT__( , ) __VA_ARGS__); \
} while (0)
#define TRACE(msg, ...) PRINT_DEBUG(OK, "TRACE", TRACE_L, msg, __VA_ARGS__)
#define DEBUG(msg, ...) PRINT_DEBUG(HINT, "DEBUG", DEBUG_L, msg, __VA_ARGS__)
#define INFO(msg, ...) PRINT_DEBUG(HINT, "INFO", INFO_L, msg, __VA_ARGS__)
#define WARNING(msg, ...) PRINT_DEBUG(ATTENTION, "WARNING", WARNING_L, msg, __VA_ARGS__)
#define ERROR(msg, ...) PRINT_DEBUG(ATTENTION, "ERROR", ERROR_L, msg, __VA_ARGS__)
#define CRITICAL(msg, ...) PRINT_DEBUG(KO, "CRITICAL", CRITICAL_L, msg, __VA_ARGS__)
#endif // ERROR_H_

128
tp3/TP3/main.c Normal file
View File

@@ -0,0 +1,128 @@
#include "alloc.h"
#include "queuetest.h"
#include "stacktest.h"
#include "testprint.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Basculez à 1 les valeurs ci-dessous pour activer les tests correspondants.
#define TEST_STACK_BASIC 1
#define TEST_SORT_STACK 0
#define TEST_COPY_STACK 1
#define TEST_HANOI 1
#define TEST_QUEUE_BASIC 0
#define TEST_COPY_QUEUE 0
#define TEST_SORT_QUEUE 0
int main(void) {
// Initialisation du générateur de nombres aléatoires
srandom(time(NULL));
#if TEST_STACK_BASIC
stack *p, *r, *s;
printf("\nTest de random et de tower\n\n");
p = random_stack(42, 999);
r = tower_stack(42);
s = tower_stack(42);
print_stacks(0, 2, p, r);
printf("\nTest de push\n\n");
for (int i = 0; i < 24; i++) // pour provoquer un grow
push(i, s);
print_stacks(0, 2, r, s);
printf("\nTest de pop\n\n");
delete_stack(s);
s = tower_stack(42);
for (int i = 0; i < 40; i++) // pour provoquer un shrink
pop(s);
print_stacks(0, 2, r, s);
delete_stack(p);
delete_stack(r);
delete_stack(s);
#endif
#if TEST_COPY_STACK
stack *p1, *p2;
printf("\nTest de copy_stack\n\n");
p1 = random_stack(42, 999);
p2 = copy_stack(p1);
print_stacks(0, 2, p1, p2);
delete_stack(p1);
delete_stack(p2);
#endif
#if TEST_SORT_STACK
printf("\nTest de bubble_sort_stack\n\n");
stack *t = random_stack(42, 999);
printf("Avant le tri\n\n");
print_stacks(0, 1, t);
bubble_sort_stack(t);
printf("Après le tri\n\n");
print_stacks(0, 1, t);
delete_stack(t);
#endif
#if TEST_HANOI
printf("\nTest de Hanoi\n\n");
hanoi(3);
#endif
#if TEST_QUEUE_BASIC
queue *p, *r, *s;
printf("\nTest de random et de mountain\n\n");
p = random_queue(42, 50);
r = mountain_queue(21);
s = mountain_queue(21);
print_queue(p);
print_queue(r);
printf("\nTest de enqueue\n\n");
for (int i = 0; i < 24; i++) // pour provoquer un grow
enqueue(99 - i, s);
print_queue(r);
print_queue(s);
printf("\nTest de dequeue\n\n");
delete_queue(s);
s = mountain_queue(21);
for (int i = 0; i < 40; i++) // pour provoquer un shrink
dequeue(s);
print_queue(r);
print_queue(s);
delete_queue(p);
delete_queue(r);
delete_queue(s);
#endif
#if TEST_COPY_QUEUE
queue *p1, *p2;
printf("\nTest de copy_queue\n\n");
p1 = random_queue(42, 99);
p2 = copy_queue(p1);
print_queue(p1);
print_queue(p2);
delete_queue(p1);
delete_queue(p2);
#endif
#if TEST_SORT_QUEUE
printf("\nTest de select_sort_queue\n\n");
queue *t = random_queue(5, 100);
printf("Avant le tri\n");
print_queue(t);
select_sort_queue(t);
printf("\nAprès le tri\n");
print_queue(t);
delete_queue(t);
#endif
return EXIT_SUCCESS;
}

2
tp3/TP3/main.d Normal file
View File

@@ -0,0 +1,2 @@
main.o: main.c alloc.h error.h queuetest.h queue.h stacktest.h stack.h \
testprint.h

BIN
tp3/TP3/main.o Normal file

Binary file not shown.

53
tp3/TP3/queue.c Normal file
View File

@@ -0,0 +1,53 @@
#include "queue.h"
#include "alloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/////////////////////////////////////////////////////////////////////////////////
// Fonctions auxiliaires ne pouvant pas être utilisées dans d'autres fichiers. //
// Elles ne sont pas déclarées dans queue.h et sont déclarées "static". Cela //
// signifie qu'elles ne peuvent être utilisées QUE dans ce fichier, queue.c. //
/////////////////////////////////////////////////////////////////////////////////
// Double la taille du tableau utilisé dans la représentation.
// Cette fonction sera utilisée lorsque le tableau est plein et qu'on veut y
// ajouter une valeur.
static void grow_queue(queue *p) {
return;
}
// Divise par deux la taille du tableau utilisé dans la représentation
// Cette fonction sera utilisée lorsque le tableau est rempli à moins de 25% de
// sa capacité.
static void shrink_queue(queue *p) {
return;
}
////////////////////////////////////////////////////////////////
// Fonctions primitives, exportées dans le fichier d'en-tête. //
////////////////////////////////////////////////////////////////
queue *create_queue(void) {
return NULL;
}
void delete_queue(queue *p) {
return;
}
bool isempty_queue(const queue *p) {
return false;
}
int getsize_queue(const queue *p) {
return 0;
}
void enqueue(int val, queue *p) {
return;
}
int dequeue(queue *p) {
return 0;
}

1
tp3/TP3/queue.d Normal file
View File

@@ -0,0 +1 @@
queue.o: queue.c queue.h alloc.h error.h

45
tp3/TP3/queue.h Normal file
View File

@@ -0,0 +1,45 @@
/*********************************************/
/** Implémentation des files par un tableau **/
/*********************************************/
#ifndef DEQUEUE_H_
#define DEQUEUE_H_
#include <stdbool.h>
////////////////////////
// Définition du type //
////////////////////////
typedef struct {
int *array; // Tableau des valeurs.
int size_array; // Taille du tableau des valeurs.
int left; // Indice de la valeur à gauche de la file (si non-vide).
int right; // Indice qui suit celui de la valeur à droite de la file
// (si elle est non-vide).
bool empty; // Booléen indiquant si la file est vide.
} queue;
//////////////////////////
// Fonctions primitives //
//////////////////////////
// Crée une file vide.
queue *create_queue(void);
// Libère la mémoire allouée pour la file.
void delete_queue(queue *);
// Renvoie le nombre d'éléments dans la file.
int getsize_queue(const queue *);
// Renvoie vrai si la file est vide, faux sinon.
bool isempty_queue(const queue *);
// Ajoute une valeur dans la file, à gauche de la valeur la plus à gauche.
void enqueue(int, queue *);
// Renvoie la valeur la plus à droite de la file et la retire.
int dequeue(queue *);
#endif // DEQUEUE_H_

BIN
tp3/TP3/queue.o Normal file

Binary file not shown.

21
tp3/TP3/queuetest.c Normal file
View File

@@ -0,0 +1,21 @@
#include "queuetest.h"
#include "alloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
queue *random_queue(int size, int maxval) {
return NULL;
}
queue *copy_queue(queue *p) {
return NULL;
}
queue *mountain_queue(int n) {
return NULL;
}
void select_sort_queue(queue *p) {
return;
}

1
tp3/TP3/queuetest.d Normal file
View File

@@ -0,0 +1 @@
queuetest.o: queuetest.c queuetest.h queue.h alloc.h error.h

36
tp3/TP3/queuetest.h Normal file
View File

@@ -0,0 +1,36 @@
/******************************/
/** Fonctions de test: files **/
/******************************/
#ifndef DEQUEUETEST_H_
#define DEQUEUETEST_H_
#include "queue.h"
// Crée une file aléatoire de valeurs entre 0 et maxval de taille size
// Si size est inférieure ou égal à 0, la file construite sera vide.
queue *random_queue(int, int);
// Crée une copie d'une file.
queue *copy_queue(queue *);
// Crée la file suivante :
// 1 2 3 4 .... n n .... 4 3 2 1
// Si n est inférieur ou égal à 0, la file construite est vide.
queue *mountain_queue(int);
// Trie la file par ordre croissant (la plus grande valeur à droite).
// L'algorithme devra être basé sur le principe du tri par sélection.
// Le principe de ce tri est le suivant :
// - On cherche le minimum de la file et on le place à gauche.
// - On cherche le minimum du reste de la file et on le place à sa droite.
// - On continue jusqu'à ce que la file soit triée.
// Voir https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html ou
// https://visualgo.net/en/sorting pour une visualisation de cet algorithme.
//
// La file doit être triée sur place, c'est-à-dire que la file passée en
// paramètre doit être modifiée. Aucune structure auxiliaire n'est autorisée, et
// la récursivité n'est pas autorisée non plus.
void select_sort_queue(queue *);
#endif // DEQUEUETEST_H_

BIN
tp3/TP3/queuetest.o Normal file

Binary file not shown.

80
tp3/TP3/stack.c Normal file
View File

@@ -0,0 +1,80 @@
#include "stack.h"
#include "alloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/////////////////////////////////////////////////////////////////////////////////
// Fonctions auxiliaires ne pouvant pas être utilisées dans d'autres fichiers. //
// Elles ne sont PAS déclarées dans stack.h et sont déclarées "static". Cela //
// signifie qu'elles ne peuvent être utilisées QUE dans ce fichier, stack.c. //
/////////////////////////////////////////////////////////////////////////////////
// Double la taille du tableau utilisé dans la représentation.
// Cette fonction sera utilisée lorsque le tableau est plein et qu'on veut y
// ajouter une valeur.
static void grow_stack(stack *p) {
p -> size_array *= 2;
p -> array = realloc(p -> array, p -> size_array * sizeof(int));
return;
}
// Divise par deux la taille du tableau utilisé dans la représentation.
// Cette fonction sera utilisée lorsque le tableau est rempli à moins de 25% de
// sa capacité.
static void shrink_stack(stack *p) {
if (p -> size_array >= 2) {
p -> size_array /= 2;
p -> array = realloc(p -> array, p -> size_array * sizeof(int));
}
return;
}
////////////////////////////////////////////////////////////////
// Fonctions primitives, exportées dans le fichier d'en-tête. //
////////////////////////////////////////////////////////////////
stack *create_stack(void) {
stack *p = malloc(sizeof(stack));
p -> size_array = 1;
p -> size_stack = 0;
p -> array = malloc(sizeof(int));
return p;
}
void delete_stack(stack *p) {
if (p == NULL) return;
free(p -> array);
free(p);
return;
}
bool isempty_stack(stack *p) {
return p -> size_stack == 0;
}
int size_stack(stack *p) {
return p -> size_stack;
}
int pop(stack *p) {
if (p -> size_stack <= 0) {
FATAL("Pop on empty stack");
}
int val = p -> array[p -> size_stack - 1];
p -> size_stack--;
if (p -> size_stack <= p -> size_array / 4) {
shrink_stack(p);
}
return val;
}
void push(int val, stack *p) {
if (p -> size_stack >= p -> size_array) {
grow_stack(p);
}
p -> array[p -> size_stack] = val;
p -> size_stack++;
return;
}

1
tp3/TP3/stack.d Normal file
View File

@@ -0,0 +1 @@
stack.o: stack.c stack.h alloc.h error.h

49
tp3/TP3/stack.h Normal file
View File

@@ -0,0 +1,49 @@
/***********************************************/
/***********************************************/
/** Implémentation des piles par les tableaux **/
/***********************************************/
/***********************************************/
#ifndef STACK_H_
#define STACK_H_
#include <stdarg.h>
#include <stdbool.h>
/***********************/
/* Déclaration du type */
/***********************/
typedef struct {
int size_array; // Taille totale du tableau alloué en mémoire.
int size_stack; // Nombre d'éléments dans la pile représentée.
int *array; // Tableau contenant les valeurs de la pile représentée.
} stack;
/************************/
/* Fonctions primitives */
/************************/
// Crée une pile vide.
stack *create_stack(void);
// Libère la mémoire allouée pour la pile.
void delete_stack(stack *);
// Renvoie vrai si la pile est vide, faux sinon.
bool isempty_stack(stack *);
// Renvoie le nombre d'éléments dans la pile.
int size_stack(stack *);
// Renvoie la valeur au sommet de la pile et la retire. Si la pile est vide, la
// fonction affiche un message sur la sortie erreur standard et termine le
// programme. Si l'occupation du tableau tombe à 25% après le pop(), le tableau
// est redimensionné par la fonction shrink_stack().
int pop(stack *);
// Ajoute une valeur au sommet de la pile. Si le tableau est plein, il est
// redimensionné au préalable, par la fonction grow_stack.
void push(int, stack *);
#endif // STACK_H_

BIN
tp3/TP3/stack.o Normal file

Binary file not shown.

BIN
tp3/TP3/stackqueue Executable file

Binary file not shown.

68
tp3/TP3/stacktest.c Normal file
View File

@@ -0,0 +1,68 @@
#include "stacktest.h"
#include "alloc.h"
#include "stack.h"
#include "testprint.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
stack *random_stack(int size, int maxval) {
stack* p = create_stack();
for (int i = 0; i < size; i++) {
push(rand() % maxval, p);
}
return p;
}
stack *tower_stack(int n) {
stack* p = create_stack();
for (int i = 0; i < n; i++) {
push(n - i, p);
}
return p;
}
stack *copy_stack(stack *p) {
stack* p_temp = create_stack();
stack* p_out = create_stack();
while (size_stack(p) > 0) {
push(pop(p), p_temp);
}
while (size_stack(p_temp) > 0) {
int val = pop(p_temp);
push(val, p);
push(val, p_out);
}
delete_stack(p_temp);
return p_out;
}
void hanoi(int n) {
if (n <= 0) return;
stack *p1 = tower_stack(n);
stack *p2 = create_stack();
stack *p3 = create_stack();
int max = n;
int *count = 0;
hanoi_rec(p1, p2, p3, p1, p2, p3, n, max, count);
print_stacks(max, 3, p1, p2, p3);
return;
}
void hanoi_rec(stack *p1, stack *p2, stack *p3,
stack *q1, stack *q2, stack *q3,
int n, int max, int *count) {
if (n == 0) {
// print_stacks(max, 3, q1, q2, q3);
return;
};
hanoi_rec(p1, p3, p2, q1, q2, q3, n-1, max, count);
print_stacks(max, 3, q1, q2, q3);
push(pop(p1), p3);
hanoi_rec(p2, p1, p3, q1, q2, q3, n-1, max, count);
return;
}
void bubble_sort_stack(stack *p) {
return;
}

2
tp3/TP3/stacktest.d Normal file
View File

@@ -0,0 +1,2 @@
stacktest.o: stacktest.c stacktest.h stack.h alloc.h error.h testprint.h \
queue.h

104
tp3/TP3/stacktest.h Normal file
View File

@@ -0,0 +1,104 @@
////////////////////////////////
/// Fonctions de test: piles ///
////////////////////////////////
#ifndef STACKTEST_H_
#define STACKTEST_H_
#include "stack.h"
// Crée une pile aléatoire de valeurs entre 0 et maxval de taille size.
// Si size est inférieure ou égal à 0, la pile construite est vide.
stack *random_stack(int size, int maxval);
// Crée la pile suivante:
// 1
// 2
// .
// .
// .
// n-2
// n-1
// n
//*****
//
// Si n est inférieur ou égal à 0, la pile construite est vide.
stack *tower_stack(int n);
// Crée une copie de la pile prise en entrée.
// Cette dernière doit rester inchangée après appel de la fonction.
stack *copy_stack(stack *p);
// Trie la pile par ordre croissant (la plus grande valeur au sommet).
// L'algorithme devra être basé sur le principe du tri à bulles.
// Une seule structure auxiliaire est autorisée: une seconde pile.
// Toute autre structure auxiliaire (comme un tableau) est interdite.
void bubble_sort_stack(stack *p);
// Tours de Hanoi.
//
// Si n > 0, affiche la séquence de mouvements qui résout le problème des tours
// de Hanoi pour n disques. On utilisera la primitive qui sert à afficher une ou
// plusieurs piles.
//
// Par exemple, pour $n = 3$, la fonction dont afficher les informations
// suivantes: Situation initiale:
// 1
// 2
// 3
// ***** ***** *****
//
// Étape 1:
//
// 2
// 3 1
// ***** ***** *****
//
// Étape 2:
//
//
// 3 2 1
// ***** ***** *****
//
// Étape 3:
//
// 1
// 3 2
// ***** ***** *****
//
// Étape 4:
//
// 1
// 2 3
// ***** ***** *****
//
// Étape 5:
//
//
// 1 2 3
// ***** ***** *****
//
// Étape 6:
//
// 2
// 1 3
// ***** ***** *****
//
// Étape 7:
// 1
// 2
// 3
// ***** ***** *****
void hanoi(int n);
// Fonction récursive auxiliaire pour les tours de Hanoi.
// p1, p2, p3 sont les trois piles de départ.
// q1, q2, q3 mémorisent les trois piles de départ et ne changent pas au cours
// des appels. Utilisées pour l'affichage (on affiche q1, puis q2, puis q3).
// n est le nombre de disques à déplacer.
// max est l'espacement horizontal que prend l'affichage (utilisez max=n).
// *count permet de compter les étapes réalisées.
void hanoi_rec(stack *p1, stack *p2, stack *p3, stack *q1, stack *q2, stack *q3,
int n, int max, int *count);
#endif // STACKTEST_H_

BIN
tp3/TP3/stacktest.o Normal file

Binary file not shown.

83
tp3/TP3/testprint.c Normal file
View File

@@ -0,0 +1,83 @@
#include "testprint.h"
void print_stacks(int h, int nb, ...) {
va_list liste;
va_start(liste, nb);
stack **tab;
int i, j, max = 1;
MALLOC(tab, nb);
for (i = 0; i < nb; i++) {
tab[i] = va_arg(liste, stack *);
CHECK_NULL(2, tab[i], "The stack", tab[i]->array,
"The array used to implement the stack");
}
// Récupération de la hauteur maximum parmi les piles.
for (i = 0; i < nb; i++)
if (tab[i]->size_stack > max)
max = tab[i]->size_stack;
for (j = h; j > max; j--) {
PRINT_BLANK;
for (i = 1; i < nb; i++) {
PRINT_BLANK;
PRINT_BLANK;
}
printf("\n");
}
// Affichage des piles.
for (j = max; j > 0; j--) {
if (tab[0]->size_stack < j)
PRINT_BLANK;
else
printf("%" xstr(MAX_SIZE_INT_STACK) "d", tab[0]->array[j - 1]);
for (i = 1; i < nb; i++) {
PRINT_BLANK;
if (tab[i]->size_stack < j)
PRINT_BLANK;
else
printf("%" xstr(MAX_SIZE_INT_STACK) "d", tab[i]->array[j - 1]);
}
printf("\n");
}
PRINT_STARS;
for (i = 1; i < nb; i++) {
PRINT_BLANK;
PRINT_STARS;
}
printf("\n");
free(tab);
va_end(liste);
}
void print_queue(const queue *p) {
printf("File:");
if (isempty_queue(p)) {
printf(" vide\n");
return;
}
int i = p->left;
if (i < p->right)
while (i < p->right) {
printf("%4d", p->array[i]);
i++;
}
else {
while (i < p->size_array) {
printf("%4d", p->array[i]);
i++;
}
i = 0;
while (i < p->right) {
printf("%4d", p->array[i]);
i++;
}
}
printf("\n");
}

1
tp3/TP3/testprint.d Normal file
View File

@@ -0,0 +1 @@
testprint.o: testprint.c testprint.h alloc.h error.h queue.h stack.h

51
tp3/TP3/testprint.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef TESTPRINT_H_
#define TESTPRINT_H_
#include "alloc.h"
#include "queue.h"
#include "stack.h"
// Pour l'affichage des piles.
// Taille maximale d'un entier dans une pile, pour l'affichage.
#define STARS "*******"
#define MAX_SIZE_INT_STACK 7
#define PRINT_STARS \
do { \
printf("%*s", MAX_SIZE_INT_STACK, STARS); \
} while (0)
#define PRINT_BLANK \
do { \
printf("%*s", MAX_SIZE_INT_STACK, ""); \
} while (0)
// Permet l'expansion d'une macro
#define xstr(s) str(s)
// Ex: scanf("%"xstr(DMAX)"s",buffer);
#define str(s) #s
// Fonction d'affichage d'un nombre arbitraire de piles.
//
// Cette fonction est déjà écrite (elle est utile pour afficher les tours de
// Hanoi). Elle utilise un nombre variable de parametres, comme printf.
//
// Utilisation : printstacks(h,nb,p1,p2,p3,p5,...)
//
// h est la hauteur minimale d'affichage (si h est inférieure à la hauteur de
// plus grande pile, il est remplacé par cette hauteur).
//
// nb est le nombre de piles à afficher.
//
// p1,p2,p3,p4,p5,... sont les nbs piles à afficher.
//
// Attention, la fonction est prévue pour afficher des nombres à (au plus)
// MAX_SIZE_INT_STACK chiffres. Pour afficher des piles contenant des nombres à
// plus de 7 chiffres, il faut modifier la valeur de MAX_SIZE_INT_STACK et celle
// de la macro STARS.
void print_stacks(int, int, ...);
// Fonction d'affichage d'une file.
// Cette primitive est déjà écrite. Utilisez-la pour vos tests.
void print_queue(const queue *);
#endif // TESTPRINT_H_

BIN
tp3/TP3/testprint.o Normal file

Binary file not shown.

13
tp3/TP3/tools.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef TOOLS_H_
#define TOOLS_H_
// C2x typeof supported by clang and gcc but not by ccls.
#define SWAP(a, b) \
do { \
__typeof__(a) temp; \
temp = a; \
a = b; \
b = temp; \
} while (0)
#endif // TOOLS_H_