Search
πŸ“Ÿ

getnextline

Created
2022/01/13 13:26
Updated
2022/01/13 13:32
Tags
Circle 01
File Descriptor
Buffer
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
볡사