[C] Get_Next_line 구현하기

Austin·2024년 11월 24일

42-Cursus

목록 보기
5/24

Get_next_line이란?

gnl함수는 파일이나 표준 입력으로부터 한 줄씩 읽어오는 함수다.

GNL 구현

이 함수의 프로토타입은 아래와 같이 작성 되어 있다.

char *get_next_line(int fd);
  • fd : 읽어올 파일의 파일 디스크립터
  • 반환값: 읽어온 한 줄의 문자열 (개행 문자 포함)

GNL 구현 요구사항

  • 한 줄씩 읽기: 함수를 호출할 때마다 파일에서 한 줄씩 읽어온다.
  • 정적 변수 사용: 이전 호출에서 읽은 데이터를 저장하기 위해 정적 변수를 사용한다.
  • 버퍼 크기 설정: BUFFER_SIZE 매크로를 통해 한 번에 읽어올 버퍼의 크기를 지정할 수 있다.
    컴파일 시 -D BUFFER_SIZE=00 플래그를 추가하여 BUFFER_SIZE를 지정할 수 있다.
  • 메모리 관리: 동적 할당을 사용하여 메모리를 효율적으로 관리해야한다.

GNL 구현 고려사항

  • 파일 읽기: read() 함수를 사용하여 파일에서 데이터를 읽어온다.
  • 문자열 처리: 개행 문자를 찾아 한 줄의 끝을 찾는다.
  • 메모리 누수 방지: 동적 할당된 메모리를 적절히 해제해야 한다.
  • EOF 처리: 파일의 끝에 도달했을 때 적절히 처리해야 한다.
  • 에러 처리: 파일 읽기 실패 등의 에러 상황을 고려해야 한다.

코드 설명

GNL 함수의 반환값은 파일에서 읽어온 한 줄의 문자열이다.
아래 코드는 함수를 구성하는 메인 코드이다.

char    *get_next_line(int fd)
{
        static char     *saved_buffer;
        char            *result;

        if (fd < 0 || fd > OPEN_MAX || BUFFER_SIZE <= 0)
                return (NULL);
        saved_buffer = read_line(fd, saved_buffer);
        if (!saved_buffer)
        {
                free(saved_buffer);
                return (NULL);
        }
        result = result_line(saved_buffer);
        saved_buffer = separate_line(saved_buffer);
        return (result);
}

기능

  • 파일 디스크립터에서 한 줄을 읽어 반환한다..

핵심 동작

  • saved_buffer: static 변수로 이전에 읽었던 데이터를 저장한다.
  • read_line: 파일에서 데이터를 읽어 saved_buffer에 저장한다.
  • result_line: saved_buffer에 저장된 문자열에서 개행 문자까지 한 줄을 찾아 저장하여 반환한다.
  • separate_line: 반환한 줄 이후의 데이터(개행 문자 등)를 저장한다.

read

char    *read_line(int fd, char *saved_buffer)
{
        char    *buffer;
        int             result;

        buffer = (char *)malloc(sizeof(char) * BUFFER_SIZE + 1);
        if (!buffer)
                return (NULL);
        result = 1;
        while (ft_strchr(saved_buffer, '\n') == NULL && result > 0)
        {
                result = read(fd, buffer, BUFFER_SIZE);
                if (result == -1)
                {
                        free(buffer);
                        if (saved_buffer)
                                free(saved_buffer);
                        return (NULL);
                }
                buffer[result] = '\0';
                saved_buffer = ft_strjoin(saved_buffer, buffer);
        }
        free(buffer);
        return (saved_buffer);
}

read 함수

  • 버퍼 크기만큼 파일을 읽어 saved_buffer에 저장한다.
    \n문자 혹은 EOF를 만날때까지의 한줄의 문자열을 찾아 반환한다.
  • buffer의 동적할당 크기를 BUFFER_SIZE+1을 하여 read 한 문자열에 끝을 알 수 있게 \0문자를 추가하는 코드가 작성 되어있다.
  • ft_strchr 함수로 \n이 있는지 확인하여 read를 반복하게 while문 종료조건을 작성했다.
  • ft_strjoin함수로 기존 saved_buffer와 새로 읽은 데이터를 합쳐 한 문장의 끝이 나올 때 까지 연결하였다.
  • 읽기 도중 에러 발생 시, 할당된 메모리를 모두 해제하고 NULL을 반환한다.

result

char    *result_line(char *saved_buffer)
{
        char    *line;
        int             i;

        i = 0;
        if (saved_buffer == NULL || saved_buffer[i] == '\0')
                return (NULL);
        while (saved_buffer[i] != '\n' && saved_buffer[i] != '\0')
                i++;
        line = (char *)malloc(sizeof(char) * (i + 2));
        if (!line)
                return (NULL);
        i = 0;
        while (saved_buffer[i] != '\n' && saved_buffer[i] != '\0')
        {
                line[i] = saved_buffer[i];
                i++;
        }
        if (saved_buffer[i] == '\n')
        {
                line[i] = saved_buffer[i];
                i++;
        }
        line[i] = '\0';
        return (line);
}

result 함수

  • saved_buffer에서 한 줄만 추출하는 기능이다.
  • saved_buffer에서 \n을 찾고 없으면 \0을 찾아 반환할 line을 동적할당 해준다.
  • 동적할당 된 line에 내용을 붙여 넣고 반환한다.

separate

char    *separate_line(char *saved_buffer)
{
        char    *rear_line;
        int             i;
        int             j;

        i = 0;
        j = 0;
        while (saved_buffer[i] != '\n' && saved_buffer[i] != '\0')
                i++;
        if (saved_buffer[i] == '\0')
        {
                free(saved_buffer);
                return (NULL);
        }
        i++;
        rear_line = (char *)malloc((int)ft_strlen(saved_buffer) - i + 1);
        if (!rear_line)
                return (NULL);
        while (saved_buffer[i] != '\0')
                rear_line[j++] = saved_buffer[i++];
        rear_line[j] = '\0';
        free(saved_buffer);
        return (rear_line);
}

separate 함수

  • result로 출력 될 문자열를 저장하고 이 후 다음 문자열에 이어질 문자만 static 변수인 saved_buffer에 저장하는 함수다.
  • 전체 문자열길이에서 첫 문자열부터 \n까지의 길이를 빼서 rear_line에 동적할당 한다.
    이후 문자열들을 붙여넣고 반환한다.
  • 이 때 saved_buffer를 free 해주는데 상위 함수에서 saved_buffer에 다시 저장하게 됨으로 현재 불러져있는 내용은 free 한다.

0개의 댓글