get_next_line

slee2·2022년 5월 23일
0

42Seoul

목록 보기
2/15
post-thumbnail

Reference

이 프로젝트는 업데이트 되며 내용이 변경되었습니다. 이번 문서는 이전 버전의 get_next_line 입니다.

int	get_next_line(int fd, char **line)
  • 매개변수
    • fd 파일 디스크립터
    • line 읽혀들인 값
  • 반환
    • 1 제대로 읽힘
    • 0 EOF 임
    • -1 에러

파일 디스크립터로부터 개행 직전까지의 한 줄을 읽고,
반환하는 함수를 작성하시오.

예를 들어서 설명해보자면,

abcde
abc
a

라는 이중 배열 line이 존재할때, while 반복문 안에 get_next_line 메서드를 이용하게 되면 abcde, abc, a 이렇게 세번의 반복문이 실행되는 것이다.


파일 디스크립터(FD)

파일 디스크립터는 스템으로 부터 할당받은 파일이나 소켓을 대표하는 정수다.

FD는 0부터 2번까지는 고정되어있다.

FD<unistd.h><stdio.h>
0STDIN_FILENOstdin표준입력
1STDOUT_FILENOstdout표준출력
2STDERR_FILENOstderr표준에러출력

이건 우리가 흔히 쓰는 read(0, ...), write(1, ...)와 같은 메서드에서 확인할 수 있다.
fd는 파일이나 소켓을 새로 생성하게 된다면 3부터 하나씩 늘려가게 된다.
하지만, 이 프로젝트는 파일 생성과는 관련이 없으니 위 내용이 사용되지는 않는다.

다만, 이 fd를 구분해줄 필요는 있다.


검토

먼저 고려해야할 사항들을 검토해보자.

line은 아마 이런 형태로 들어올 것이다. 개행이 있다면 \n으로 들어오고, 문자열 마지막 EOF에 도달했을 경우 \0이 붙을 것이다.

위 그림과 같이 get_next_line 메서드를 첫 번째 호출과 두 번째 호출을 다른 fd로 호출할 수도 있다. 그러므로 각 fd로 버퍼를 구분하여 관리해줘야한다.

그리고 read로 읽을 BUFFER_SIZE가 수동으로 결정되므로 한번에 \n까지 읽는다는 보장이 없다.

그러므로 이와같이 개행이 나올때까지 또는 EOF가 나올때까지 반복해줘야한다.

그외에 fd 음수 검사 등 여러가지 고려해야할 사항들이 존재한다.


주요 로직

예외처리나 자잘한 처리들은 생략하고
주요 로직에 대해 알아보자.

while (1)
{
	rd_size = read(fd, buf, BUFFER_SIZE);
	if (rd_size <= 0)
		break ;
	buf[rd_size] = '\0';
	backup[fd] = ft_strjoin(backup[fd], buf);
	j = 0;
	while (backup[fd][j])
	{
		if (backup[fd][j] == '\n')
			return (input_new_line(backup, j, line, fd));
		j++;
	}
}

BUFFER_SIZE : 컴파일할때 이 값을 설정한다. 0~최대값으로 초기에 미리 막아두자.
rd_size : read 메서드로 읽은 버퍼의 길이이다.
backup[fd] : 위에서 고려해야하는 사항 중 하나인 fd 버퍼 관리가 여기서 가능하다. 정적으로 만들기 때문에 값이 유지된다.

while(backup[fd][j]) 를 통해 개행을 확인하고 개행이 있다면, 해당 버퍼를 동적할당하고 *line에 넣은다음 backup에 문자열을 추가해준 후에 1을 반환하게 된다.

EOF에 도달한 경우, if(rd_size <= 0) 부분을 통해 while문을 빠져나오게 된다.

int	take_case_line(char **backup, int fd, char **line)
{
	int		i;

	if (backup[fd])
	{
		i = signal_n(backup[fd]);
		if (i >= 0)
			return (input_new_line(backup, i, line, fd));
		*line = ft_strdup(backup[fd]);
		free(backup[fd]);
		backup[fd] = 0;
		return (0);
	}
	*line = ft_strdup("");
	return (0);
}
  • EOF의 경우일때 개행이 있는지 한번 더 검사한다. 있을 경우, 그 줄을 동적할당 해준 후에 *line에 넣고 1을 반환한다.
  • EOF까지 개행이 아닌 문자열이 존재하면, 해당 문자열을 동적할당 해준 후에 *line에 넣고 0을 반환한다.
  • EOF까지 문자열이 존재하지 않으면, 빈 문자열을 동적할당 해준 후에 *line에 넣고 0을 반환한다.

이와 같은 로직이면 보너스와 함께 통과가 가능하다.
보너스는 하나의 정적 변수와 여러 fd관리가 목표이므로,
backup 정적변수와 backup[fd]로 해결 가능하다.

0개의 댓글