[Get_next_line] 알고리즘 - 삽질의 흔적들 .(feat. split)

Cadet_42·2021년 6월 19일
0

Get_next_line

목록 보기
2/3

Get_next_line 로직 및 알고리즘

개인적으로 Get_next_line의 로직과 알고리즘을 짜는데 매우 어려웠다.
일주일동안 각각의 레퍼런스를 찾으면서 나만의 방법을 생각했지만, Get_next_line의 주제의 개념이 명확하게 정의되지 않은채로 여러 레퍼런스를 통해 아이디어를 얻고자 했더니 오히려 더 헷갈렸다. 먼저 이미 직접 코드를 구현한 libft를 바탕으로, get_next_line을 최대한 생성하고 싶었다. 하지만, 그것은 나의 잘못된 접근 방식이었다.

1. get_one_line (로직 연습)

  • 먼저, get_next_line의 주제를 이해하기 위한 기본 작업으로 fd파일의 한줄을 읽는 함수를 생성하였다.
  • 하기 함수 생성시 메모리를 비워주는 free 함수는 아직 만들지 않았다.
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);
}

2. read_all_line : fd 파일의 함수를 모두 읽는 함수 생성 (feat.문제의 시발점)

  • 1번 내용의 로직을 바탕으로 fd 파일의 eof까지 읽는 함수 생성.
  • bytes = 1 < buf 이면, 파일의 끝임을 알도록 설계됨
  • 유의사항: BUFFER_SIZE에 관계없이 fd의 내용을 다 읽어야함.!

!!! 여기서, 문제가 발생한다. 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);
}

3. (잘못된 로직이었지만, 상기 2번의 로직을 바탕으로) split의 개념을 적용하여 get_next_line 함수를 만드려고 하였다.

==> 하기 함수 생성시 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);
}

Get_next_line_utils (그외 사용된 함수들)

  • ft_memcpy: len 바이트 수만큼 src를 des로 복사함
  • ft_realloc : old_ptr을 free해가면서, new_ptr에 동적 메모리 할당 (malloc)을 해줌
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안에 넣어줄 split 함수

  • count : 문자열 s 안에 d로 나눠지는 단어의 수를 구하는 함수
  • word_len : 문자열 s안에 문자 d가 나오기전까지의 단어의 길이를 반환함.
  • split : split함수
//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의 주제와 개념을 제대로 파악하자.

profile
안녕하세요! 개발공부를 하고 있습니다. 감사히 배우겠습니다. ;)

0개의 댓글