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λ₯Ό ν λ²λ§ μ½μ μ μκ³ μ¬λ¬ λ² μ΄λν μ μμ΅λλ€.
About fd(File Descriptor)
μλ₯Ό λ€μ΄ μλμ κ°μ ν
μ€νΈ νμΌμ΄ μλ€κ³ μκ°μ ν΄ λ΄
μλ€.
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λ‘ μ¬μ©νμ¬ λ¬Έμμ΄ μ΄μ΄ λΆμ΄κΈ°
μμ
Β BREAK POINT
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
볡μ¬