[libft] ft_split
split?
//원 함수 없음
char **ft_split(char const *s, char c);
구현해야할 함수 기능
: Allocates (with malloc(3)) and returns an array of strings obtained by splitting ’s’ using the character ’c’ as a delimiter. The array must be ended by a NULL pointer.
해석 및 부연설명
: 문자열 s를 문자 c를 기준으로 쪼갠 후 새롭게 할당한 문자열 배열에 집어넣어 반환하고, 이때 각 배열은 반드시 NULL
로 끝나야한다.
ex)
char **array;
char str[] = "abcde?fg?hijkl?mnop";
char c = '?';
int i = 0;
array = ft_split(str, c);
while(array[i])
printf("%s\n", array[i++]);
코드 실행 결과
abcde
fg
hijkl
mnop
문자열 str이 문자 c에 저장되어있는 ‘?’을 기준으로 잘 나뉘어진 것을 확인할 수 있다.
의문점 및 생각해볼점
메모리 누수 방지
이전까지의 함수들은 새롭게 할당하는 메모리가 하나 뿐이었고, 해당 메모리에 할당을 실패했을 경우 NULL을 반환하면 아무런 문제가 생기지 않았다.
하지만 split 함수의 경우 기능상 여러 개의 메모리를 할당하게 되어있고, 그 메모리들 중 하나라도 문제가 생길경우 전체적으로 잘못되었다고 판단하여 작동을 멈출 필요가 있다.
따라서 함수가 비정상적으로 작동 중지될 때는 앞서 정상적으로 할당된 메모리를 free해주는 과정을 거치지 않으면 메모리 누수가 발생할 수 있으니 주의해야한다.
ft_split 구현
static void free_str(char **splitstr)
{
int i;
i = 0;
while (!splitstr[i])
free(splitstr[i++]);
free(splitstr);
}
static int word_count(char const *str, char c)
{
int count;
count = 0;
while (*str)
{
if (*str == c)
str++;
else
{
count++;
while (*str != c && *str)
str++;
}
}
return (count);
}
static int plus_word(char const *str, char c, char **splitstr, int i)
{
int len;
while (*str)
{
if (*str == c)
str++;
else
{
len = 0;
while (*str != c && *str)
{
str++;
len++;
}
splitstr[i] = (char *)malloc((len + 1) * sizeof(char));
if (!splitstr[i])
{
free_str(splitstr);
return (-1);
}
ft_strlcpy((char *)splitstr[i++], (char *)str - len, len + 1);
}
}
splitstr[i] = 0;
return (1);
}
char **ft_split(char const *str, char c)
{
char **splitstr;
splitstr = (char **)malloc((word_count(str, c) + 1) * sizeof(char *));
if (!splitstr)
return (NULL);
if ((plus_word(str, c, splitstr, 0)) == -1)
return (NULL);
return (splitstr);
}
word_count
함수를 통해 문자열을 자르고 난 후 만들어지는 1차원배열의 갯수를 센 뒤 마지막에 NULL
을 넣어줄 공간까지 생각해 이차원배열 메모리를 할당한다.
그 메모리 속 일차원배열 각각에 plus_word
함수를 통해 문자열을 저장하고, 만약 각 문자열 저장시 메모리 할당 과정에 문제가 생기면 free_str
함수에서 모든 메모리를 free
한 후 -1을 반환해 문제가 생겼다는 것을 알려준다.
문자열을 자르는 과정은 다음과 같다.
- 우선 문자 c에 해당하는 문자가 있는지, 주어진 문자열의 처음부터 탐색한다.
- 만약 c가 있다면 그냥 넘긴다.
- c가 아니라면 그 부분부터 새롭게 잘라내어 저장해야하는 문자열이라고 판단해 길이를 센다. 그리고 다시 문자열을 읽어나가는데, 이번엔 c가 아닌 문자열이 나올경우 계속 넘긴다.
- 그러다 다시 c가 나올경우 길이세기를 멈추고 그 길이값을 바탕으로 문자열을 저장한다.
- 위 과정을 주어진 문자열이 끝날때까지 반복한다.