[C] Libft - Part2_Additional functions

Austin·2024년 10월 15일

42-Cursus

목록 보기
2/24

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에 저장하고 slenstart보다 긴 문자열인지 확인한다.
    만약 startslen 밖이라면 빈 문자열을 return 한다.
  • lslen - start\0공간까지 추가하여 저장한다. 만약 llen보다 큰 공간을 갖고 있으면 len\0공간을 더한 길이로 대입한다.
  • strl길이로 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에서 s1s2의 문자열 길이를 더해 구해주었다.
  • len\0자리를 더하여 malloc으로 동적할당을 해주었다.
  • while을 이용하여 s1의 문자열을 str에 복사하였다.
    stri를 이어서 i++하면서 s2jj++하여 이어 붙였다.
  • 마지막 자리에 \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에 포함된 문자를 찾아 제거하여 반환하는 함수를 구현했다.
  • 변수 fr에 각각 s1문자열의 시작과 끝 인덱스를 저장했다.
  • while문의 조건을 ft_strchrset문자열과 s1[f(r)] 값을 비교하여 일치하지 않는데까지 찾았다.
  • r은 음수 인덱스 접근을 막기 위해 && r != -1의 조건을 추가하였다.
  • rf보다 적어지는, set의 문자로만 이루어진 문자열이면 빈 문자열을 return 했다.
  • set 문자들을 제거된 길이대로 calloc으로 동적할당을 해주고 strlcpy를 통해 자른 문자를 복사했다.
    이 때, ps1s1의 포인터와 동일하고 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으로 동적할당 하였다.
  • newstrstr_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를 지정하여 출력하였다.

0개의 댓글