TP1 - Correction
ppompeani_chain.c
#include <stdio.h>
#include <stdlib.h>
struct chain {
int value;
struct chain *next;
};
typedef struct chain chain_t;
chain_t *chain_new(int value, chain_t *next) {
chain_t *ret = (chain_t *)malloc(sizeof(chain_t));
ret->value = value;
ret->next = next;
return ret;
}
chain_t *chain_insert(chain_t *list, int value) {
return chain_new(value, list);
}
// Les fonctions suivantes sont écrites en récursif
// Et en itératif avec `_iterate`
chain_t *chain_append(chain_t *list, int value) {
// Le cas particulier est toujours quand la liste vaut NULL :
// Ça veut dire qu'on est au bout de la liste chaînée.
if (list == NULL) {
return chain_new(value, NULL);
}
// On met à jour le next de notre structure.
// Ce sera une opération inutile en général,
// à part quand on est le dernier maillon de la chaine
list->next = chain_append(list->next, value);
return list;
}
chain_t *chain_append_iterate(chain_t *list, int value) {
// On crée un nouveau bloc
chain_t *new_item = chain_new(value, NULL);
if (list == NULL) {
return new_item;
}
// À la fin du while,
// iter pointe vers le dernier bloc de la chaine
chain_t *iter = list;
while (iter->next != NULL) {
iter = iter->next;
}
iter->next = new_item;
return list;
}
chain_t *chain_find(chain_t *list, int value) {
if (list == NULL) {
return NULL;
}
if (list->value == value) {
return list;
}
return chain_find(list->next, value);
}
chain_t *chain_find_iterate(chain_t *list, int value) {
chain_t *iter = list;
while (iter != NULL) {
if (iter->value == value) {
return iter;
}
iter = iter->next;
}
return NULL;
}
void chain_free(chain_t *list) {
if (list != NULL) {
chain_free(list->next);
free(list);
}
}
void chain_free_iterate(chain_t *list) {
chain_t *iter = list;
while (iter != NULL) {
// On conserve d'abord un pointeur vers l'élément suivant
chain_t *next = iter->next;
// On peut maintenant libérer l'élément actuel
free(iter);
// On met à jour notre itérateur vers l'élément suivant
iter = next;
}
}
chain_t *chain_copy(chain_t *list) {
if (list == NULL) {
return NULL;
}
return chain_new(list->value, chain_copy(list->next));
}
chain_t *chain_copy_iterate(chain_t *list) {
if (list == NULL) {
return NULL;
}
// Itérateur sur la liste originale
chain_t *iter = list->next;
// Pointeur sur le premier élément de la nouvelle liste
chain_t *new_list = chain_new(list->value, NULL);
// Itérateur sur la nouvelle liste
chain_t *iter_copy = new_list;
while (iter != NULL) {
// On crée un nouveau bloc
chain_t *new_block = chain_new(iter->value, NULL);
// On l'ajoute à la suite de notre nouvelle liste
iter_copy->next = new_block;
// On fait pointer notre itérateur sur le nouvel élément
iter_copy = new_block;
// On passe à l'élément suivant de la liste originale
iter = iter->next;
}
// On retourne le pointeur sur le premier élément
return new_list;
}
void chain_print(chain_t *list) {
if (list != NULL) {
// Sur le dernier élément, on affiche un retour à la ligne
if (list->next == NULL) {
printf("%d\n", list->value);
// Sinon on affiche une virgule
// et on rappelle la fonction sur l'élément suivant
} else {
printf("%d, ", list->value);
chain_print(list->next);
}
}
}
void chain_print_iterate(chain_t *list) {
chain_t *iter = list;
// Tant qu'on est pas sur le dernier élément,
// on affiche une virgule
while (iter->next != NULL) {
printf("%d, ", iter->value);
iter = iter->next;
}
// Sur le dernier élément, on affiche un retour à la ligne
// On teste si l'élément n'est pas NULL,
// pour le cas d'une liste vide
if (iter != NULL) {
printf("%d\n", iter->value);
}
}
int main(int argc, char **argv) {
chain_t *my_list =
chain_new(1,
chain_new(2,
chain_new(3,
chain_new(4, NULL)
)
)
);
chain_print(my_list);
chain_t *new_list = chain_copy(my_list);
chain_free(my_list);
chain_print(new_list);
chain_t *list_from_3 = chain_find(new_list, 3);
chain_print(list_from_3);
list_from_3 = chain_append(list_from_3, 5);
chain_print(new_list);
return EXIT_SUCCESS;
}
ppompeani_grep.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// file ne doit pas être NULL
// le char* retourné doit être libéré
// retourne NULL quand EOF est atteint
char *readline(FILE *file) {
char *buffer = NULL;
int size = 0;
char c = fgetc(file);
while (c != EOF && c != '\n') {
size += 1;
buffer = (char *)realloc(buffer, size * sizeof(char));
buffer[size - 1] = c;
c = fgetc(file);
}
if (c == EOF && size == 0) {
return NULL;
}
buffer = (char *)realloc(buffer, size + 1 * sizeof(char));
buffer[size] = '\0';
return buffer;
}
// file ne doit pas être NULL
// needle ne doit pas être NULL
void grep(FILE *file, char *needle) {
char *line;
line = readline(file);
while (line != NULL) {
// man 3 strstr
if (strstr(line, needle) != NULL) {
printf("%s\n", line);
}
free(line);
line = readline(file);
}
}
// argv[1] : le texte qu'on cherche
// argv[2] : le fichier à ouvrir
int main(int argc, char **argv) {
if (argc != 3) {
printf("Je veux 2 arguments, pas %d.\n", argc - 1);
return EXIT_FAILURE;
}
FILE *file = fopen(argv[2], "r");
if (file == NULL) {
printf("Erreur à l'ouverture du fichier\n");
return EXIT_FAILURE;
}
grep(file, argv[1]);
fclose(file);
return EXIT_SUCCESS;
}