[get_next_line] get_next_line! 어떤 식으로 구현해야할까?

개발하는 곰댕이·2021년 4월 11일
0

42Seoul

목록 보기
13/45

1. 구현방법

일단 구현하는 부분은 보너스를 한다는 가정하에 만들었습니다.
우선 구현 방법에는 static변수의 자료형에따라 두가지로 나뉘는데
하나는 연결리스트를 사용하는 방법이고, 하나는 static char* static_buf[OPEN_MAX]의 형태로 사용하는 방법입니다.
OPEN_MAX는 OPEN_MAX < fd일때 터질거라고 들었기 때문에 우선 저는 연결리스트로 구현을 했습니다.
먼저 연결리스트로 구현하는 방법을 알아보도록 합시다.

1. 연결리스트로 구현하기

1.1 구조체를 만듭시다.

typedef struct		s_gnl_lst
{
    int			index; // fd와 동일한 값을 갖게 됩니다.
    char		*buff; // 남은 문자열을 저장할 버퍼입니다.
    struct s_gnl_lst	*next;
}			t_gnl_lst;

1.2 필요한 변수의 선언을 해 줍니다.

static t_gnl_lst	*head; //헤드노드를 static으로 선언해줍니다.
t_gnl_lst		*lst_buf; // fd에 맞는 노드를 찾아서 이 곳에 넣어줍니다.

1.3 fd에 맞는 노드를 찾습니다.

t_gnl_lst	*find_buff(t_gnl_lst *lst_buff, int fd)
{
	while (lst_buff)
	{
		if (lst_buff->fd == fd)
			break ;
		if (lst_buff->next == NULL)
			if (!(lst_buff->next = new_buff(fd)))
				return (0);
		lst_buff = lst_buff->next;
	}
	return (lst_buff);
}

1.4 이전에 사용하던 buff에 개행이 있는지 찾아줍니다.

int		find_new_line(char **line, t_gnl_lst *lst_buf)
{
	size_t	i;
	size_t	j;
	int		found;

	found = 0;
	i = 0;
	j = 0;
	while (lst_buf->buff[i] != '\0')
	{
		if (lst_buf->buff[i++] == '\n')
		{
			found = 1;
			*line = malloc(i);
			ft_strlcpy(*line, lst_buf->buff, i);
			break ;
		}
	}
	if (found) // 덮어쓰기로 사용된 문자는 날려버렸습니다.
		ft_strlcpy(lst_buf->buff, lst_buf->buff + i,
					ft_strlen(lst_buf->buff) + 1);
	return (found);
}

만약 개행을 찾지 못 했으면 한 줄 더 읽고 계속 반복합니다.

1.5 주의해야할 점

  1. 당연하게도 누수는 나면 안됩니다.
  2. EOF는 개행이 아니기 때문에 개행만 검사한다면 마지막 한 줄을 날려버리게 되기에 한번 더 검사하거나 다른 방식을 사용해 보세요.
  3. EOF를 만나서 해당 노드가 필요 없어지면 꼭free를 해 주세요. free를 한 후 앞, 뒤 노드를 연결해줘야 하는데 구조체에 이전 노드의 주소를 넣어둔다면 좀 더 편합니다.

2. OPEN_MAX로 구현하기

#include <limits.h>에 있는 OPEN_MAX를 이용해서 구현하는 방법입니다.
저는 연결리스트를 이용했기 때문에 상세한 부분은 모르지만 돌아가는 방법은 동일하기에 간단하게 적어보도록 하겠습니다.
사용될 정적 변수는 이렇습니다.

   static char *buff[OPEN_MAX];

2.1 이전에 사용하던 buff에 개행이 있는지 찾아줍니다.

여기서부터는 연결리스트와 차이가 없습니다. 단순히 buff[fd]로 사용하느냐, 노드를 찾아서 사용하느냐의 차이죠.
문자열 buff[fd]에 개행이 있는지 찾아줍니다.
있으면 line에 읽어들인 한 줄의 문자열을 할당한 후 buff안에 있는 문자열을 개행 이후의 문자로 덮어쓰기 해 주고 리턴을 해 줍니다.
없다면 다시 반복해 줍니다.

2.2 주의해야할 점

  1. 당연하게도 누수는 나면 안됩니다.
  2. EOF는 개행이 아니기 때문에 개행만 검사한다면 마지막 한 줄을 날려버리게 되기에 한번 더 검사하거나 다른 방식을 사용해 보세요.
  3. OPEN_MAX는 OPEN_MAX < fd일때 에러처리를 해 주어야 합니다. 그렇지 않으면 큰 값을 넣었을때 터져요..

연결리스트와 OPEN_MAX는 큰 차이는 없습니다.
하지만 연결리스트는 노드와 관련된 함수들을 사용하기에 좀 더 많은 함수를 쓰게 되는데 GNL은 파일 2개만 이용해야 하기 때문에 총 함수 10개로 제한이 돼서 연결리스트를 사용하면 norm에 맞추기 힘들수도 있습니다.
그래서 확실히 OPEN_MAX를 이용하는게 좀 더 간단하고 편하죠.
하지만 연결리스트를 사용하면 OPEN_MAX에서 터질만큼의 크기도 사용이 가능하기에 도전해보면 좋을 것 같습니다.

[get_next_line] get_next_line에 대해 알아보자.
[get_next_line] 파일디스크립터에 대해 알아보자
[get_next_line] 정적변수, static variable에 대해 알아보자
[get_next_line] get_next_line! 어떤 식으로 구현해야할까?

0개의 댓글