🤪
次の行を読み込む関数を作成する
課題の内容
42の規則上課題のPDFを掲載できないのですが、ざっくりいうと渡したファイルを1行ずつ読み込んでくれる関数です。
for
やswitch
などがコード規約で禁止されているため、一部モダンじゃない書き方をしています。
それ以外で「ここもっとスッキリかけそう」と言う箇所があればお知らせください。
また、使用できる標準関数はread
とmalloc
およびfree
のみです。
ft_
で始まる関数は標準関数を自作したもので、挙動は同じになっているはずです、
ソースコード
get_next_line.h
#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H
# define SUCCESS 1
# define END_OF_FILE 0
# define READ_ERROR -1
# include <unistd.h>
# include <stdlib.h>
int get_next_line(int fd, char **line);
size_t ft_strlen(const char *s);
char *ft_strchr(char *s, int c);
void *ft_memmove(void *dst, const void *src, size_t len);
char *ft_substr(char const *s, unsigned int start, size_t len);
#endif
get_next_line.c
#include "get_next_line.h"
static char *free_return(char *save)
{
free(save);
save = NULL;
return (NULL);
}
static int count_till_endl(char *s)
{
int i;
i = 0;
if (!s)
return (0);
while (s[i] && s[i] != '\n')
i++;
return (i);
}
static char *gnl_strjoin(char const *s1, char const *s2)
{
size_t len1;
size_t len2;
size_t total_len;
char *ret;
if (!s1 && !s2)
return (NULL);
len1 = ft_strlen((char *)s1);
len2 = ft_strlen((char *)s2);
total_len = len1 + len2;
if (!(ret = (char *)malloc((total_len + 1) * sizeof(char))))
return (NULL);
ft_memmove(ret, s1, len1);
ft_memmove(ret + len1, s2, len2);
ret[total_len] = '\0';
free((char *)s1);
return (ret);
}
static char *get_save(char *save)
{
char *ret;
int i;
int j;
i = 0;
j = 0;
if (!save)
return (NULL);
while (save[i] != '\n')
{
if (!save[i])
return (free_return(save));
i++;
}
if (!(ret = malloc(sizeof(char) * ((ft_strlen(save) - i) + 1))))
return (NULL);
i++;
while (save[i])
ret[j++] = save[i++];
ret[j] = '\0';
free(save);
return (ret);
}
int get_next_line(int fd, char **line)
{
int read_res;
char *buf;
static char *save;
read_res = SUCCESS;
if (fd < 0 || !line || BUFFER_SIZE < 1 ||
!(buf = (char *)malloc((size_t)BUFFER_SIZE + 1)))
return (READ_ERROR);
while (!(ft_strchr(save, '\n')) && read_res != 0)
{
if ((read_res = read(fd, buf, BUFFER_SIZE)) == READ_ERROR)
{
free(buf);
return (READ_ERROR);
}
buf[read_res] = '\0';
save = gnl_strjoin(save, buf);
}
free(buf);
*line = ft_substr(save, 0, count_till_endl(save));
save = get_save(save);
return ((read_res == END_OF_FILE) ? END_OF_FILE : SUCCESS);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "get_next_line.h"
/*main.cは提出しないため、printfとか使ってもOKです*/
int main(int argc, char **argv)
{
int fd;
char *line;
if (argc == 1 || argc == 2)
{
fd = (argc == 1) ? 0 : open(argv[1], P_RDONLY);
while (get_next_line(fd, &line) == 1)
{
printf("%s\n", line);
free(line);
}
close(fd);
}
else
return (2);
system("leaks a.out");
return (0);
}
Discussion