[GNL] 과제 정리

유성·2022년 10월 16일

42seoul

목록 보기
1/2

Subject

Mandatory Part

프로토타입int get_next_line(int fd);
제출할 파일get_next_line.c, get_next_line_utils.c, get_next_line.h
매개변수프로그램이 읽을 파일 디스크럽터(The file descriptor to read from)
리턴 값Read line: correct behavior
NULL: there is nothing else to read, or an error occurred
외부 함수read, malloc, free
설명파일 디스크럽터로부터 읽어 온 하나의 라인(newline 없이)을 반환하는 함수 작성

Goal

  • GNL 함수를 loop 안에서 호출하면 fd의 텍스트를 EOF가 올 때 까지 한 번에 한 줄씩 읽을 수 있다.
  • GNL 함수를 처음 호출 했을 때 파일을 끝까지 읽었다 하더라도, 두 번째 호출했을 때는 두 번째 line부터 시작해야한다.
  • file로부터, redirection으로부터, stdin으로부터 읽었을 때 함수가 제대로 동작해야 한다.
  • 이 프로그램은 -D BUFFER_SIZE=xx 플래그를 붙여서 컴파일 해야 한다. 즉, read 함수는 표준입력으로 또는 파일로부터 읽어들이기 위해서 컴파일할 때 정의된 BUFFER_SIZE를 사용해야 한다.
  • BUFFER_SIZE가 1일 때도, 9999일 때도, 10000000 (1000만)일 때도 함수가 제대로 동작해야 한다.

1. 파일 디스크럽터 (File Descriptor)

표준 입력(Standard Input) : File Descriptor 0
표준 출력(Standard Output) : File Descriptor 1
표준 에러 출력(Standard Error) : File Descriptor 2

2. read() 함수

size_t read(int fd, void *buf, size_t bytes)
bytes 수 만큼 fd를 읽어 buf에 저장한다.
리턴값 : 읽어 온 바이트 수. 실패 시 -1.
파일을 끝까지 읽었으면, 다음 번에는 더 이상 읽을 바이트가 없기 때문에 0을 반환한다.

3. gcc -d 플래그

외부에서 #define을 정의한다.
이 문제에서 컴파일은 다음과 같이 진행된다.
$ gcc -Wall -Wextra -Werror -D BUFFER_SIZE=42 get_next_line.c get_next_line_utils.c
즉, BUFFER_SIZE를 컴파일할 때 정하게 된다.

4. static 변수

  • static 변수는 지역변수와 같이 선언된 함수 내에서만 사용이 가능하다.
  • 그러나 한 번만 초기화하며, 전역 변수처럼 프로그램이 종료될 때까지 메모리 공간에 존재한다.
  • 지역 변수와는 달리, 해당 함수가 종료되거나 반환을 하더라도 소멸되지 않는다.
  • GNL에서는 개행 이후의 문자열 주소를 저장하기 위해 사용

Code

get_next__line.c

#include "get_next_line.h"

char	*read_line(int fd, char *buf)
{
	char	*str;
	int		rsize;

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

char	*get_line(char *buf)
{
	char	*str;
	int		j;
	int		i;

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

char	*backup(char *buf)
{
	char	*str;
	int		i;
	int		j;

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

char	*get_next_line(int fd)
{
	char		*line;
	static char	*buf;

	if (fd < 0 || BUFFER_SIZE < 1)
		return (NULL);
	buf = read_line(fd, buf);
	if (!buf)
	{
		free (buf);
		return (NULL);
	}
	line = get_line(buf);
	buf = backup(buf);
	return (line);
}

get_next_line_utils.c

#include "get_next_line.h"

char	*ft_strchr(const char *s, int c)
{
	int	i;

	i = 0;
	if (!s)
		return (NULL);
	while (s[i])
	{
		if (s[i] == (char)c)
			return ((char *)s + i);
		i++;
	}
	if (c == '\0')
		return ((char *)s + i);
	return (NULL);
}

size_t	ft_strlen(const char *s)
{
	size_t	i;

	i = 0;
	if (!s)
		return (0);
	while (s[i])
		i++;
	return (i);
}

char	*ft_strjoin(char *s1, char *s2)
{
	char	*res;
	int		i;
	int		j;

	i = 0;
	j = 0;
	if (!s1 && !s2)
		return (NULL);
	res = malloc((sizeof(char) * (ft_strlen(s1) + ft_strlen(s2)) + 1));
	if (!res)
		return (NULL);
	if (s1)
	{
		while (s1[i])
		{
			res[i] = s1[i];
			i++;
		}
	}
	while (s2[j])
		res[i++] = s2[j++];
	free (s1);
	res[i] = '\0';
	return (res);
}

get_next_line.h

#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H

# include <unistd.h>
# include <stdlib.h>

# ifndef BUFFER_SIZE
#  define BUFFER_SIZE 1024
# endif

char	*get_next_line(int fd);
char	*backup(char *buf);
char	*get_line(char *buf);
char	*read_line(int fd, char *buf);
size_t	ft_strlen(const char *s);
char	*ft_strchr(const char *s, int c);
char	*ft_strjoin(char *s1, char *s2);

#endif

Comment

다음 과제에는 leak 관련된 부분, 변수 이름이 적절하지 못했던 점들 신경쓰기

0개의 댓글