--- Category : get_next_line Id : 4 Title : "get_next_line : 구현" Description : "get_next_line을 실제로 만들어 보자" Date : 2020, 10, 20 (Tue) Auther : seolim pre : 3 next : 0 tags : get_next_line --- # 3 get_next_line : EOF > Link [link not yet]() > Caution 본 문서를 포함한 블로그의 모든 내용은 <b>42 innovation academy</b>의 과제의 작성자의 해석 및 풀이 등으로 이루어져 있습니다.</br>본인이 42 교육생이거나 42 교육을 희망하는 분이라면 글을 먼저 보기보다는 고민해보고 읽어보기를 추천드립니다. > 목적 get_next_line을 실제로 구현해보자 ```c int get_next_line(int fd, char **line); ``` > get_next_line 이 글은 완전히 완성된 코드에 대한 이야기가 아니며, 완성된 코드는 위 링크를 통해 직접 해석해보자. 혹은 다른 분들의 완성 git을 참고하는것도 좋은 방법이다. 이 글에선 대략적 구조와 구성을 설명할 것이며, 이를 완벽한 코드로 변경하는것은 직접 할 수 있도록 하자. ### Structure 기본적인 gnl의 구조는 아래와 같이 두고 진행한다. ```c int get_next_line(int fd, char **line) { static char *file = NULL; int code; while (strchr(file, '\n') == 0) //개행을 찾을 때 까지 파일을 읽는다.. { code = read_file(fd, &file); //file을 읽고 read가 반환한 값을 반환한다. if (code == -1) return (error_handling()); //error case에 대한 처리를 한다. if (code == 0) break; } /* * 만약 마지막에 도달했는데, file에 문자가 남아있다면 개행으로 종료되지 않은 파일이고 * 이를 line에 담는다. */ if (code == 0 && file) fill_last_line(line, &file); // 개행이 발견된다면 file에 쓴다. else fill_line(line, &file); return(code < 1 ? code : 1); } ``` 위 함수를 살펴보면 개행을 찾을때까지 파일을 읽고(`read_file`) file변수에 저장한다. 개행을 찾거나 파일을 전부 읽으면 (`code == 0`) line에 file의 값을 채운다. 이때, 파일에서 line에 쓴값은 file에서 지운다. ### 파일을 읽는법 ```c int read_file(int fd, char **file) { char buf[BUFFER_SIZE + 1]; //BUFFER_SIZE는 외부에서 -D옵션을 통해 정해진 임의의 값이다. char *temp = *file; /* 만약 파일이 단 한번도 쓰인적이 없다면 최초의 할당을 진행한다. */ if (!file) temp = strdup(""); /* */ if ((code = read(fd, buf, BUFFER_SIZE)) > 0) strcat(temp, buf, code); //실제로는 해당 과정을 하기 전 file에 realloc을 진행해야 한다. *file = temp; //추가된 내용을 읽은 값을 file에 할당 return (code); } ``` ##### 왜 file을 2차 포인터로 받아올까? 변수의 지역성을 생각해보자. 어떠한 scope내에서 선언된 변수는 scope외부에서 접근할 수 없다. 마찬가지로 scope내부에서 할당된 메모리는 scope외부에서 접근할 수 없다. 따라서 이를 return거나, double 포인터를 통해 할당된 위치의 주소를 넣어둠으로써 외부에서 이를 사용할 수 있게끔 하는것이다. ### file을 read에 쓰는법 ```c void fill_line(char **line, char **file) { char *f_temp = *file; char *l_temp; char *new_file; int len; /* line의 file의 개행 전까지를 복사 */ len = strchr(f_temp, '\n') - f_temp; //line에 쓸 개행까지의 길이 l_temp = malloc((sizeof(char) * len) + 1); memncpy(l_temp, file, len); l_temp[len] = 0; *line = l_temp; /* file에서 line에 쓴 내용을 지우고 재 할당 */ new_file = malloc(sizeof(char) * (strlen(f_temp) - len) + 1); new_file = strcpy(strchr(f_temp, '\n') + 1); //개행 하나 뒤부터 마지막까지 내용을 복사 free(f_temp); *file = new_file; } ``` 위 코드들은 앞서 말했듯이 의사코드에 가깝다. 대략적으로 동작을 하지만 malloc protection도 걸려있지 않고 코드도 전혀 정리되지 않았다. 구조적으로만 이해하고 본인의 프로젝트에 도움이 될 수 있도록 참고하자.