개인적으로 Get_next_line의 로직과 알고리즘을 짜는데 매우 어려웠다.
일주일동안 각각의 레퍼런스를 찾으면서 나만의 방법을 생각했지만, Get_next_line의 주제의 개념이 명확하게 정의되지 않은채로 여러 레퍼런스를 통해 아이디어를 얻고자 했더니 오히려 더 헷갈렸다. 먼저 이미 직접 코드를 구현한 libft를 바탕으로, get_next_line을 최대한 생성하고 싶었다. 하지만, 그것은 나의 잘못된 접근 방식이었다.
int get_one_line(int fd, char **line)
{
static char buf[BUFFER_SIZE + 1];
int nbr_read;
int i;
char *end;
nbr_read = read(fd, buf, BUFFER_SIZE);
if (nbr_read <= 0)
return (ERROR);
end = ft_strchr(buf, '\n');
*line = ft_calloc(end - buf + 1, sizeof(char));
if (!*line)
return (ERROR);
i = 0;
while (i < end - buf)
{
(*line)[i] = buf[i];
i++;
}
return (SUCCESS);
}
!!! 여기서, 문제가 발생한다. get_next_line의 문제에서는, 한 라인씩 read()를 사용하여 읽어야 한다고 정의 되어 있다.
==> 여기서 Get_next_line의 문제를 잘못 이해해서, 로직 및 함수를 잘못 설계 했고, 시간을 예상치 못하게 허비하게 되었다.
( +여담이지만, 나와 같은 로직으로, 학교에서 fd 파일의 함수를 모두 읽는 함수를 생성하고, Get_next_line 프로젝트를 pass한 사람이 있었다. 하지만, peer to peer 방식으로 진행되는 evaluation에서 제대로 defense를 하려면, 기 방식은 전적으로 비추천 한다!!!!!)
Calling your function get_next_line in a loop will then allow you to read the text available on a file descriptor one line at a time until the EOF.
(get_next_line subject)
int read_all_line(int fd, char **line)
{
static char *buf;
int read_all;
int i;
if (fd < 0 || BUFFER_SIZE <= 0 || !line)
return (ERROR);
i = 0;
read_all = BUFFER_SIZE;
while (read_all == BUFFER_SIZE)
{
if (i == 0)
buf = malloc(BUFFER_SIZE + 1);
else
buf = ft_realloc(buf, i * BUFFER_SIZE + 1, (i + 1) * BUFFER_SIZE + 1);
if (!buf)
return (ERROR);
read_all = read(fd, &buf[i * BUFFER_SIZE], BUFFER_SIZE);
if (read_all < 0)
return (ERROR);
buf[i * BUFFER_SIZE + read_all] = 0;
i++;
}
*line = buf;
return (SUCCESS);
}
==> 하기 함수 생성시 free를 적용하지 않아 Memory leaks가 발생하였고, 그 외 여러 에러가 발생하여, 나의 로직을 바꾸기로 했다.
int get_next_line(int fd, char **line)
{
static char **buf = NULL;
static int i = 0;
if (!fd || !line)
return (ERROR);
if (!buf) // 1er fois
{
buf = read_all_line(fd);
if (!buf)
return (ERROR);
}
if (buf[i])
*line = buf[i++]; //apres l'initialisation
if (!buf[i])
{
free(buf);
return (END);
}
return (SUCCESS);
}
void ft_memcpy(char *des, char *src, size_t len)
{
size_t i;
i = 0;
while (i < len)
{
des[i] = src[i];
i++;
}
}
void *ft_realloc(void *old_ptr, size_t old_len, size_t new_len)
{
char *new_ptr;
new_ptr = malloc(new_len);
if (!new_ptr)
return (NULL);
if (new_ptr)
ft_memcpy(new_ptr, old_ptr, old_len);
free(old_ptr);
return (new_ptr);
}
//get_next_line_utils : split
int count(char *s, char d)
{
int i;
int c;
i = 0;
c = 0;
while (s[i])
{
if (s[i] == d)
c++;
i++;
}
return (c + 1);
}
int word_len(char *s, char d)
{
int i;
i = 0;
while (s[i] && s[i] != d)
i++;
return (i);
}
char **ft_split(char *s, char d)
{
int word_count;
char **tab;
int w;
int len;
word_count = count(s, d);
tab = malloc(sizeof(char *) * (word_count) + 1);
if (!tab)
return (NULL);
w = 0;
while (w < word_count)
{
len = word_len(s, d);
tab[w] = malloc(sizeof(char) * (len + 1));
ft_memcpy(tab[w], s, len);
tab[w][len] = 0;
s += len + 1;
w++;
}
tab[w] = NULL;
return (tab);
}
Get_next_line 의 로직과 알고리즘을 짜면서 느낀점 :
시간이 더 걸리더라도, subject의 주제와 개념을 제대로 파악하자.