| 프로토타입 | int get_next_line(int fd); |
|---|---|
| 제출할 파일 | get_next_line.c, get_next_line_utils.c, get_next_line.h |
| 매개변수 | 프로그램이 읽을 파일 디스크럽터(The file descriptor to read from) |
| 리턴 값 | Read line: correct behavior NULL: there is nothing else to read, or an error occurred |
| 외부 함수 | read, malloc, free |
| 설명 | 파일 디스크럽터로부터 읽어 온 하나의 라인(newline 없이)을 반환하는 함수 작성 |
- GNL 함수를 loop 안에서 호출하면 fd의 텍스트를 EOF가 올 때 까지 한 번에 한 줄씩 읽을 수 있다.
- GNL 함수를 처음 호출 했을 때 파일을 끝까지 읽었다 하더라도, 두 번째 호출했을 때는 두 번째 line부터 시작해야한다.
- file로부터, redirection으로부터, stdin으로부터 읽었을 때 함수가 제대로 동작해야 한다.
- 이 프로그램은 -D BUFFER_SIZE=xx 플래그를 붙여서 컴파일 해야 한다. 즉, read 함수는 표준입력으로 또는 파일로부터 읽어들이기 위해서 컴파일할 때 정의된 BUFFER_SIZE를 사용해야 한다.
- BUFFER_SIZE가 1일 때도, 9999일 때도, 10000000 (1000만)일 때도 함수가 제대로 동작해야 한다.
표준 입력(Standard Input) : File Descriptor 0
표준 출력(Standard Output) : File Descriptor 1
표준 에러 출력(Standard Error) : File Descriptor 2
size_t read(int fd, void *buf, size_t bytes)
bytes 수 만큼 fd를 읽어 buf에 저장한다.
리턴값 : 읽어 온 바이트 수. 실패 시 -1.
파일을 끝까지 읽었으면, 다음 번에는 더 이상 읽을 바이트가 없기 때문에 0을 반환한다.
외부에서 #define을 정의한다.
이 문제에서 컴파일은 다음과 같이 진행된다.
$ gcc -Wall -Wextra -Werror -D BUFFER_SIZE=42 get_next_line.c get_next_line_utils.c
즉, BUFFER_SIZE를 컴파일할 때 정하게 된다.
#include "get_next_line.h"
char *read_line(int fd, char *buf)
{
char *str;
int rsize;
rsize = 1;
str = (char *)malloc(sizeof(char) * (BUFFER_SIZE + 1));
if (!str)
return (NULL);
while (!ft_strchr(buf, '\n') && rsize != 0)
{
rsize = read(fd, str, BUFFER_SIZE);
if (rsize == -1)
{
free(str);
return (NULL);
}
str[rsize] = '\0';
buf = ft_strjoin(buf, str);
}
free(str);
return (buf);
}
char *get_line(char *buf)
{
char *str;
int j;
int i;
i = 0;
j = 0;
if (!buf[0])
return (NULL);
while (buf[j] && buf[j] != '\n')
j++;
str = (char *)malloc(sizeof(char) * (j + 2));
if (!str)
return (NULL);
while (buf[i] && buf[i] != '\n')
{
str[i] = buf[i];
i++;
}
if (buf[i] == '\n')
{
str[i] = buf[i];
i++;
}
str[i] = '\0';
return (str);
}
char *backup(char *buf)
{
char *str;
int i;
int j;
i = 0;
if (!buf)
return (NULL);
while (buf[i] && buf[i] != '\n')
i++;
if (!buf[i])
{
free(buf);
return (NULL);
}
str = (char *)malloc(sizeof(char) * (ft_strlen(buf) - i + 1));
if (!str)
return (NULL);
i++;
j = 0;
while (buf[i])
str[j++] = buf[i++];
str[j] = '\0';
free(buf);
return (str);
}
char *get_next_line(int fd)
{
char *line;
static char *buf;
if (fd < 0 || BUFFER_SIZE < 1)
return (NULL);
buf = read_line(fd, buf);
if (!buf)
{
free (buf);
return (NULL);
}
line = get_line(buf);
buf = backup(buf);
return (line);
}
#include "get_next_line.h"
char *ft_strchr(const char *s, int c)
{
int i;
i = 0;
if (!s)
return (NULL);
while (s[i])
{
if (s[i] == (char)c)
return ((char *)s + i);
i++;
}
if (c == '\0')
return ((char *)s + i);
return (NULL);
}
size_t ft_strlen(const char *s)
{
size_t i;
i = 0;
if (!s)
return (0);
while (s[i])
i++;
return (i);
}
char *ft_strjoin(char *s1, char *s2)
{
char *res;
int i;
int j;
i = 0;
j = 0;
if (!s1 && !s2)
return (NULL);
res = malloc((sizeof(char) * (ft_strlen(s1) + ft_strlen(s2)) + 1));
if (!res)
return (NULL);
if (s1)
{
while (s1[i])
{
res[i] = s1[i];
i++;
}
}
while (s2[j])
res[i++] = s2[j++];
free (s1);
res[i] = '\0';
return (res);
}
#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H
# include <unistd.h>
# include <stdlib.h>
# ifndef BUFFER_SIZE
# define BUFFER_SIZE 1024
# endif
char *get_next_line(int fd);
char *backup(char *buf);
char *get_line(char *buf);
char *read_line(int fd, char *buf);
size_t ft_strlen(const char *s);
char *ft_strchr(const char *s, int c);
char *ft_strjoin(char *s1, char *s2);
#endif
다음 과제에는 leak 관련된 부분, 변수 이름이 적절하지 못했던 점들 신경쓰기