init projet
This commit is contained in:
BIN
tp3/TP3.tgz
Normal file
BIN
tp3/TP3.tgz
Normal file
Binary file not shown.
12
tp3/TP3/.ccls
Normal file
12
tp3/TP3/.ccls
Normal 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
3640
tp3/TP3/.uncrustify
Normal file
File diff suppressed because it is too large
Load Diff
37
tp3/TP3/Makefile
Normal file
37
tp3/TP3/Makefile
Normal 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
19
tp3/TP3/alloc.c
Normal 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
1
tp3/TP3/alloc.d
Normal file
@@ -0,0 +1 @@
|
||||
alloc.o: alloc.c alloc.h error.h
|
||||
178
tp3/TP3/alloc.h
Normal file
178
tp3/TP3/alloc.h
Normal 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
BIN
tp3/TP3/alloc.o
Normal file
Binary file not shown.
58
tp3/TP3/error.h
Normal file
58
tp3/TP3/error.h
Normal 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
128
tp3/TP3/main.c
Normal 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
2
tp3/TP3/main.d
Normal 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
BIN
tp3/TP3/main.o
Normal file
Binary file not shown.
53
tp3/TP3/queue.c
Normal file
53
tp3/TP3/queue.c
Normal 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
1
tp3/TP3/queue.d
Normal file
@@ -0,0 +1 @@
|
||||
queue.o: queue.c queue.h alloc.h error.h
|
||||
45
tp3/TP3/queue.h
Normal file
45
tp3/TP3/queue.h
Normal 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
BIN
tp3/TP3/queue.o
Normal file
Binary file not shown.
21
tp3/TP3/queuetest.c
Normal file
21
tp3/TP3/queuetest.c
Normal 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
1
tp3/TP3/queuetest.d
Normal file
@@ -0,0 +1 @@
|
||||
queuetest.o: queuetest.c queuetest.h queue.h alloc.h error.h
|
||||
36
tp3/TP3/queuetest.h
Normal file
36
tp3/TP3/queuetest.h
Normal 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
BIN
tp3/TP3/queuetest.o
Normal file
Binary file not shown.
80
tp3/TP3/stack.c
Normal file
80
tp3/TP3/stack.c
Normal 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
1
tp3/TP3/stack.d
Normal file
@@ -0,0 +1 @@
|
||||
stack.o: stack.c stack.h alloc.h error.h
|
||||
49
tp3/TP3/stack.h
Normal file
49
tp3/TP3/stack.h
Normal 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
BIN
tp3/TP3/stack.o
Normal file
Binary file not shown.
BIN
tp3/TP3/stackqueue
Executable file
BIN
tp3/TP3/stackqueue
Executable file
Binary file not shown.
68
tp3/TP3/stacktest.c
Normal file
68
tp3/TP3/stacktest.c
Normal 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
2
tp3/TP3/stacktest.d
Normal 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
104
tp3/TP3/stacktest.h
Normal 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
BIN
tp3/TP3/stacktest.o
Normal file
Binary file not shown.
83
tp3/TP3/testprint.c
Normal file
83
tp3/TP3/testprint.c
Normal 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
1
tp3/TP3/testprint.d
Normal 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
51
tp3/TP3/testprint.h
Normal 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
BIN
tp3/TP3/testprint.o
Normal file
Binary file not shown.
13
tp3/TP3/tools.h
Normal file
13
tp3/TP3/tools.h
Normal 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_
|
||||
Reference in New Issue
Block a user