이 프로젝트는 업데이트 되며 내용이 변경되었습니다. 이번 문서는 이전 버전의
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는 0부터 2번까지는 고정되어있다.
FD | <unistd.h> | <stdio.h> | 뜻 |
---|---|---|---|
0 | STDIN_FILENO | stdin | 표준입력 |
1 | STDOUT_FILENO | stdout | 표준출력 |
2 | STDERR_FILENO | stderr | 표준에러출력 |
이건 우리가 흔히 쓰는 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]
로 해결 가능하다.