get_next_line

J_JEON·2022년 4월 4일
0

gnl

목록 보기
3/3

get_next_line

파일디스크립터를 받아와 해당 파일에서 개행으로 끝나는 한줄의 문장을 반환하는 함수

get_next_line (int fd)

char	*get_next_line(int fd)
{
	char		*readstr;
	static char	*backup[OPEN_MAX];
	char		*str;
	int			readsize;
    int			j;
    
	j = 0;
	if (BUFFER_SIZE <= 0 || fd < 0 || fd >= OPEN_MAX)
		return (0);
    readstr = malloc(sizeof(char) * (BUFFER_SIZE + 1));
    if (!readstr)
    	return (0);
	while (!ft_strchr(backup[fd], '\n'))
	{
		readsize = read(fd, readstr, BUFFER_SIZE);
		if (readsize <= 0)
			break ;
		readstr[readsize] = '\0';
		backup[fd] = ft_strjoin(backup[fd], readstr);
	}
	str = make_line(backup[fd], j);
	backup[fd] = cut_line(backup[fd]);
	return (str);
}

1. 받아온 fd가 음수인지, BUFFER_SIZE가 0이하 인지 확인

	if (BUFFER_SIZE <= 0 || fd < 0 || fd >= OPEN_MAX)
		return (0);
  • BUFFER_SIZE가 0 또는 음수라면 read함수에서 제대로 문자열을 불러올 수 없기때문에 종료
  • fd가 음수인것은 정상적인 상황이 아니니 종료
  • fd가 OPEN_MAX보다 크면 안되므로 종료

2. 반복문을 사용해 read함수로 BUFFER_SIZE만큼 문자열을 받아오고 정적변수에 저장, 또한 해당 문자열에 개행이 포함되어있다면 반복문 종료

	while (!ft_strchr(backup[fd], '\n'))
	{
		readsize = read(fd, readstr, BUFFER_SIZE);
		if (readsize <= 0)
			break ;
		readstr[readsize] = '\0';
		backup[fd] = ft_strjoin(backup[fd], readstr);
	}
  • 문자열에서 특정 문자가 나온다면 해당 문자의 위치를 반환하는 ft_strchr 함수를 사용해 개행문자가 나온다면 반복문을 빠져나옴
  • read함수를 사용해 BUFFER_SIZE만큼 문자열을 읽고 readstr에 저장해줌, 그리고 읽어온 문자열의 길이를 readsize에 저장해줌
  • 만약 readsize가 0이라면 더이상 읽어올 문자열이 없는것이므로 반복문을 종료
  • readstr의 끝에 문자열이 끝났음을 표시하는 '\0'을 넣어줌
  • 정적변수에 들어있는 전에 읽었던 문자열과 이번에 읽었던 문자열을 합쳐줘야하므로 ft_strjoin을 사용해 두 문자열을 합쳐줌

3. 받아온 문자열을 사용해 개행문자가 나오거나 문자열이 종료될때 까지 한줄의 문자를 완성하고 반환시켜줌

str = make_line(backup[fd]);
...
char	*make_line(char *backup, int j)
{
	char	*str;

	if (backup == NULL)
		return (NULL);
	if (backup[0] == '\0')
		return (NULL);
	while (backup[j] != '\n' && backup[j] != '\0')
		j++;
	if (backup[j] == '\n')
		str = malloc(sizeof(char) * (j + 2));
	else
		str = malloc(sizeof(char) * (j + 1));
	if (!str)
		return (0);
	j = 0;
	while (backup[j] != '\n' && backup[j] != '\0')
	{
		str[j] = backup[j];
		j++;
	}
	if (backup[j] == '\n')
		str[j++] = '\n';
	str[j] = '\0';
	return (str);
}
  • backup이 NULL이라면 현재 정적변수에 아무것도 할당되지않은것이니 그대로 NULL을 반환
  • backup[0] 이 '\0'인것은 현재 정적변수에 남아있는 문자열이 없는것이니 NULL을 반환
  • 반복문을 사용해 문자열에 \n이나 \0이 나올때까지 인덱스값 증가
  • \n로 끝났다면 \n과 \0두가지를 더 넣어줘야하므로 인덱스값 + 2만큼 str문자열에 저장공간을 할당
  • \0으로 끝났다면 \0을 넣어줘야하므로 인덱스값 + 1만큼 str문자열에 저장공간을 할당
  • 반복문을 사용해 \n 또는 \0이 나올때까지 정적변수에 저장된 문자열을 str로 복사해줌
  • 문자열이 \n으로 끝났다면 str에도 \n을 넣어줌
  • 문자열 한줄이 완성되었으므로 \0을 넣어주고 문자열을 반환

4. 문자열을 저장해둔 정적변수에서 방금 출력한 한줄만큼을 삭제한 새 문자열을 만들고 정적변수에 넣어줌

backup[fd] = cut_line(backup[fd]);
...
char	*cut_line(char *backup)
{
	int		i;
	char	*str;

	i = 0;
	if (backup == NULL)
		return (NULL);
	while (backup[i] != '\n' && backup[i] != '\0')
		i++;
	if (backup[i] == '\0')
	{
		free(backup);
		return (NULL);
	}
	if (backup[i] == '\n')
		i++;
	str = ft_strdup(&backup[i]);
	free(backup);
	return (str);
}
  • backup이 NULL이라면 현재 정적변수에 아무것도 할당되지않은것이니 그대로 NULL을 반환
  • 반복문을 사용해 문자열에 \n이나 \0이 나올때까지 인덱스값 증가
  • 만약 \0이 나왔다면 읽어온 파일이 끝난것이므로 free해주고 NULL 반환
  • 만약 \n이 나왔다면 해당자리는 일단 건너야하므로 인덱스값을 1 증가
  • 현재 위치부터 끝까지의 문자열을 새롭게 만들어주는 ft_strdup함수를 사용해 backup[i]부터 끝까지의 문자열을 새로 할당하여 str에 저장
  • 기존에 사용하던 backup을 free해주고 새로 만든 str을 반환
profile
늅늅

0개의 댓글