Do You Coding?

[utility] get_next_line ๊ตฌํ˜„ํ•˜๊ธฐ ๋ณธ๋ฌธ

CS & Engineering/C

[utility] get_next_line ๊ตฌํ˜„ํ•˜๊ธฐ

๐Ÿ“Œ ๋งค๋‰ด์–ผ (in subject)

๋”๋ณด๊ธฐ

Function name

     get_next_line

 

Prototype

     char *get_next_line(int fd);

 

Parameters

     fd: The file descriptor to read from

: ์ฝ์–ด์˜จ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ

 

Return value

    Read line: correct behavior / NULL: there is nothing else to read, or an error occurred

: ์˜ฌ๋ฐ”๋ฅธ ๋™์ž‘์€ ์ค„ 1์ค„ ์ฝ์–ด์˜ค๋Š” ๊ฒƒ์ด๊ณ , ์ฝ์„ ๊ฒŒ ์—†๊ฑฐ๋‚˜ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด NULL์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค

 

External functs

     read, malloc, free

 

Description

     Write a function that returns a line read from a file descriptor

: ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋กœ๋ถ€ํ„ฐ ์ฝ์–ด์™€ ํ•œ์ค„์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค

 

๐Ÿ“Œ ์ž‘์„ฑ ์ฝ”๋“œ (1) - header file code

#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H

# ifndef BUFFER_SIZE
#  define BUFFER_SIZE 10
# endif

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

size_t	do_strlen(const char *s);
char	*do_strdup_s(char *str, char *buff);
char	*do_strljoin(char *s1, char *s2, int rs);
size_t	do_strlcpy(char *dst, const char *src, size_t size);
char	*get_next_line(int fd);

#endif

๐Ÿ“Œ ์ž‘์„ฑ ์ฝ”๋“œ (2) - utils code

#include "get_next_line.h"

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

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

char	*do_strdup_s(char *str, char *buff)
{
	char	*dup;
	size_t	buff_len;
	size_t	i;

	buff_len = do_strlen(buff);
	i = 0;
	dup = (char *)malloc(sizeof(char) * (buff_len + 1));
	if (dup == NULL)
		return (NULL);
	while (buff[i] != '\0')
	{
		dup[i] = buff[i];
		i ++;
	}
	dup[i] = '\0';
	if (str != NULL)
		free (str);
	return (dup);
}

char	*do_strljoin(char *s1, char *s2, int rs)
{
	char	*s3;
	size_t	i;
	size_t	len_s1;

	i = 0;
	len_s1 = do_strlen(s1);
	if (!s1 || !s2)
		return (NULL);
	s3 = (char *)malloc(sizeof(char) * (len_s1 + rs + 1));
	if (s3 == NULL)
		return (NULL);
	while (i < len_s1)
	{
		s3[i] = s1[i];
		i ++;
	}
	while (i < len_s1 + rs)
	{
		s3[i] = s2[i - len_s1];
		i ++;
	}
	free (s1);
	s3[i] = '\0';
	return (s3);
}

size_t	do_strlcpy(char *dst, const char *src, size_t size)
{
	size_t	i;

	i = 0;
	while (i + 1 < size && src[i] != '\0')
	{
		dst[i] = src[i];
		i ++;
	}
	if (size != 0)
		dst[i] = '\0';
	return (do_strlen(src));
}

๐Ÿ“Œ ์ž‘์„ฑ ์ฝ”๋“œ (3) - main code

#include "get_next_line.h"

static int	read_and_store(int fd, char **str)
{
	char	buff[BUFFER_SIZE + 1];
	int		rs;

	rs = read(fd, buff, BUFFER_SIZE);
	if (rs <= 0)
		return (rs);
	buff[rs] = '\0';
	if (*str == NULL)
		*str = do_strdup_s(*str, buff);
	else
		*str = do_strljoin(*str, buff, rs);
	return (rs);
}

static char	*put_next_line(char **str, size_t len, size_t i)
{
	char	*restr;

	restr = NULL;
	i ++;
	restr = malloc(i + 1);
	if (restr == NULL)
		return (NULL);
	do_strlcpy(restr, *str, i + 1);
	if (i - 1 == len)
	{
		free (*str);
		*str = NULL;
	}
	else if (i - 1 != len)
		*str = do_strdup_s(*str, *str + i);
	return (restr);
}

char	*get_next_line(int fd)
{
	static char	*str = NULL;
	int			rs;
	size_t		len;
	size_t		i;

	while (1)
	{
		rs = read_and_store(fd, &str);
		if (str[fd] != NULL)
			len = do_strlen(str);
		if (rs == -1 || (rs == 0 && str == NULL) || (len == 0))
		{
			free (str);
			str = NULL;
			return (NULL);
		}
		i = 0;
		while (str[i] != '\n' && i < len)
			i ++;
		if ((i == len && (rs < BUFFER_SIZE)) || (i != len))
			return (put_next_line(&str, len, i));
	}
}

 

๐Ÿ“Œ ์ฝ”๋“œ ๋ฆฌ๋ทฐ

- char *get_next_line(int fd)


โ— ๋™์ž‘ : ์ธ์ž๋กœ ๋ฐ›์•„์˜จ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ(fd)๋กœ ์ฝ์–ด์˜จ ํŒŒ์ผ์—์„œ, ๊ฐœํ–‰์„ ์ฐพ์•„๊ฐ€๋ฉฐ 1์ค„ ์”ฉ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜


โ— ์ฃผ์š” ๊ณผ์ • : static์œผ๋กœ ๋‚ด๋ถ€์ •์ ๋ณ€์ˆ˜ str์„ ์„ ์–ธํ•˜๊ณ , while(1)์„ ํ†ตํ•ด ๋ฌดํ•œ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ฆฐ๋‹ค.
๊ทธ ํ›„, read_and_store ํ•จ์ˆ˜์—์„œ BUFFER_SIZE ๋งŒํผ readํ•˜์—ฌ buff ๋ฌธ์ž์—ด์— ๋‹ด์•„์ค€๋‹ค.
str์ด ๋น„์–ด์žˆ์œผ๋ฉด (=NULL) strdup์œผ๋กœ ์ƒˆ๋กœ ๋‹ด์•„์ฃผ๊ณ , ๋น„์–ด์žˆ์ง€ ์•Š์œผ๋ฉด strljoin์œผ๋กœ ๋ถ™์—ฌ์ค€๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ฝ์€ read_size๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํ•ด๋‹น ๊ฐ’์— ๋”ฐ๋ผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๊ณ , ๊ฐœํ–‰์ด ํ•ด๋‹น str์— ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด

put_next_line ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜์—์„œ๋Š” ํ˜„์žฌ str์—์„œ ๊ฐœํ–‰ ์ „๊นŒ์ง€ ๋ฌธ์ž์—ด์€ ๋ฐ˜ํ™˜ํ•˜๊ณ ,

๊ฐœํ–‰ ์ดํ›„์˜ ๋ฌธ์ž์—ด๋งŒ str์— ๋‚จ๊ฒจ๋‘๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ๋งŒ์•ฝ ์œ„์—์„œ str์— ๊ฐœํ–‰์ด ํฌํ•จ ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด,

while๋ฌธ์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์—ฌ ๋‹ค์‹œ read_and_store ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜์—ฌ BUFFER_SIZE๋งŒํผ readํ•˜๋Š” ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜๋‹ค

๊ฐœํ–‰์„ ๋งŒ๋‚˜ ๋ฐ˜ํ™˜ํ•  ๋•Œ๊นŒ์ง€ ์ˆ˜ํ–‰ํ•œ๋‹ค.
 
โ— ์„ค๋ช…
- ์šฐ์„ , static์„ ํ†ตํ•ด ํ•จ์ˆ˜ ๋‚ด์— ๋งŒ๋“  ๋‚ด๋ถ€์ •์ ๋ณ€์ˆ˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋  ๋•Œ ํ• ๋‹น๋˜๊ณ , ์ข…๋ฃŒํ•  ๋•Œ ํ•ด์ œ๋œ๋‹ค.
๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ๋ฒˆ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด๋„, ํ•œ๋ฒˆ๋งŒ ์ดˆ๊ธฐํ™”๋˜๋ฏ€๋กœ ์ด๋ฅผ ํ™œ์šฉํ•ด ๊ฐœํ–‰ ์ดํ›„์˜ ๋ฌธ์ž์—ด์„ ๋‹ด์•„๋‘๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.


- while๋ฌธ์„ ๋ฌดํ•œ ๋ฐ˜๋ณต์œผ๋กœ ํ•˜์—ฌ ๊ณ„์† ์‹คํ–‰ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ๊ฐœํ–‰์„ ๋งŒ๋‚˜์„œ put_next_line ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด

๊ทธ๋•Œ ์ข…๋ฃŒ๋œ๋‹ค. get_next_line ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ ์œ„์—์„œ์˜ ์–ธ๊ธ‰์ฒ˜๋Ÿผ ๋‚ด๋ถ€์ •์ ๋ณ€์ˆ˜์ด๋ฏ€๋กœ,

ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ๊นŒ์ง€ static์ด ์œ ์ง€๊ฐ€ ๋˜๋Š”๋ฐ, ์ฒซ ์ค„์ด ๊ฐœํ–‰์„ ๋งŒ๋‚˜ get_ next_line์„ ์ฒ˜์Œ ๋ฐ˜ํ™˜ํ–ˆ๋‹ค๊ณ  ํ•ด๋„,

static ๋ณ€์ˆ˜์— ๊ทธ ๊ฐœํ–‰ ์ดํ›„์˜ ๊ฐ’์ด ๋‚จ์•„์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

(Buffer ํฌ๊ธฐ๋งŒํผ read๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฏ€๋กœ, buffer ํฌ๊ธฐ์— ๋”ฐ๋ผ ๊ฐœํ–‰ ์ดํ›„์˜ ๋ฌธ์ž์—ด์ด ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.)

 

- ์ด static ์œผ๋กœ ์„ ์–ธํ•œ ๋ฌธ์ž์—ด์— ๊ฐœํ–‰์ด ์ค‘๊ฐ„์— ์žˆ๋‹ค๋ฉด ๊ทธ ์ดํ›„์˜ ๋ฌธ์ž์—ด๋งŒ static๋ณ€์ˆ˜์— ๋‚จ๊ฒจ๋‘๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.

๋‹ค์Œ get_next_line์„ ๋ถˆ๋Ÿฌ์™”์„ ๋•Œ, static์— ์žˆ๋Š” ๋ฌธ์ž์—ด ๋’ค๋กœ ์ƒˆ๋กœ ์ฝ์–ด์˜จ ๋ฌธ์ž์—ด์„ ๋ถ™์—ฌ์•ผ ์ •์ƒ์ ์œผ๋กœ

๋‹ค์Œ ์ค„์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
 

- ์‹คํ–‰ ์‹œ, buffer size๋ฅผ ํ„ฐ๋ฏธ๋„์—์„œ ํ‘œ์ค€์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„์™€ ์ ์šฉํ•˜๋Š”๋ฐ, ์ด ์ž…๋ ฅ๊ฐ’์ด ์กด์žฌํ•˜์ง€์•Š์„ ๋•Œ๋Š”

header์—์„œ define์ด ๋˜์ง€ ์•Š์•˜์„ ๋•Œ 10์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ์ง€์ •ํ•ด๋‘์—ˆ๋‹ค.

 

- util๋“ค์„ ํ™•์ธํ•ด๋ณด๋ฉด, ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋งŒ๋“ค์–ด๋’€๋˜ str ๊ด€๋ จ ํ•จ์ˆ˜๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ๊ฐ€์ ธ์˜จ string์„ freeํ•ด์ฃผ๋Š” ๊ณผ์ •์„

์ถ”๊ฐ€ํ•ด๋‘์—ˆ๋‹ค. ๊ธฐ์กด์— ์กด์žฌํ•˜๋Š” string์„ freeํ•ด์ฃผ๊ณ  ์ƒˆ๋กœ ํ• ๋‹น๋œ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ž‘์—… ๋“ฑ์„ ํ•˜๊ธฐ์œ„ํ•ด ์ ์šฉํ•˜์˜€๋‹ค.

 

โ— ํšŒ๊ณ 
- 3 ~ 4๋‹ฌ ์ „์— ์ง  ํ•จ์ˆ˜๋ผ ์ง€๊ธˆ ๋ณด๋‹ˆ ์ •๋ฆฌ๊ฐ€ ๊น”๋”ํ•˜๊ฒŒ ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋Š” ๋А๋‚Œ์ด ์žˆ๊ธด ํ•˜๋‹ค.

๋˜ํ•œ, ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ถ„์ด ์กด์žฌํ•˜๋ฉฐ, buffer๋งŒํผ ๊ณ„์† ์ฝ๋Š” ๊ฒƒ๋ณด๋‹ค๋Š”, ์ด๋ฏธ str์— ๊ฐœํ–‰์ด ์กด์žฌํ•˜๋ฉด ์ฝ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ

put_next_line์œผ๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. ์•„๋ฌด๋ž˜๋„ ์ด๋Ÿฐ์‹์œผ๋กœ ๋ฐ”๊พธ๋ ค๋ฉด ์ƒˆ๋กœ ๋‹ค ๋ฐ”๊ฟ”์•ผํ•  ๊ฒƒ ๊ฐ™์€๋ฐ,

์ถ”ํ›„์— ์‹œ๊ฐ„์ด ๋˜๋ฉด 'get_next_line_renewal_ver'๋กœ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด๋ด์•ผ๊ฒ ๋‹ค. (...)