getnextline

This commit is contained in:
Ladebeze66 2023-12-12 17:46:17 +01:00
commit d901ad9116
7 changed files with 570 additions and 0 deletions

205
fr.subject.pdf Normal file
View File

@ -0,0 +1,205 @@
Get Next Line
Parce que lire depuis un fd, cest pas passionnant
Résumé:
Ce projet a pour but de vous faire développer une fonction qui renvoie une ligne
lue depuis un descripteur de fichier.
Version: 12
Table des matières
I Objectifs 2
II Règles communes 3
III Partie obligatoire 4
IV Partie Bonus 6
V Rendu et peer-evaluation 7
1
Chapitre I
Objectifs
Ce projet va non seulement vous permettre dajouter une fonction très pratique à
votre collection, mais également daborder un nouvel élément surprenant de la program-
mation en C : les variables statiques.
2
Chapitre II
Règles communes
• Votre projet doit être écrit en C.
• Votre projet doit être codé à la Norme. Si vous avez des fichiers ou fonctions bonus,
celles-ci seront inclues dans la vérification de la norme et vous aurez 0 au projet
en cas de faute de norme.
• Vos fonctions ne doivent pas sarrêter de manière inattendue (segmentation fault,
bus error, double free, etc) mis à part dans le cas dun comportement indéfini. Si
cela arrive, votre projet sera considéré non fonctionnel et vous aurez 0 au projet.
• Toute mémoire allouée sur la heap doit être libéré lorsque cest nécessaire. Aucun
leak ne sera toléré.
• Si le projet le demande, vous devez rendre un Makefile qui compilera vos sources
pour créer la sortie demandée, en utilisant les flags -Wall, -Wextra et -Werror.
Votre Makefile ne doit pas relink.
• Si le projet demande un Makefile, votre Makefile doit au minimum contenir les
règles $(NAME), all, clean, fclean et re.
• Pour rendre des bonus, vous devez inclure une règle bonus à votre Makefile qui
ajoutera les divers headers, librairies ou fonctions qui ne sont pas autorisées dans
la partie principale du projet. Les bonus doivent être dans un fichier différent :
_bonus.{c/h}. Lévaluation de la partie obligatoire et de la partie bonus sont
faites séparément.
• Si le projet autorise votre libft, vous devez copier ses sources et son Makefile
associé dans un dossier libft contenu à la racine. Le Makefile de votre projet doit
compiler la librairie à laide de son Makefile, puis compiler le projet.
• Nous vous recommandons de créer des programmes de test pour votre projet, bien
que ce travail ne sera pas rendu ni noté. Cela vous donnera une chance de
tester facilement votre travail ainsi que celui de vos pairs.
• Vous devez rendre votre travail sur le git qui vous est assigné. Seul le travail déposé
sur git sera évalué. Si Deepthought doit corriger votre travail, cela sera fait à la fin
des peer-evaluations. Si une erreur se produit pendant lévaluation Deepthought,
celle-ci sarrête.
3
Chapitre III
Partie obligatoire
Function name get_next_line
Prototype char *get_next_line(int fd);
Fichiers de rendu get_next_line.h, get_next_line.c,
get_next_line_utils.c
Paramètres fd : le descripteur de fichier depuis lequel lire
Valeur de retour Le contenu de la ligne lue : comportement correct
NULL : rien dautre à lire ou une erreur sest
Fonctions ex- produite
read, malloc, free
ternes autorisées
Écrire une fonction qui retourne une ligne lue
Description depuis un descripteur de fichier
• Des appels successifs à votre fonction get_next_line() doivent vous permettre de
lire lintégralité du fichier texte référencé par le descripteur de fichier, une ligne
à la fois.
• Votre fonction doit retourner la ligne qui vient dêtre lue.
Sil ny a plus rien à lire, ou en cas derreur, elle doit retourner NULL.
• Assurez-vous que votre fonction se comporte correctement quelle lise un fichier
ou quelle lise sur lentrée standard.
• Important : Vous devez toujours retourner la ligne qui a été lue suivie du \n la
terminant, sauf dans le cas où vous avez atteint la fin du fichier et que ce dernier
ne se termine pas par un \n.
• Le fichier den-tête get_next_line.h doit contenir au minimum le prototype de
la fonction.
• Le fichier get_next_line_utils.c vous servira à ajouter des fonctions supplé-
mentaires nécessaires à la réalisation de votre get_next_line().
Savoir ce quest une variable statique est un bon point de départ.
4
Get Next Line Parce que lire depuis un fd, cest pas passionnant
• Votre programme doit compiler avec loption : -D BUFFER_SIZE=n
Cette macro définie à linvocation du compilateur servira à spécifier la taille du
buffer lors de vos appels à read() dans votre fonction get_next_line().
Cette valeur sera modifiée lors de la peer-evaluation et par la Moulinette dans le
but de tester votre rendu.
We must be able to compile this project with and without the -D
BUFFER_SIZE flag in addition to the usual flags. You can choose the
default value of your choice.
• Votre programme sera donc compilé de la manière suivante (exemple ci-dessous
avec une taille de buffer de 42) :
cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 <files>.c
• Nous considérons que get_next_line() a un comportement indeterminé si, entre
deux appels, le fichier pointé par le descripteur de fichier a été modifié, alors que
le premier fichier na pas été lu en entier.
• Nous considérons aussi que get_next_line() a un comportement indeterminé en
cas de lecture dun fichier binaire. Cependant, si vous le souhaitez, vous pouvez
rendre ce comportement cohérent.
Votre fonction marche-t-elle encore si la valeur de BUFFER_SIZE est
de 9999? Ou de 1 ? Ou encore de 10 000 000 ? Savez-vous pourquoi ?
Votre programme doit lire le moins possible à chaque appel à
get_next_line(). Si vous rencontrez une nouvelle ligne, vous devez
retourner la ligne précédente venant dêtre lue.
Ne lisez pas lintégralité du fichier pour ensuite traiter chaque
ligne.
Ce qui nest pas autorisé
• La libft nest pas autorisée pour ce projet.
• La fonction lseek() est interdite.
• Les variables globales sont interdites.
5
Chapitre IV
Partie Bonus
Du fait de sa simplicité, le projet get_next_line laisse peu de place aux bonus, mais
nous sommes sûrs que vous avez beaucoup dimagination. Si vous avez réussi la partie
obligatoire, alors nhésitez pas à faire les bonus pour aller plus loin.
Voici les bonus à réaliser :
• Faites get_next_line() avec une seule variable statique.
• Complétez get_next_line() en lui permettant de gérer plusieurs fd.
Par exemple, si les fd 3, 4 et 5 sont accessibles en lecture, alors il est possible de
les lire chacun leur tour sans jamais perdre les contenus lus sur chacun des fd, et
sans retourner la mauvaise ligne.
Vous devriez pouvoir appeler get_next_line() une fois avec le fd 3, puis le 4, le
5, puis à nouveau le 3, à nouveau le 4, etc.
Ajoutez le suffixe _bonus.[c\h] aux fichiers de cette partie.
Ainsi, en plus des 3 fichiers de la partie obligatoire, vous rendrez les 3 fichiers suivants :
• get_next_line_bonus.c
• get_next_line_bonus.h
• get_next_line_utils_bonus.c
Les bonus ne seront évalués que si la partie obligatoire est
PARFAITE. Par parfaite, nous entendons complète et sans aucun
dysfonctionnement. Si vous navez pas réussi TOUS les points de la
partie obligatoire, votre partie bonus ne sera pas prise en compte.
6
Chapitre V
Rendu et peer-evaluation
Rendez votre travail sur votre dépot Git comme dhabitude. Seul le travail présent
sur votre dépot sera évalué en soutenance. Vérifiez bien les noms de vos dossiers et de
vos fichiers afin que ces derniers soient conformes aux demandes du sujet.
Pour vos tests, gardez à lesprit que :
1) Le buffer et la ligne peuvent être de tailles très différentes.
2) Un descripteur de fichier ne pointe pas seulement sur de simples
fichiers.
Soyez malins et vérifiez votre travail avec vos pairs. Préparez un
large éventail de tests pour votre évaluation.
Une fois ce projet validé, nhésitez pas à ajouter votre get_next_line() à votre
libft.
/=∂/\/\[](_)§ /\/\@|V †|-|@¯|¯ /-/!570®1<|-\£1_`/ ¢@/\/\ε vv!7}{ ???
7

127
get_next_line.c Executable file
View File

@ -0,0 +1,127 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/12 15:39:29 by fgras-ca #+# #+# */
/* Updated: 2023/04/12 17:40:44 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line.h"
char *rec_line_before_nl(const char *s)
{
char *res;
int i;
i = 0;
while (s[i] && s[i] != '\n')
i++;
if (s[i] && s[i] == '\n')
i++;
res = ft_calloc_gnl(i + 1, sizeof(char));
if (!res)
return (NULL);
i = 0;
while (s[i] && s[i] != '\n')
{
res[i] = s[i];
i++;
}
if (s[i] == '\n')
{
res[i] = s[i];
i++;
}
return (res);
}
char *rec_after_nl(const char *s)
{
char *res;
int i;
int j;
j = 0;
while (s && s[j])
j++;
i = 0;
while (s[i] && s[i] != '\n')
i++;
if (s[i] && s[i] == '\n')
i++;
res = ft_calloc_gnl((j - i) + 1, sizeof(char));
if (!res)
return (NULL);
j = 0;
while (s[i + j])
{
res[j] = s[i + j];
j++;
}
return (res);
}
void ft_read_line(int fd, char **keep, char **tmp)
{
char *buf;
int byte_read;
buf = malloc(sizeof(char) * (BUFFER_SIZE + 1));
if (!buf)
return ;
byte_read = 1;
while (byte_read > 0)
{
byte_read = read(fd, buf, BUFFER_SIZE);
if (byte_read == -1)
{
ft_free(&buf, keep, tmp);
return ;
}
buf[byte_read] = '\0';
*tmp = ft_strdup(*keep);
ft_free(keep, 0, 0);
*keep = ft_strjoin_gnl(*tmp, buf);
ft_free(tmp, 0, 0);
if (find_newline(*keep))
break ;
}
ft_free(&buf, 0, 0);
}
char *ft_gnl_recal(char **keep, char **tmp)
{
char *line;
*tmp = ft_strdup(*keep);
ft_free(keep, 0, 0);
*keep = rec_after_nl(*tmp);
line = rec_line_before_nl(*tmp);
ft_free(tmp, 0, 0);
return (line);
}
char *get_next_line(int fd)
{
static char *keep = NULL;
char *tmp;
char *line;
if (fd < 0 || BUFFER_SIZE <= 0)
return (NULL);
line = NULL;
tmp = NULL;
ft_read_line(fd, &keep, &tmp);
if (keep != NULL && *keep != '\0')
line = ft_gnl_recal(&keep, &tmp);
if (!line || *line == '\0')
{
ft_free(&keep, &line, &tmp);
return (NULL);
}
return (line);
}

43
get_next_line.h Executable file
View File

@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/12 17:41:38 by fgras-ca #+# #+# */
/* Updated: 2023/04/12 17:45:17 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H
# include <fcntl.h>
# include <stddef.h>
# include <unistd.h>
# include <stdlib.h>
# include <stdio.h>
# ifndef BUFFER_SIZE
# define BUFFER_SIZE BUFSIZ
# endif
# if BUFFER_SIZE > 9223372036854775806
# undef BUFFER_SIZE
# define BUFFER_SIZE 0
# endif
char *get_next_line(int fd);
void ft_read_line(int fd, char **keep, char **tmp);
char *ft_gnl_recal(char **keep, char **tmp);
char *rec_line_before_nl(const char *s);
char *rec_after_nl(const char *s);
int find_newline(const char *s);
char *ft_strdup(const char *s1);
char *ft_strjoin_gnl(const char *s1, const char *s2);
void *ft_calloc_gnl(size_t count, size_t size);
void ft_free(char **str, char **str2, char **str3);
#endif

127
get_next_line_bonus.c Executable file
View File

@ -0,0 +1,127 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/12 18:02:03 by fgras-ca #+# #+# */
/* Updated: 2023/04/12 18:08:04 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line_bonus.h"
char *rec_line_before_nl(const char *s)
{
char *res;
int i;
i = 0;
while (s[i] && s[i] != '\n')
i++;
if (s[i] && s[i] == '\n')
i++;
res = ft_calloc_gnl(i + 1, sizeof(char));
if (!res)
return (NULL);
i = 0;
while (s[i] && s[i] != '\n')
{
res[i] = s[i];
i++;
}
if (s[i] == '\n')
{
res[i] = s[i];
i++;
}
return (res);
}
char *rec_after_nl(const char *s)
{
char *res;
int i;
int j;
j = 0;
while (s && s[j])
j++;
i = 0;
while (s[i] && s[i] != '\n')
i++;
if (s[i] && s[i] == '\n')
i++;
res = ft_calloc_gnl((j - i) + 1, sizeof(char));
if (!res)
return (NULL);
j = 0;
while (s[i + j])
{
res[j] = s[i + j];
j++;
}
return (res);
}
void ft_read_line(int fd, char **keep, char **tmp)
{
char *buf;
int byte_read;
buf = malloc(sizeof(char) * (BUFFER_SIZE + 1));
if (!buf)
return ;
byte_read = 1;
while (byte_read > 0)
{
byte_read = read(fd, buf, BUFFER_SIZE);
if (byte_read == -1)
{
ft_free(&buf, keep, tmp);
return ;
}
buf[byte_read] = '\0';
*tmp = ft_strdup(*keep);
ft_free(keep, 0, 0);
*keep = ft_strjoin_gnl(*tmp, buf);
ft_free(tmp, 0, 0);
if (find_newline(*keep))
break ;
}
ft_free(&buf, 0, 0);
}
char *ft_gnl_recal(char **keep, char **tmp)
{
char *line;
*tmp = ft_strdup(*keep);
ft_free(keep, 0, 0);
*keep = rec_after_nl(*tmp);
line = rec_line_before_nl(*tmp);
ft_free(tmp, 0, 0);
return (line);
}
char *get_next_line(int fd)
{
static char *keep[1024];
char *tmp;
char *line;
if (fd < 0 || fd >= 1024 || BUFFER_SIZE <= 0)
return (NULL);
line = NULL;
tmp = NULL;
ft_read_line(fd, &keep[fd], &tmp);
if (keep[fd] != NULL && *keep[fd] != '\0')
line = ft_gnl_recal(&keep[fd], &tmp);
if (!line || *line == '\0')
{
ft_free(&keep[fd], &line, &tmp);
return (NULL);
}
return (line);
}

43
get_next_line_bonus.h Executable file
View File

@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_bonus.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/12 18:05:29 by fgras-ca #+# #+# */
/* Updated: 2023/04/12 18:05:45 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef GET_NEXT_LINE_BONUS_H
# define GET_NEXT_LINE_BONUS_H
# include <fcntl.h>
# include <stddef.h>
# include <unistd.h>
# include <stdlib.h>
# include <stdio.h>
# ifndef BUFFER_SIZE
# define BUFFER_SIZE BUFSIZ
# endif
# if BUFFER_SIZE > 9223372036854775806
# undef BUFFER_SIZE
# define BUFFER_SIZE 0
# endif
char *get_next_line(int fd);
void ft_read_line(int fd, char **keep, char **tmp);
char *ft_gnl_recal(char **keep, char **tmp);
char *rec_line_before_nl(const char *s);
char *rec_after_nl(const char *s);
int find_newline(const char *s);
char *ft_strdup(const char *s1);
char *ft_strjoin_gnl(const char *s1, const char *s2);
void *ft_calloc_gnl(size_t count, size_t size);
void ft_free(char **str, char **str2, char **str3);
#endif

115
get_next_line_utils.c Executable file
View File

@ -0,0 +1,115 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/12 17:03:41 by fgras-ca #+# #+# */
/* Updated: 2023/04/12 17:47:26 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line.h"
int find_newline(const char *s)
{
int i;
i = 0;
while (s[i])
{
if (s[i] == '\n')
return (1);
i++;
}
return (0);
}
char *ft_strjoin_gnl(char const *s1, char const *s2)
{
int i;
int len;
char *new_s;
len = 0;
if (!s1 && !s2)
return (NULL);
while (s1 && s1[len])
len++;
i = 0;
while (s2 && s2[i])
i++;
new_s = ft_calloc_gnl(len + i + 1, sizeof(char));
if (!new_s)
return (NULL);
len = -1;
while (s1 && s1[++len])
new_s[len] = s1[len];
i = -1;
while (s2 && s2[++i])
new_s[len + i] = s2[i];
return (new_s);
}
char *ft_strdup(const char *s1)
{
char *s2;
int i;
if (!s1)
return (ft_strdup("\0"));
i = 0;
while (s1[i])
i++;
s2 = ft_calloc_gnl(i + 1, sizeof(char));
if (!s2)
return (NULL);
i = 0;
while (s1[i])
{
s2[i] = s1[i];
i++;
}
return (s2);
}
void *ft_calloc_gnl(size_t count, size_t size)
{
void *r;
unsigned char *p;
size_t total;
size_t i;
total = count * size;
r = malloc(total);
if (!r)
return (NULL);
p = (unsigned char *)r;
i = 0;
while (i < total)
{
p[i] = '\0';
i++;
}
return (r);
}
void ft_free(char **str, char **str2, char **str3)
{
if (str && *str)
{
free(*str);
*str = NULL;
}
if (str2 && *str2)
{
free(*str2);
*str2 = NULL;
}
if (str3 && *str3)
{
free(*str3);
*str3 = NULL;
}
}

115
get_next_line_utils_bonus.c Executable file
View File

@ -0,0 +1,115 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_utils_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/12 18:04:48 by fgras-ca #+# #+# */
/* Updated: 2023/04/12 18:05:03 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line_bonus.h"
int find_newline(const char *s)
{
int i;
i = 0;
while (s[i])
{
if (s[i] == '\n')
return (1);
i++;
}
return (0);
}
char *ft_strjoin_gnl(char const *s1, char const *s2)
{
int i;
int len;
char *new_s;
len = 0;
if (!s1 && !s2)
return (NULL);
while (s1 && s1[len])
len++;
i = 0;
while (s2 && s2[i])
i++;
new_s = ft_calloc_gnl(len + i + 1, sizeof(char));
if (!new_s)
return (NULL);
len = -1;
while (s1 && s1[++len])
new_s[len] = s1[len];
i = -1;
while (s2 && s2[++i])
new_s[len + i] = s2[i];
return (new_s);
}
char *ft_strdup(const char *s1)
{
char *s2;
int i;
if (!s1)
return (ft_strdup("\0"));
i = 0;
while (s1[i])
i++;
s2 = ft_calloc_gnl(i + 1, sizeof(char));
if (!s2)
return (NULL);
i = 0;
while (s1[i])
{
s2[i] = s1[i];
i++;
}
return (s2);
}
void *ft_calloc_gnl(size_t count, size_t size)
{
void *r;
unsigned char *p;
size_t total;
size_t i;
total = count * size;
r = malloc(total);
if (!r)
return (NULL);
p = (unsigned char *)r;
i = 0;
while (i < total)
{
p[i] = '\0';
i++;
}
return (r);
}
void ft_free(char **str, char **str2, char **str3)
{
if (str && *str)
{
free(*str);
*str = NULL;
}
if (str2 && *str2)
{
free(*str2);
*str2 = NULL;
}
if (str3 && *str3)
{
free(*str3);
*str3 = NULL;
}
}