Author | Created | Updated |
mcha(Min-jae Cha) | 2022. 01. 13 | 2022. 01. 13 |
Subtitle
Reading a line on a fd is way too tedious
Version
10
Specification
Function name | get_next_line |
Prototype | char *get_next_line(int fd); |
Turn in files | get_next_line.c, get_next_line_utils.c, get_next_line.h |
Parameters | File descriptor to read from |
Return value | Read line: correct behavior
NULL: nothing else to read or an error occurred |
External functs. | read, malloc, free |
Description | Write a function which returns a line read from a file descriptor |
ย Before start
๋ณธ ๊ณผ์ ์ ๋ชฉ์ ์ ๊ณผ์ ๋ช
๊ทธ๋๋ก ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ก๋ถํฐ ์ฝํ์ง, ๊ฐํ์ผ๋ก ๋๋๋ ํ ์ค์ ๋ฐํํ๋ ๊ณผ์ ์
๋๋ค.
์ฌ์ฉ์ ๋๋ ๊ธฐ๊ณ ์ฑ์ ์ ์คํ ํ ํ์ผ์ธ fd๋ฅผ ํ ๋ฒ๋ง ์ฝ์ ์ ์๊ณ ์ฌ๋ฌ ๋ฒ ์ด๋ํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ ํ
์คํธ ํ์ผ์ด ์๋ค๊ณ ์๊ฐ์ ํด ๋ด
์๋ค.
test.txt
Hello
My name is minjae
How are you?
๋ง์ฝ ์ฌ์ฉ์๊ฐ ํ ๋ฒ๋ง fd๋ฅผ ์ด๋ ํ์๋ค๋ฉด ๊ฒฐ๊ณผ ๊ฐ์ "Hello" ์ผ ๊ฒ์ด๊ณ , fd๋ฅผ ๊ณ์ ์ด๋ ํ๋ค๋ฉด ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ๊ฒ์
๋๋ค.
Result example
1๋ฒ์งธ read
"Hello"
2๋ฒ์งธ read
"My name is minjae"
3๋ฒ์งธ read
"How are you?"
4๋ฒ์งธ read
NULL
๊ฒฐ๊ณผ์ ์ผ๋ก ์ด ๊ณผ์ ๋ ๋ ์ด์ ์ฝ์ ๊ฒ์ด ์๊ฑฐ๋ ์ค๋ฅ๊ฐ ๋ฐ์ ํ์ ๊ฒฝ์ฐ NULL์ ๋ฐํํด ์ํ์ด ๋๋จ์ ์๋ฆฐ๋ค.
ย Respected value
1.
String โ ํ ์ค์ด ์ ๋๋ก ์ฝํ์ ๊ฒฝ์ฐ
ํ ์ค์ ๋ง์ง๋ง์ ๊ฐํ ๋ฌธ์('\n')๊ฐ ์๊ฑฐ๋, EOF๋ก ๋ง๋ฌด๋ฆฌ ๋์์ ๋.
์์
2.
NULL โ ์ฝ์ ๋ผ์ธ์ด ๋ ์ด์ ์๊ฑฐ๋ ์๋ฌ๊ฐ ๋ฐ์ํ์ ์
โ ๋น ํ์ผ์ธ ๊ฒฝ์ฐ
์์
โ ์ ํจํ์ง ์์ fd(file descriptor)์ผ ๊ฒฝ์ฐ
a.
์กด์ฌํ์ง ์๋ fd invalid fd
์์
b.
์ด ์ ์๋ ์ต๋ ํ์ผ ์๋ณด๋ค ๋์ fd์ผ ๊ฒฝ์ฐ OPEN_MAX < fd
์์
โ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์๋ฌ
ย How to do this?
์ฃผ์ด์ง ํ์ผ์ ๋ด์ฉ
(start)
Hello('\n')
(end of file)
โ ์ฃผ์ด์ง BUFFER_SIZE๋งํผ ํ์ผ์ ๋ด์ฉ์ ์ฝ๊ธฐ (-D BUFFER_SIZE=<number>)
์์
โ ๋ฐ์์จ ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ฅผ index๋ก ์ฌ์ฉํ์ฌ ๋ฌธ์์ด ์ด์ด ๋ถ์ด๊ธฐ
์์
1.
๋ ์ด์ ์ฝ์ ๋ฌธ์๊ฐ ์์ ๋
โ ์์ ๋ณ์์ธ 'buf'์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ (free) ํ ์ด์ด ๋ถ์ธ ptr ๋ฐํ
ย CODE
ย char *get_next_line(int fd)
๋ณธ ๊ณผ์ ์ ๋์
๋ถ์ด์ ๋ก์ง์ ์ฒ๋ฆฌํ๋ ํต์ฌ ๋ถ๋ถ
๋ฐํ ํํ | char * (๋ฌธ์์ด ๋๋ NULL) |
ํ๋ผ๋ฏธํฐ | fd โ ํ์ผ ๋์คํฌ๋ฆฝํฐ |
char *get_next_line(int fd)
{
// file descriptor์ ๋ฐ๋ผ ๋ฌธ์์ด์ด ๋ค์ด๊ฐ ๊ณต๊ฐ ์์ฑ
static char *ptr[10240];
// ๋ฐํํ ๋ฌธ์์ด์ ๋ด์ ๋ฐฐ์ด
char *line;
// fd, BUFFER_SIZE ์ ํจ์ฑ ๊ฒ์ฌ
if (fd < 0 || BUFFER_SIZE < 1)
return (NULL);
// ํด๋นํ๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ์ ๋ด์ฉ์ ์ด์ด๋ถ์
ptr[fd] = read_line(ptr[fd], fd);
// ptr ๋ ๊ฐ๋
if (!ptr[fd])
return (NULL);
// ๊ฐํ ๋ฌธ์ ๋๋ NULL๋ฌธ์๋ก ์คํ๋ฆฟ
line = do_split(ptr[fd]);
// ์๋ผ์ง ๋ฌธ์์ด ๋ค์ ์ฃผ์๋ก ptr[fd] ์ด๋
ptr[fd] = do_move(ptr[fd]);
// ์๋ผ์ง ๋ฌธ์์ด ๋ฐํ
return (line);
}
C
๋ณต์ฌ
ย static char *read_line(char *ptr, int fd)
fd์ ์๋ ๋ด์ฉ์ ์ฝ์ด์ค๋ ํจ์
๋ฐํ ํํ | char * (๋ฌธ์์ด ๋๋ NULL) |
ํ๋ผ๋ฏธํฐ | char *ptr โ ํฉ์ณ์ง ๋ฌธ์์ด
int fd โ ํ์ผ ๋์คํฌ๋ฆฝํฐ |
static char *read_line(char *ptr, int fd)
{
// BUFFER_SIZE๋งํผ ์ฝ์ ๋ฌธ์(๋ฌธ์์ด)๊ฐ ๋ค์ด๊ฐ ์์ ๋ฐฐ์ด
char *buf;
// ์ฝ์ ๋ฌธ์ ๊ฐ์
int r_size;
// BUFFER_SIZE + 1๋งํผ ๋์ ํ ๋น
buf = (char *)malloc(sizeof(char) * (BUFFER_SIZE + 1));
// NULL ๊ฐ๋
if (!buf)
return (NULL);
// ์ฝ์ ๋ฌธ์ ๊ฐ์๋ฅผ 1๋ก ์ด๊ธฐํ
r_size = 1;
// ์ฝ์ ๋ฌธ์ ๊ฐ์๊ฐ ์๊ณ ๊ฐํ ๋ฌธ์๊ฐ ์์ ๋๊น์ง ๋ฐ๋ณต
while (r_size > 0 && nl_index(ptr, '\n') == -1)
{
// buf์ BUFFER_SIZE๋งํผ ์ฝ์ด์ค๊ธฐ
r_size = read(fd, buf, BUFFER_SIZE);
// ๋ง์ฝ ์ฝ์ ๋ฌธ์๊ฐ ์๋ค๋ฉด break
if (r_size == 0)
break ;
// ๋ง์ฝ invalid fd ๋๋ ์ค๋ฅ ๋ฐ์ ์
if (r_size == -1)
{
// buf ๋ฉ๋ชจ๋ฆฌ ํด์ ํ NULL ๋ฐํ
free(buf);
return (NULL);
}
// ์ฝ์ ๋ฌธ์๊ฐ ์๋ค๋ฉด ptr์ buf join
buf[r_size] = '\0';
ptr = ft_strjoin(ptr, buf);
}
// buf free
free(buf);
// ptr ๋ฐํ
return (ptr);
}
C
๋ณต์ฌ
ย static char *do_split(char *ptr)
๊ฐํ ๋ฌธ์๋ฅผ ํฌํจํ์ฌ ์๋ฅธ ๋ค ์๋ผ์ง ๋ฌธ์์ด์ ๋ฐํ
๋ฐํ ํํ | char * (๋ฌธ์์ด ๋๋ NULL) |
ํ๋ผ๋ฏธํฐ | char *ptr โ ์๋ฅผ ๋์ |
static char *do_split(char *ptr)
{
// ์๋ผ์ง ๋ด์ฉ์ด ๋ค์ด๊ฐ ๋ณ์
char *line;
// ๊ฐํ ๋ฌธ์ ๋๋ NULL๋ฌธ์๊ฐ ์๋ ์์น
int idx;
// line๊ณผ ptr์ ์์น
int i;
idx = 0;
// ptr์ ๊ฐ์ด NULL์ด๋ฉด NULL ๋ฐํ
// ๋ ์ด์ ์ฝ์ ๊ฒ์ด ์๋ค๋ ๊ฒ
if (*ptr == '\0')
return (NULL);
// ptr[idx]๊ฐ NULL, ๊ฐํ๋ฌธ์๊ฐ ์๋ ๋๊น์ง ์ฆ๊ฐ
while (ptr[idx] && ptr[idx] != '\n')
idx++;
// while๋ฌธ ์ข
๋ฃ ํ idx์ ์์น ๋ฌธ์๊ฐ ๊ฐํ๋ฌธ์๋ฉด ํ ๋ฒ ๋ ์ฆ๊ฐ
// -> ๊ฐํ๋ฌธ์๋ฅผ ํฌํจํ์ฌ ๋ฐํํด์ฃผ์ด์ผ ํด์
if (ptr[idx] == '\n')
idx++;
// line ๋ฉ๋ชจ๋ฆฌ ํ ๋น
line = (char *)malloc((idx + 1) * sizeof(char));
if (!line)
return (NULL);
i = 0;
// ptr๋ด์ฉ์ line์ผ๋ก ๋ณต์ฌ
while (i < idx)
{
line[i] = ptr[i];
i++;
}
// ๋ค์ ๋ ๋ฌธ์ ๋ฃ๊ณ ์ข
๋ฃ
line[i] = '\0';
return (line);
}
C
๋ณต์ฌ
ย static char *do_move(char *ptr)
์๋ผ์ง ๋ฌธ์์ด ๋ค๋ก ptr[fd] ์ด๋
๋ฐํ ํํ | char * (๋ฌธ์์ด ๋๋ NULL) |
ํ๋ผ๋ฏธํฐ | char *ptr โ ์ด๋์ด ๋ ๋์ |
static char *do_move(char *ptr)
{
// ์ด๋์ด ๋ ๊ฒฐ๊ณผ
char *str;
// ๊ฐํ ๋ฌธ์ ๋๋ NULL์ด ์๋ ์์น
int idx;
// str๊ณผ ptr์ idx
int i;
idx = 0;
// ๊ฐํ ๋ฌธ์์ NULL๋ฌธ์๊ฐ ์๋ ๋๊น์ง idx ์ฆ๊ฐ
while (ptr[idx] && ptr[idx] != '\n')
idx++;
// ๋ฃจํ ํ ๊ฐํ๋ฌธ์๋ฅผ ๋ง๋๋ฉด ํ ๋ฒ ๋ ์ฆ๊ฐ
if (ptr[idx] == '\n')
idx++;
// NULL ๋ฌธ์๋ฉด ๋ ์ด์ ์ฝ์ ๊ฒ์ด ์๋ค๋ ๋ป์ด๋ฏ๋ก ptr ๋ฉ๋ชจ๋ฆฌ ํด์ ํ ์ข
๋ฃ
if (ptr[idx] == '\0')
{
free(ptr);
return (NULL);
}
// ptr ์ ์ฒด ๊ธธ์ด์์ NULL๋ฌธ์ ๋๋ ๊ฐํ ๋ฌธ์ ๋ค์ ์๋ฆฌ๋ถํฐ ๋ง์ง๋ง๊น์ง์ ๊ธธ์ด๋งํผ ํ ๋น
//
// 0 1 2 3 4 5 6 7 8
// a b c d e \n f g h
//
// 9 - 6 + 1 = 4๋งํผ ํ ๋น
// *str = "fgh"
str = (char *)malloc((ft_strlen(ptr) - idx + 1) * sizeof(char));
if (!str)
return (NULL);
i = 0;
while (ptr[idx])
str[i++] = ptr[idx++];
str[i] = '\0';
// ptr ํด์
free(ptr);
return (str);
}
C
๋ณต์ฌ