C - <string.h> - strdup 구현하기, strjoin, split 함수 만들기

skyju·2022년 2월 17일
0

C

목록 보기
5/5

char *strdup(char *src)
strdup은 문자열 src를 복사하기 위해 메모리를 할당하고 (malloc 사용), 그곳에 src를 복사한다. 그리고 그 만들어진 문자열 포인터가 가르키는 곳을 반환한다.
과정
우선 src의 길이를 재고 null자리를 포함하여 동적할당 진행.
아무 것도 할당되지 않았다면 null을 return.
그 후 새로운 문자열에 복사 진행하고 null을 붙여준 뒤 반환하면 된다.

#include <stdlib.h>

char	*reproduce_strdup(char *src)
{
	char	*new_src;
	int		src_length;
	int		i;

	src_length = strlen(src);
	new_src = (char *)malloc(src_length + 1 * sizeof(char));
	if (!(new_src))
		return (0);
	i = 0;
	while (src[i])
	{
		new_src[i] = src[i];
		++i;
	}
	new_src[i] = '\0';
	return (new_src);
}

char *strjoin(int size, char **strs, char *sep)
매개 변수로 받은 문자열 배열을 size개수만큼 sep으로 이어서 하나의 문자열로 만든 뒤 반환한다.
과정
우선 malloc을 위해 size를 재는 함수를 작성한다.

int	malloc_size_cal(int size, char **strs, char *sep)
{
	int	strs_len;
	int	sep_len;
	int	i;

	strs_len = 0;
	sep_len = strlen(sep); //sep의 길이를 따로 재어놓음
	i = 0;
	if (size == 1)
		return (strlen(strs[0]) + 1); //size가 1일때 null만 붙여서 반환
	while (i < size - 1)
	{
		strs_len += strlen(strs[i]);
		strs_len += sep_len;
		++i;
	}
	strs_len += strlen(strs[i]);
	return (strs_len + 1); //null자리 고려하여 반환
}

계산한 size를 이용하여 동적할당을 진행하고 join한다.

char	*poduce_strjoin(int size, char **strs, char *sep)
{
	int		total_length;
	int		i;
	char	*str;

	if (size == 0)
	{
		str = (char *)malloc(1);
		str[0] = 0;
		return (str);
	}
	total_length = malloc_size_cal(size, strs, sep); //위 함수 활용
	str = (char *)malloc(total_length * sizeof(char));
	i = 0;
	if (*(str + i) != 0) //새로 동적할당 받은 주소에 쓰레기값이 있으면 밀기위해
		*(str + i) = 0;
	i = 0;
	while (i < (size - 1))
	{
		str = strcat(str, *(strs + i));
		str = strcat(str, sep);
		++i;
	}
	str = strcat(str, *(strs + i));
	return (str);
}

char **split(char *str, char *sep)
매개 변수로 받은 문자열을 seperator로 쪼갠다. 이때 문자열 sep 문자 하나 하나가 구분자 역할을 한다.
과정
우선 반환타입이 char **이므로, 즉 문자열의 주소를 담고 있는 배열을 반환한다고 생각할 수 있다. 따라서 문자열 포인터를 배열 개수만큼 동적할당해줘야 한다. 이때 배열의 개수는 쪼갤 단어의 개수 + 1(null)이다.

그럼 단어의 개수를 세는 함수 먼저 작성해보자.

int	is_sep(char c, char *sep)
{
	int	i = 0;
	while (sep[i])
	{
		if (sep[i] == c)
			return (1);
		++i;
	}
	return (0);
}

int	count_words(char *str, char *sep)
{
	int	i = 0;
	int	count = 1; //단어 개수는 1개부터 시작이므로

	while (str[i] != '\0')
	{
		if (is_sep(str[i], sep)
			&& !is_sep(str[i + 1], sep))
			++count;
		++i;
	}
	return (count);
}

계산한 size를 이용하여 동적할당을 진행한다.

char	**split(char *str, char *sep)
{
	char	**str_arr; //할당 후 반환할 변수
	int		arr_i;
	int		i;
	int		word_num; //malloc할 size

	word_num = count_words(str, sep);
	str_arr = (char **)malloc((word_num + 1) * sizeof(char *)); //null자리 하나 붙여서 char\*를 곱해줌
	arr_i = 0;
	i = 0;
	while (*(str + i))
	{
		while (*(str + i) && is_sep(*(str + i), sep))
			++i;
		if (*(str + i) && !is_sep(*(str + i), sep))
		{
			str_arr[arr_i] = make_str((str + i), sep);
			++arr_i;
		}
		while (*(str + i) && !is_sep(*(str + i), sep))
			++i; //다음 sep을 만날 때까지 index를 점프시킨다.
	}
	str_arr[arr_i] = 0;
	return (str_arr);
}

한 단어씩 string으로 만드는 make_str함수를 작성한다.
이때 make_str에는 split함수에 따라, 앞의 sep은 보내고 난 뒤의 str포인터가 들어온다.

char	make_str(char *str, char *sep)
{
	int		str_len;
	int		i;
	char	*new_str;

	str_len = 0;
	while (*(str + str_len) && !is_sep(str[str_len], sep))
		++str_len;
	new_str = (char *)malloc(str_len * sizeof(char) + 1);
	if (new_str == 0)
		return (0);
	i = 0;
	while (i < str_len)
	{
		new_str[i] = str[i];
		++i;
	}
	new_str[i] = 0;
	return (new_str);
}
profile
https://github.com/skyju

0개의 댓글