ft_substr
char *ft_substr(char const *s, unsigned int start, size_t len)
{
unsigned int l;
size_t slen;
char *str;
char *src;
if (s == NULL)
return (NULL);
src = (char *)s;
slen = ft_strlen(s);
if (slen < start || s[0] == '\0' || len == 0)
return (str = (char *)ft_calloc(1, 1));
l = (unsigned int)slen - start + 1;
if (l > (unsigned int)len)
l = (unsigned int)len + 1;
str = (char *)ft_calloc(l, sizeof(char));
if (str == NULL)
return (NULL);
ft_strlcpy(str, src + start, l);
return (str);
}
- 스트링
s안에서 start 지점부터 len 길이까지 있는 문자를 찾아 return 하는 함수다.
s의 길이를 구해 slen에 저장하고 slen이 start보다 긴 문자열인지 확인한다.
만약 start가 slen 밖이라면 빈 문자열을 return 한다.
l은 slen - start에 \0공간까지 추가하여 저장한다. 만약 l이 len보다 큰 공간을 갖고 있으면 len에 \0공간을 더한 길이로 대입한다.
str을 l길이로 malloc을 사용해 동적할당을 해준다.
ft_strlcpy함수를 통해 str안에 src의 포인터를 start만큼 옮겨서 l만큼 복사하고 return 한다.
ft_strjoin
char *ft_strjoin(char const *s1, char const *s2)
{
size_t len;
char *str;
int i;
int j;
i = 0;
j = 0;
if (s1 == NULL || s2 == NULL)
return (NULL);
len = ft_strlen(s1) + ft_strlen(s2);
str = (char *)malloc(sizeof(char) * (len + 1));
if (str == NULL)
return (NULL);
while (s1[i] != '\0')
{
str[i] = s1[i];
i++;
}
while (s2[j] != '\0')
str[i++] = s2[j++];
str[i] = '\0';
return (str);
}
s1문자열뒤에 s2를 이어 붙이는 함수를 구현 하였다.
len에서 s1과 s2의 문자열 길이를 더해 구해주었다.
len에 \0자리를 더하여 malloc으로 동적할당을 해주었다.
- while을 이용하여
s1의 문자열을 str에 복사하였다.
str의 i를 이어서 i++하면서 s2는 j를 j++하여 이어 붙였다.
- 마지막 자리에
\0을 추가하고 return을 하였다.
ft_strtrim
char *ft_strtrim(char const *s1, char const *set)
{
char *str;
char *ps1;
int f;
int r;
int str_len;
if (s1 == NULL || set == NULL)
return (0);
r = (int)ft_strlen(s1);
f = 0;
r -= 1;
while (ft_strchr(set, s1[f]))
f++;
while (ft_strchr(set, s1[r]) && r != -1)
r--;
str_len = r - f + 2;
if (str_len < 1)
return (str = (char *)ft_calloc(1, 1));
str = (char *)ft_calloc(str_len, sizeof(char));
if (str == NULL)
return (NULL);
ps1 = (char *)s1;
ft_strlcpy(str, ps1 + f, str_len);
return (str);
}
s1문자열 양 끝에서 set에 포함된 문자를 찾아 제거하여 반환하는 함수를 구현했다.
- 변수
f와 r에 각각 s1문자열의 시작과 끝 인덱스를 저장했다.
- while문의 조건을
ft_strchr로 set문자열과 s1[f(r)] 값을 비교하여 일치하지 않는데까지 찾았다.
r은 음수 인덱스 접근을 막기 위해 && r != -1의 조건을 추가하였다.
r이 f보다 적어지는, set의 문자로만 이루어진 문자열이면 빈 문자열을 return 했다.
set 문자들을 제거된 길이대로 calloc으로 동적할당을 해주고 strlcpy를 통해 자른 문자를 복사했다.
이 때, ps1은 s1의 포인터와 동일하고 f만큼 포인터를 이동하여 set의 문자를 건너뛰어 복사했다.
set문자들을 잘라내고 복사한 문자열을 return 했다.
ft_split
static int str_count(char const *s, char c)
{
int i;
int count;
int flag;
i = 0;
count = 0;
flag = 0;
while (s[i] != '\0')
{
if (!(s[i] == c) && flag == 0)
{
flag = 1;
count++;
}
else if (s[i] == c)
flag = 0;
i++;
}
return (count);
}
static void free_str(char **newstr)
{
int i;
i = 0;
while (newstr[i])
free(newstr[i++]);
free(newstr);
}
static int str_plus(char **newstr, char const *s, char c, int cnt)
{
char *str;
int n;
int len;
n = 0;
str = (char *)s;
while (n < cnt)
{
len = 0;
while (*str == c)
str++;
while (str[len] != c && str[len] != '\0')
len++;
newstr[n] = (char *)malloc(sizeof(char) * (len + 1));
if (!newstr[n])
{
free_str(newstr);
return (-1);
}
ft_strlcpy(newstr[n++], str, len + 1);
str += len;
}
return (1);
}
char **ft_split(char const *s, char c)
{
char **newstr;
int cnt;
if (s == NULL)
return (NULL);
cnt = str_count(s, c);
newstr = (char **)malloc(sizeof(char *) * (cnt + 1));
if (!newstr)
return (NULL);
newstr[cnt] = NULL;
if (str_plus(newstr, s, c, cnt) == -1)
return (NULL);
return (newstr);
}
ft_split함수는 s문자열에서 c를 구분 문자로 2차원 배열로 나누어 주는 함수다.
- 먼저
s문자열 안에 c로 구분된 문자열이 몇개가 있는지 str_count 함수를 이용하여 cnt에 저장 하였다.
str_count 함수는 flag를 가지고 c를 만나지 않을 때 count를 올리고 flag를 바꿔 c 만날때까지 i++만 했다. 이 후 c를 만나면 flag를 0으로 바꿔 다음 c가 아닌 문자를 만나면 count하는 식으로 문자열을 찾았다.
cnt를 가지고 새로운 문자열 **newstr에 malloc으로 동적할당 하였다.
newstr에 str_plus 함수를 이용하여 문자열을 분리하여 넣었다.
str_plus함수는 n을 0으로 초기화하여 cnt보다 작을 때까지 while을 사용하는데 먼저, c 문자가 나오면 포인터를 증가시켜 건너뛰었다. c가 아닌 문자열은 len인덱스를 c문자열을 만날 때까지 증가했다. len이 구해지면 newstr[n]에 malloc으로 동적할당하여 strlcpy로 len 만큼 문자열을 넣었다. n++, str += len으로 n으로 2차원 배열의 다음 인덱스를, str의 포인터를 len만큼 증가시켜 다음 문자열을 찾았다.
만약 malloc이 실패 하면 지금까지 동적할당되었던 메모리를 free 해줘야 한다. 이 작업을 위해 free_str함수를 만들었다. while을 이용하여 newstr[i]의 인덱스마다 free를 해주고 newstr도 free를 해줌으로써 전부 free를 해주었다.
str plus함수를 사용 해서 malloc이 실패하면 -1이 리턴이 되는데 이럴 경우 ft_split함수는 NULL을 return하게 했다. 모든 문자열이 분리되어 저장되면 1이 리턴이 되는데 이 경우 newstr을 최종 return 하였다.
ft_itoa
static int nbrlen(int n)
{
int len;
len = 0;
if (n == -2147483648)
return (11);
else if (n < 0)
{
n *= -1;
len++;
}
while (n > 9)
{
n /= 10;
len++;
}
len++;
return (len);
}
char *ft_itoa(int n)
{
char *i;
int len;
len = nbrlen(n);
i = (char *)malloc(sizeof(char) * (len + 1));
if (i == NULL)
return (NULL);
i[len--] = '\0';
if (n == -2147483648)
return (ft_memcpy(i, "-2147483648", len + 1));
else if (n < 0)
{
n *= -1;
i[0] = '-';
}
while (len > 0 && n > 9)
{
i[len] = n % 10 + '0';
n /= 10;
len --;
}
i[len] = n % 10 + '0';
return (i);
}
- int to char로 숫자를 문자열로 표시하는
ft_itoa함수를 구현하였다.
nbr_len함수로 숫자의 자릿수를 확인하였다.
nbr_len함수는 먼저 음수 최솟값인지 확인하여 맞으면 11을 리턴 하였다.
int형은 -2147483648~2147483647로 부호를 제외하면 음수가 1이 더 많아 음수를 양수로 변경 시 오버플로우가 발생한다.
입력받은 int n이 음수면 -1을 곱해줘 양수를 만들고 이 후 10으로 계속 나누어 len++을 해 자리수를 구해 리턴한다.
len이 구해지면 char *i에 malloc으로 동적할당을 해준다.
- 최소 음수값이면
ft_memcpy함수를 사용하여 값을 그대로 넣어준다.
- 음수면 인덱스 0번에
-를 넣고 양수로 바꾸어 아래 while문을 진행한다.
- while문으로
n을 10으로 나누어 나눈 나머지에 0을 더해 i[len]에 저장한다. char에서 아스키코드대로 표시되어 0을 더해 아스키 코드의 0~9까지 표시 범위로 올려준다.
- 일의자리까지 모두
n을 나누어 저장하고 리턴한다.
ft_strmapi
char *ft_strmapi(char const *s, char (*f)(unsigned int, char))
{
char *ps;
int i;
int len;
if (s == NULL || f == NULL)
return (NULL);
len = ft_strlen(s);
i = 0;
ps = (char *)malloc(sizeof(char) * len + 1);
if (ps == NULL)
return (NULL);
while (i < len)
{
ps[i] = (*f)(i, s[i]);
i++;
}
ps[i] = '\0';
return (ps);
}
*s에 (*f)(unsigned int, char)포인터 함수를 적용하여 리턴하는 ft_strmapi함수를 구현했다.
s의 길이를 ft_strlen으로 구하여 ps포인터변수에 malloc으로 동적할당했다.
- while문을 통해
ps[i] = (*f)(i, s[i])로 i 인덱스를 맞춰 모든 값이 함수가 적용되어 저장되게 하였다.
ft_striteri
void ft_striteri(char *s, void (*f)(unsigned int, char *))
{
unsigned int i;
if (!s || !f)
return ;
i = 0;
while (s[i])
{
f(i, &s[i]);
i++;
}
}
ft_striteri함수는 입력받은 s에 포인터 함수를 적용하여 저장하는 함수이다.
- while문을 통해 함수가 적용되게 구현하였다.
ft_putchar_fd
void ft_putchar_fd(char c, int fd)
{
write(fd, &c, 1);
}
- 이 함수는
putchar함수에서 파일디스크립터(fd)를 입력받은 fd로 write 해주는 함수이다.
- write 구성 중 파일디스크럽터 입력에 Standard output인 1이 아닌 fd를 넣었다.
ft_putstr_fd
void ft_putstr_fd(char *s, int fd)
{
int i;
if (s == NULL)
return ;
i = 0;
while (s[i] != '\0')
{
ft_putchar_fd(s[i], fd);
i++;
}
}
- 입력받은
s문자열을 출력하는 함수로 while문으로 문자열이 \0을 만날 때 까지 ft_putchar_fd 함수로 fd를 입력받은 fd로하여 문자열을 출력하였다.
ft_putendl_fd
void ft_putendl_fd(char *s, int fd)
{
if (s == NULL)
return ;
ft_putstr_fd(s, fd);
ft_putchar_fd('\n', fd);
}
ft_putendl_fd 함수는 입력받은 문자열을 fd를 지정하여 출력하고 마지막에 줄바꿈을 하는 함수이다.
ft_putstr_fd를 통해 문자열을 출력하고, ft_putchar_fd에서 \n을 출력하여 줄바꿈을 해주었다.
ft_putnbr_fd
void ft_putnbr_fd(int n, int fd)
{
if (n == -2147483648)
write(fd, "-2147483648", 11);
else if (n < 0)
{
n *= -1;
ft_putchar_fd('-', fd);
}
if (n >= 0)
{
if (n >= 10)
{
ft_putnbr_fd(n / 10, fd);
ft_putnbr_fd(n % 10, fd);
}
else
ft_putchar_fd(n % 10 + '0', fd);
}
}
int n을 write로 출력하는 함수이다.
- 최소 음수값을 만나면 위에
ft_itoa에서 설명한대로 예외적으로 먼저 출력하였다.
- 음수면
-를 먼저 출력하고 양수로 바꿔 아래 재귀를 사용하여 한자리씩 출력하였다.
- 모든 출력함수는 fd를 지정하여 출력하였다.