Commit e7d05a1b authored by Justine Ribas's avatar Justine Ribas
Browse files

Initial commit

parents
This diff is collapsed.
#Fichier Makefile
CC = gcc -Wall
RM = rm -f
srcdir = src/
bindir = bin/
docdir = doc/
savedir = save/
SRC = $(wildcard $(srcdir)*.c)
HEAD = $(wildcard *.h)
OBJ = $(subst $(srcdir), $(bindir), $(SRC:.c=.o))
PROG = TP7
all : $(PROG)
$(PROG) : $(OBJ) #Compilation du programme
$(CC) $^ -o $@
./bin/%.o : ./src/%.c #Compilation des objets
$(CC) -c $^ -o $@
.PHONY : clean #Regle de contournement de fichier appele clean
.PHONY : doc #Regle de contournement de fichier appele doc
clean : #Suppression des objets et le la documentation
$(RM) $(OBJ) sauvegarde.txt
$(shell rm -rf doc/html doc/latex)
doc : #Generation de la documentation Doxygen
$(shell doxygen Doxyfile)
# TD – Tableau dynamique
## Arborescence du projet :
- Dans /bin se trouvent les fichiers objets servant à la compilation
- Dans /doc se trouve la documentation Doxygen
- Dans /src se trouvent tous les fichiers .c et .h contenant le code source
## Compilation :
Pour compiler le programme il faut exécuter la commande "make" à la racine du projet
## Exécution :
Pour exécuter le programme il faut exécuter la commande "./TP7" à la racine du projet
## Documentation :
Pour générer la documentation Doxygen il faut exécuter la commande "make doc" à la racine du projet
La documentation sera ainsi générée dans le dossier /doc et est accessible à partir du fichier /doc/html/index.html par exemple
## Nettoyage du projet :
Pour effacer la documentation générée, les fichiers objets et la dernière sauvegarde il faut exécuter la commande "make clean" à la racine du projet
File added
/*!
* \file main.c
*
* \brief le code de la fonction main
*
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
*
* \date 03 décembre 2021
*/
/*inclusion des entêtes de librairie*/
#include "main.h"
/*code de la fonction main*/
// fonction principale qui affaiche le menu
int main(int argc, char *argv[])
{
//Déclaration des variables
int int_n; // la taille du tableau
int int_choix; //le choix de l'utilisateur dans le menu
int* pint_tab; // le tableau
// On demande la taille du tableau
printf("Entrez la taille du tableau : ");
int_n = saisirEntier();
// On crée le tableau et on l'initialise avec des valeurs aléatoires
pint_tab = creerTabEntier1D(int_n);
initTab(pint_tab, int_n);
// Affichage du tableau et du menu
printf("\nVoici le tableau généré aléatoirement :\n");
afficherTab(pint_tab, int_n);
printf("Comment voulez vous trier ce tableau ?\n\t1- Tri par insertion\n\t2- Tri fusion\n\t3- Tri par dénombrement\n");
// Saisie du choix
int_choix = saisirEntier();
// On effectue l'interraction correspondant au choix
switch (int_choix) {
case 1:
triInsertion(pint_tab, int_n);
break;
case 2:
triFusion(pint_tab, int_n);
break;
case 3:
triDenombrement(pint_tab, int_n);
break;
default :
printf("Choix invalide\n");
break;
}
// On affiche le tableau après le tri
printf("\nTableau après le tri :\n");
afficherTab(pint_tab, int_n);
// On libère la mémoire
free(pint_tab);
// On retourne 0 pour indiquer que le programme s'est bien terminé
return(0);
}
\ No newline at end of file
/*!
* \file main.h
*
* \brief le fichier en-tête de la fonction main
*
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
*
* \date 03 décembre 2021
*/
#ifndef MAIN_H
#define MAIN_H
/*inclusion des entêtes de librairie*/
#include "saisie.h"
#include "tri.h"
/*Déclaration des fonctions*/
/**
* \fn int main(int argc, char *argv[])
* \brief permet d'afficher le menu et d'appeler les fonctions
*
* \param argc nombre d'arguments
* \param argv valeur des arguments
*
* \return 0 si tout s'est bien passé
*
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
* \date 29 novembre 2021
*/
int main(int argc, char *argv[]);
#endif
\ No newline at end of file
/*!
\file saisie.c
\brief le code des fontions de saisie
\author Justine Ribas <ribasjusti@cy-tech.fr>
\version 0.1
\date 29 novembre 2021
*/
/*inclusion des entêtes de librairie*/
#include "saisie.h"
// fonction pour vider le buffer
void viderBuffer(void)
{
char char_saisie; //le caracère courant dans le buffer
scanf("%c", &char_saisie);
while (char_saisie!='\n') {
scanf("%c", &char_saisie);
}
}
// fonction pour saisir un entier
int saisirEntier(void)
{
int int_nbrSaisi; //le nombre qui sera saisie
while (!scanf("%d", &int_nbrSaisi)) {
//on vide le buffer pour eviter une boucle infini
viderBuffer();
printf("Erreur lors de la saisie ! Veuillez saisir un entier :");
}
return(int_nbrSaisi);
}
\ No newline at end of file
/*!
\file saisie.h
\brief le fichier en-tête des fonctions de saisie
\author Justine Ribas <ribasjusti@cy-tech.fr>
\version 0.1
\date 29 novembre 2021
*/
#ifndef SAISIE_H
#define SAISIE_H
/* inclusions des entêtes de librairie */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* Déclaration des fonctions */
/*! \fn void viderBuffer(void)
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
* \date 11 décembre 2019
*
* \brief vide le buffer
*
* \remarks
*/
void viderBuffer(void);
/*! \fn int saisirEntier(void)
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
* \date 11 décembre 2019
*
* \brief vérifie la saisie d'un entier
*
*
* \return l'entier saisi
*
* \remarks
*/
int saisirEntier(void);
#endif
\ No newline at end of file
/*!
* \file tableaux.c
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 02 décembre 2021
*
* \brief code des fonctions relatives aux tableaux
*
*/
/* Inclusion des entêtes de librairies */
#include"tableaux.h"
/* Codes des fonctions */
// Fonction pour créer un tableau à une dimension
int* creerTabEntier1D(int int_n)
{
// Déclaration des variables
int* pint_tab; //tableau d'entiers
// On alloue la mémoire pour le tableau
pint_tab = malloc(int_n*sizeof(int));
// On vérifie que la mémoire a bien été allouée
if(pint_tab == NULL){
fprintf(stderr, "problème d'alloc\n");
exit(1);
}
return(pint_tab);
}
// Fonction pour initialiser un tableau à une dimension avec des valeurs aléatoires
void initTab(int* pint_tab, int int_n)
{
// Déclaration des variables
int int_i; //compteur
srand(time(NULL));
// Initialisation du tableau
for(int_i=0; int_i<int_n; int_i++){
pint_tab[int_i] = rand()%100;
}
}
// Fonction pour afficher un tableau à une dimension
void afficherTab(int* pint_tab, int int_n)
{
// Déclaration des variables
int int_i; //compteur
// Affichage du tableau
for(int_i=0; int_i<int_n; int_i++){
printf("%d ", pint_tab[int_i]);
}
printf("\n\n");
}
// Fonction pour copier un tableau dans un sous tableau
int* copierSousTableau(int* pint_tab, int int_deb, int int_fin)
{
// Déclaration des variables
int* pint_sousTab; // le sous tableau
int int_i; // compteur de boucle
// On crée le sous tableau
pint_sousTab = creerTabEntier1D(int_fin - int_deb + 1);
// On copie les valeurs dans le sous tableau
for (int_i = int_deb; int_i <= int_fin; int_i++)
{
pint_sousTab[int_i - int_deb] = pint_tab[int_i];
}
// On retourne le sous tableau
return(pint_sousTab);
}
// Fonction pour trouver le minimum et le maximum d'un tableau
void minMaxTablau(int* pint_tab, int int_n, int* int_min, int* int_max)
{
// Déclaration des variables
int int_i; // compteur de boucle
// Initialisation des variables
*int_min = pint_tab[0];
*int_max = pint_tab[0];
// On parcourt le tableau
for (int_i = 0; int_i < int_n; int_i++)
{
// On regarde si la valeur est plus petite que la valeur min
if (pint_tab[int_i] < *int_min)
{
*int_min = pint_tab[int_i];
}
// On regarde si la valeur est plus grande que la valeur max
if (pint_tab[int_i] > *int_max)
{
*int_max = pint_tab[int_i];
}
}
}
\ No newline at end of file
/*!
* \file tableaux.h
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 02 décembre 2021
*
* \brief header des fonctions relatives aux tableaux
*
*
*/
#ifndef __TABLEAU_H__
#define __TABLEAU_H__
/* Inclusion des entêtes de librairies */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Déclaration des fonctions */
/**
* \fn int* creerTabEntier1D(int int_n)
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 02 décembre 2021
*
* \brief permet de créer un tableau à une dimension de taille n
*
* \param int_n la taille du tableau
* \return l'adresse de la première case du tableau crée
*
*/
int* creerTabEntier1D(int int_n);
/**
* \fn void initTab(int* pint_tab, int int_n)
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 02 décembre 2021
*
* \brief permet d'initialiser un tableau avec des valeurs aléatoires
*
* \param pint_tab l'adresse de la première case du tableau
* \param int_n la taille du tableau
*
*/
void initTab(int* pint_tab, int int_n);
/**
* \fn void afficherTab(int* pint_tab, int int_n)
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 02 décembre 2021
*
* \brief permet d'afficher le tableau
*
* \param pint_tab l'adresse de la première case du tableau
* \param int_n la taille du tableau
*
*/
void afficherTab(int* pint_tab, int int_n);
/**
* \fn int* copierSousTableau(int* pint_tab, int int_deb, int int_fin)
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 03 décembre 2021
*
* \brief permet de copier notre tableau source dans un sous tableau allant de l'indice int_deb à l'indice int_fin
*
* \param pint_tab le tableau à copier
* \param int_deb l'indice de début du sous tableau
* \param int_fin l'indice de fin du sous tableau
*
* \return le sous tableau
*
*/
int* copierSousTableau(int* pint_tab, int int_deb, int int_fin);
/**
* \fn void minMaxTablau(int* pint_tab, int int_n, int* int_min, int* int_max)
*
* \author Justine Ribas <ribasjusti@eisti.eu>
* \version 0.1
* \date 03 décembre 2021
*
* \brief permet de trouver le minimum et le maximum d'un tableau
*
* \param pint_tab le tableau
* \param int_n la taille du tableau
* \param int_min l'adresse du minimum
* \param int_max l'adresse du maximum
*
*/
void minMaxTablau(int* pint_tab, int int_n, int* int_min, int* int_max);
#endif
\ No newline at end of file
/*!
* \file tri.c
*
* \brief le code des fonctions relatives aux tris
*
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
*
* \date 03 décembre 2021
*/
/* Inclusion des entêtes de librairie*/
#include "tri.h"
/* Code des fonctions */
// Fonction pour trier un tableau avec l'algorithme du tri par insertion
void triInsertion(int* pint_tab, int int_n)
{
// Déclaration des variables
int int_i; // compteur de boucle
int int_j; // compteur de boucle
int int_tmp; // variable temporaire pour les échanges
// Boucle pour trier le tableau
for (int_i = 1; int_i < int_n; int_i++)
{
int_tmp = pint_tab[int_i];
int_j = int_i;
while (int_j > 0 && pint_tab[int_j - 1] > int_tmp)
{
pint_tab[int_j] = pint_tab[int_j - 1];
int_j--;
}
pint_tab[int_j] = int_tmp;
}
}
// Fonction pour fusionner deux sous tableaux triés en un tableau trié
void fusion(int* pint_tab1, int int_n1, int* pint_tab2, int int_n2, int* pint_tab3)
{
// Déclaration des variables
int int_i; // compteur de boucle
int int_j; // compteur de boucle
int int_k; // compteur de boucle
// Initialisation des compteurs
int_j = 0;
int_k = 0;
// Boucle pour fusionner les deux sous tableaux
for (int_i = 0; int_i < int_n1 + int_n2; int_i++)
{
if (int_j < int_n1 && (int_k >= int_n2 || pint_tab1[int_j] <= pint_tab2[int_k]))
{
pint_tab3[int_i] = pint_tab1[int_j];
int_j++;
}
else
{
pint_tab3[int_i] = pint_tab2[int_k];
int_k++;
}
}
}
// Fonction pour trier un tableau avec l'algorithme du tri fuion
void triFusion(int* pint_tab, int int_n)
{
// Déclaration des variables
int int_m; // la moitié du tableau
int* pint_tab1; // le sous tableau 1
int* pint_tab2; // le sous tableau 2
int* pint_tab3; // le tableau trié
int int_i; // compteur de boucle
// Si le tableau est de taille 1, il est déjà trié, sinon on continue de le trier
if(int_n > 1){
// On calcule la moitié du tableau
int_m = int_n / 2;
// On crée les sous tableaux
pint_tab1 = copierSousTableau(pint_tab, 0, int_m - 1);
pint_tab2 = copierSousTableau(pint_tab, int_m, int_n - 1);
// On trie les sous tableaux
triFusion(pint_tab1, int_m);
triFusion(pint_tab2, int_n - int_m);
// On fusionne les sous tableaux
pint_tab3 = creerTabEntier1D(int_n);
fusion(pint_tab1, int_m, pint_tab2, int_n - int_m, pint_tab3);
// On copie le tableau trié dans le tableau initial
for (int_i = 0; int_i < int_n; int_i++)
{
pint_tab[int_i] = pint_tab3[int_i];
}
// On libère la mémoire
free(pint_tab1);
free(pint_tab2);
free(pint_tab3);
}
}
// Fonction qui permet de créer l'historigramme des valeurs du tableau à trier
void histogramme(int* pint_tab, int int_n, int* pint_hist, int int_nH, int int_min)
{
// Déclaration des variables
int int_i; // compteur de boucle
// Initialisation de l'historigramme
for (int_i = 0; int_i < int_nH; int_i++){
pint_hist[int_i] = 0;
}
// Construction de l'historigramme avec la fréquence d'apparition des valeurs dans le tableau
for(int_i = 0; int_i < int_n; int_i++){
pint_hist[pint_tab[int_i] - int_min] ++;
}
}
// Fonction qui permer de trier un tableau avec l'algorithme du tri par dénombrement
void triDenombrement(int* pint_tab, int int_n)
{
// Déclaration des variables
int int_min; // la valeur minimale du tableau
int int_max; // la valeur maximale du tableau
int* pint_hist; // l'historigramme du tableau
int int_i; // compteur de boucle
int int_j; // compteur de boucle
// Initialisation des variables
int_i = 0;
int_j = 0;
// On cherche le min et le max du tableau
minMaxTablau(pint_tab, int_n, &int_min, &int_max);
// On crée l'historigramme
pint_hist = creerTabEntier1D(int_max - int_min + 1);
histogramme(pint_tab, int_n, pint_hist, int_max - int_min + 1, int_min);
// On recompose le tableau en parcourant l'historigramme
while(int_i < int_n){
if(pint_hist[int_j] > 0 ){
pint_tab[int_i] = int_j;
pint_hist[int_j]--;
int_i++;
} else{
int_j++;
}
}
// On libère la mémoire
free(pint_hist);
}
/*!
* \file tri.h
*
* \brief le header des fonctions relatives aux tris
*
* \author Justine Ribas <ribasjusti@cy-tech.fr>
* \version 0.1
*
* \date 03 décembre 2021