fd => 0 표준입력, 1 표준출력, 2 표준에러
임의로 파일을 읽어들이면 3번부터 배정받는다.
static 변수는 함수내부에서도 사용이 가능하고 전역에서도 사용이 가능하다. 특이하게도 static변수는 따로 초기화 하지 않아도 0 으로 초기화된다. static 변수는 프로그램이 시작될때 할당되고 프로그램이 끝날때 파괴된다. 전역 static 변수의 경우 그 소스파일 내의 모든 함수에서 사용이 가능하지만 함수 내부에서 선언을 하게되면 다른 함수에서는 값을 참조할 수 없다. 이를 내부정적변수라 하는데 프로그램이 시작될때 한번만 초기화가 되어지고 반복실행된다하여도 초기화 되지 않는다.
#주의할점#
내부 정적변수를 사용하는 과정에서 중괄호 내에서만(선언한 해당 함수 내) 사용이 가능하기 때문에 외부적인 접근에 어려움이 있다.
헤더: unistd.h
형태: ssize_t read (int fd, void buf, size_t nbytes)
인수: int fd 파일 디스크립터 void** buf 파일을 읽어 들일 버퍼 size_t nbytes 퍼버의 크기
반환: ssize_t == -1 실패> 0 정상적으로 실행되었다면 읽어들인 바이트 수
버퍼의 크기보다 파일이 크면 여러번 읽어올수있는데 read 함수가 자체적으로 이전에 읽은부분 이후를 버퍼에 담아준다.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "./get_next_line/get_next_line.h"
int main()
{
int fd;
static t_gnl_list *head;
char *buf;
if ( 0 < ( fd = open( "./txt1.txt", O_RDONLY))) //12345가 들어있는 파일
{
printf("%zd || %s\n",read( fd, buf, 2),buf);// 2 || 12
printf("%zd || %s\n",read( fd, buf, 2),buf);// 2 || 34
printf("%zd || %s\n",read( fd, buf, 2),buf);// 1 || 54
/* 읽은 바이트수가 버퍼사이즈보다 작으면 끝까지 읽은 것이고, buf+바이트수 -1 까지 버퍼에 담긴것이다. */
printf("%zd || %s\n",read( fd, buf, 2),buf);// 0 || 54
close( fd);
}
else
printf( "파일 열기에 실패했습니다.\n");
return 0;
}
형태 : open (const char *FILENAME, int FLAGS[, mode_t MODE])
파일 이름과 파일에 대한 열기 옵션을 주게 되면 파일 디스크립터의 양의 정수 값을 반환 하게 된다.
이 때 특이하게도 같은 파일을 두번 열면 같은 디스크립터가 아니라 다른 디스크립터가 반환된다.
기본적으로 양방향 리스트를 사용하여 여러 파일들에 대한 접근을 가능하게 하였다.
fd 값이랑 동일한 값을 가지는 리스트 노드를 탐색한다. 없다면 static 변수를 통해 head를 고정시켜주고 임의의 tmp노드를 사용하여 리스트 구조체의 값들에 접근을 한다.
맨처음 해당 리스트 tmp에 backup이 존재한다면 nl의 존재여부에 대한 확인을 하고, 만약 nl이 존재한다면 nl까지 부분을 결과값으로 리턴해주고 나머지 부분은 다시 해당 노드 backup부분에 저장한다.
backup이 없거나 nl이 존재하지 않는다면 while문을 통해 read를 하게 되고, read를 할때마다 nl의 존재를 판별해준다. nl이 존재한다면 backup + read nl까지 를 리턴해주고 나머지는 backup부분에 저장해준다. 만약 없다면 backup + read 한부분을 backup에 저장해주고 while문을 다시 돌게된다.
while문의 종료 조건은 eof이거나 read 오류가 발생하였거나 malloc에 대한 오류가 발생하였을 때이다. 정상적으로 eof에 도달하게 된다면 backup에 존재하는 값()을 출력해주고 해당 리스트를 free해준다. 이외의 오류로 인한 종료 조건들의 경우 leak이 발생하지 않도록 malloc한 부분들을 전부 free해주고 해당 리스트의 노드도 free 해준다.
다 읽은 파일의 경우 read값이 0 이기때문에 이 점을 활용하여 NULL을 리턴하게끔 하면 된다.
t_gnl_list *del_gnl_list(t_gnl_list **tmp)
{
/*
노드에 연결되어진 다른 리스트들에 대해 판별하고 리스트들을 이어주거나 하는
작업을 해준다.
해당 노드내에 동적할당된 부분들을 free해주고 해당노드 또한 free해준다.
*/
}
t_gnl_list *find_fd(t_gnl_list *tmp, int fd, t_gnl_list *head)
{
/*
해당 fd와 같은 값을 가지고있는 리스트를 탐색하고 만약 없다면 새로운 리스트를 만들어준다.
이후 해당 리스트의 주소값을 리턴해준다.
*/
}
char *combine_all(char **str1, char **str2, t_gnl_list **tmp)
{
/*
두 문자열을 합쳐주는 역할을 하는 함수. 합쳐주고 사용되어진 문자열들은 free해주고
NULL을 가리키게끔 한다.
*/
}
char *read_line(t_gnl_list **tmp, int fd)
{
/*
while문을 돌면서 read를 하고 eof를 판별해주며 결과에 맞는 값을 리턴해준다.
*/
}
char *get_next_line(int fd)
{
static t_gnl_list *head; // 최초의 고정 노드
t_gnl_list *tmp; // 임의로 사용하는 노드
char *res;
if (fd < 0)
return (NULL);
if (!head) // 최초 노드가 없다면
head = find_fd(head, fd, NULL);
if (!head)
return (NULL);
tmp = find_fd(head, fd, NULL);
res = NULL;
if (tmp->backup) // backup에 값이 존재한다면
res = is_nl_backup(&tmp->backup, ft_len_free(tmp->backup, 0), tmp);
/* backup에서의 nl존재여부에 따른 결과값을 받는다 */
while (1)
{
if (!res) // 결과값이 없다면
res = read_line(&tmp, fd); // read에서의 nl존재여부에 따른 결과값을 받는다
if (tmp->eof || res) // eof거나 res값이 존재한다면
{
if (tmp->eof)
head = del_gnl_list(&tmp); // eof면 해당 노드를 free해준다.
return (res);
}
}
}