컴파일 명령어
cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 get_next_line.c get_next_line.h get_next_line_utils.c main.c
get_next_line.h
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bchoi <bchoi@student.42Seoul.kr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/09 16:20:23 by bchoi #+# #+# */
/* Updated: 2022/04/09 19:48:56 by bchoi ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H
# include <stdlib.h>
// 힙 메모리에 동적 할당하는 malloc() 함수가 정의
# include <unistd.h>
// read 함수 정의
char *get_next_line(int fd);
char *ft_read_and_save(int fd, char *save);
char *ft_save(char *save);
char *ft_get_line(char *save);
size_t ft_strlen(char *s);
char *ft_strchr(char *s, int c);
char *ft_strjoin(char *s1, char *s2);
#endif
get_next_line.c
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bchoi <bchoi@student.42Seoul.kr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/09 16:17:30 by bchoi #+# #+# */
/* Updated: 2022/04/09 19:44:43 by bchoi ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line.h"
char *ft_get_line(char *save)
{
int i;
char *line;
i = 0;
if (!save[i])
return (NULL);
while (save[i] && save[i] != '\n')
i++;
line = (char *) malloc(sizeof(*line) * (i + 2));
// \n로 끝났다면 \n과 \0 두 가지를 넣어줘야하므로 길이 + 2만큼 저장공간을 할당
if (!line)
return (NULL);
i = -1;
while (save[++i] && save[i] != '\n')
line[i] = save[i];
if (save[i] == '\n')
{
line[i] = save[i];
i++;
}
line[i] = '\0';
return (line);
}
// 한 줄을 반환하는 함수
char *ft_save(char *save)
{
int i;
int j;
char *new_save;
i = 0;
while (save[i] && save[i] != '\n')
i++;
if (!save[i])
{
free(save);
return (NULL);
}
new_save = (char *) malloc(sizeof(*new_save) * (ft_strlen(save) - i + 1));
if (!new_save)
return (NULL);
i++;
j = 0;
while (save[i])
new_save[j++] = save[i++];
new_save[j] = '\0';
free(save);
return (new_save);
}
// 읽은 한 줄만큼을 삭제하고 새로운 문자열을 리턴
char *ft_read_and_save(int fd, char *save)
{
char *buffer;
int bytes;
buffer = malloc((BUFFER_SIZE + 1) * sizeof(*buffer));
// 메모리 할당. '\0' 추가해야 하기 때문에 +1
if (!buffer)
return (NULL);
bytes = 1;
while (!ft_strchr(save, '\n') && bytes)
/* strchr은 문자열 내에 일치하는 문자가 있는지 검사하는 함수임.
'\n'이 존재하는지 검사하고, 개행문자가 나온다면 반복문을 빠져나옴.
*/
{
bytes = read(fd, buffer, BUFFER_SIZE);
/* read 함수를 이용해 BUFFER_SIZE만큼 문자열을 읽고 buffer에 저장.
읽어온 문자열의 길이는 bytes에 저장
*/
if (bytes == -1)
// 오류가 생기면 bytes에 -1이 반환됨. 이때는 buffer를 free 해주고 NULL 리턴.
{
free(buffer);
return (NULL);
}
buffer[bytes] = '\0';
// buffer의 끝에 문자열의 마지막임을 표시하는 '\0' 추가
save = ft_strjoin(save, buffer);
// save에 읽은 문자열을 합쳐서 리턴해줌
}
free(buffer);
return (save);
}
// 전체를 읽고 저장하는 함수
char *get_next_line(int fd)
{
char *line;
static char *save;
if (fd < 0 || BUFFER_SIZE <= 0)
/* BUFFER_SIZE가 0 또는 음수라면 read 함수에서 제대로 문자열을 불러올 수 없기 때문에 종료
fd가 음수면 정상적인 상황이 아니기 때문에 종료
*/
return (0);
save = read_and_save(fd, save);
if (!save)
return (NULL);
// 정상적이지 않은 경우 NULL 리턴
line = get_line(save);
save = ft_save(save);
return (line);
}
get_next_line_utils.c
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bchoi <bchoi@student.42Seoul.kr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/09 16:20:13 by bchoi #+# #+# */
/* Updated: 2022/04/09 19:37:53 by bchoi ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line.h"
size_t ft_strlen(char *str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
// 문자열 내에 일치하는 문자가 있는지 검사하는 함수
// 문자가 존재하면 해당 문자가 존재하는 곳의 포인터를 반환하고, 존재하지 않으면 널 포인터를 반환
char *ft_strchr(char *s, int c)
{
int i;
i = 0;
if (!s)
return (0);
if (c == '\0')
return ((char *)&s[ft_strlen(s)]);
while (s[i] != '\0')
{
if (s[i] == (char) c)
return ((char *)&s[i]);
i++;
}
return (0);
}
char *ft_strjoin(char *s1, char *s2)
{
size_t i;
size_t c;
char *str;
if (!s1)
{
s1 = (char *)malloc(1 * sizeof(char));
s1[0] = '\0';
}
// s1이 빈 믄자열일 때 처리
if (!s1 || !s2)
return (NULL);
str = malloc((ft_strlen(s1) + ft_strlen(s2) + 1) * sizeof(char));
if (str == NULL) // !str로 수정
return (NULL);
i = -1;
c = 0;
if (s1)
while (s1[++i] != '\0')
str[i] = s1[i];
while (s2[c] != '\0')
str[i++] = s2[c++];
str[ft_strlen(s1) + ft_strlen(s2)] = '\0';
free(s1);
return (str);
}
main.c (테스트용)
#include "get_next_line.h"
#include <stdio.h>
#include <fcntl.h>
// 파일을 여는 open() 함수와 O_RDONLY 등의 파일 접근 모드가 정의되어 있음.
int main(void)
{
int fd;
char *line;
fd = open("test.txt", O_RDONLY);
while ((line = get_next_line(fd)) != NULL)
{
printf("%s", line);
free(line);
}
printf("%s", line);
free(line);
close(fd);
return (0);
}
컴파일 명령어
cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 get_next_line_bonus.c get_next_line_bonus.h get_next_line_utils_bonus.c main_bonus.c
get_next_line_bonus.h
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_bonus.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bchoi <bchoi@student.42Seoul.kr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/09 17:59:02 by bchoi #+# #+# */
/* Updated: 2022/04/09 19:48:22 by bchoi ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef GET_NEXT_LINE_BONUS_H
# define GET_NEXT_LINE_BONUS_H
# include <stdlib.h>
# include <unistd.h>
char *get_next_line(int fd);
char *ft_read_and_save(int fd, char *save);
char *ft_save(char *save);
char *ft_get_line(char *save);
size_t ft_strlen(char *str);
char *ft_strchr(char *s, int c);
char *ft_strjoin(char *s1, char *s2);
#endif
get_next_line_bonus.c
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bchoi <bchoi@student.42Seoul.kr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/09 18:00:17 by bchoi #+# #+# */
/* Updated: 2022/04/09 19:47:46 by bchoi ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line_bonus.h"
char *ft_get_line(char *save)
{
int i;
char *line;
i = 0;
if (!save[i])
return (NULL);
while (save[i] && save[i] != '\n')
i++;
line = (char *) malloc(sizeof(*line) * (i + 2));
if (!line)
return (NULL);
i = -1;
while (save[++i] && save[i] != '\n')
line[i] = save[i];
if (save[i] == '\n')
{
line[i] = save[i];
i++;
}
line[i] = '\0';
return (line);
}
char *ft_save(char *save)
{
int i;
int j;
char *new_save;
i = 0;
while (save[i] && save[i] != '\n')
i++;
if (!save[i])
{
free(save);
return (NULL);
}
new_save = (char *) malloc(sizeof(*new_save) * (ft_strlen(save) - i + 1));
if (!new_save)
return (NULL);
i++;
j = 0;
while (save[i])
new_save[j++] = save[i++];
new_save[j] = '\0';
free(save);
return (new_save);
}
char *ft_read_and_save(int fd, char *save)
{
char *buffer;
int bytes;
buffer = malloc((BUFFER_SIZE + 1) * sizeof(*buffer));
if (!buffer)
return (NULL);
bytes = 1;
while (!ft_strchr(save, '\n') && bytes)
{
bytes = read(fd, buffer, BUFFER_SIZE);
if (bytes == -1)
{
free(buffer);
return (NULL);
}
buffer[bytes] = '\0';
save = ft_strjoin(save, buffer);
}
free(buffer);
return (save);
}
char *get_next_line(int fd)
{
char *line;
static char *save[4096];
if (fd < 0 || BUFFER_SIZE <= 0 || fd > 256)
return (0);
save[fd] = read_and_save(fd, save[fd]);
if (!save[fd])
return (NULL);
line = get_line(save[fd]);
save[fd] = ft_save(save[fd]);
return (line);
}
get_next_line_utils_bonus.c
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_utils_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bchoi <bchoi@student.42Seoul.kr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/04/09 18:05:08 by bchoi #+# #+# */
/* Updated: 2022/04/09 20:17:44 by bchoi ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line_bonus.h"
size_t ft_strlen(char *str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
char *ft_strchr(char *s, int c)
{
int i;
i = 0;
if (!s)
return (0);
if (c == '\0')
return ((char *)&s[ft_strlen(s)]);
while (s[i] != '\0')
{
if (s[i] == (char) c)
return ((char *)&s[i]);
i++;
}
return (0);
}
char *ft_strjoin(char *s1, char *s2)
{
size_t i;
size_t c;
char *str;
if (!s1)
{
s1 = (char *)malloc(1 * sizeof(char));
s1[0] = '\0';
}
if (!s1 || !s2)
return (NULL);
str = malloc((ft_strlen(s1) + ft_strlen(s2) + 1) * sizeof(char));
if (str == NULL)
return (NULL);
i = -1;
c = 0;
if (s1)
while (s1[++i] != '\0')
str[i] = s1[i];
while (s2[c] != '\0')
str[i++] = s2[c++];
str[ft_strlen(s1) + ft_strlen(s2)] = '\0';
free(s1);
return (str);
}
main_bonus.c
#include "get_next_line_bonus.h"
#include <stdio.h>
#include <fcntl.h>
// 파일을 여는 open() 함수와 O_RDONLY 등의 파일 접근 모드가 정의되어 있음.
int main(void)
{
int fd;
int fd2;
char *line;
char *line2;
fd = open("test.txt", O_RDONLY);
fd2 = open("test2.txt", O_RDONLY);
printf("fd: %d\n", fd);
printf("fd2: %d\n", fd2);
line = get_next_line(fd);
printf("%s", line);
line2 = get_next_line(fd2);
printf("%s", line2);
free(line);
free(line2);
line = get_next_line(fd);
printf("%s", line);
line2 = get_next_line(fd2);
printf("%s", line2);
free(line);
free(line2);
close(fd);
close(fd2);
return (0);
}