[42libft] part2 총 정리

퐁퐁이·2021년 12월 24일
0

42SEOUL

목록 보기
5/12
post-thumbnail

[Libft] part2

1) ft_substr

: malloc()으로 메모리를 할당한 후, sstart로부터 len 개 까지의 부분 문자열을 저장하여 반환

  • 오류 발생-수정 전
    char	*ft_substr(char const *s, unsigned int start, size_t len)
    {
    	size_t	i;
    	size_t	j;
    	char *	sub;
    
    	i = 0;
    	j = 0;
    	if (!s)
    		return (NULL);
    	if (!(sub = (char*)malloc(sizeof(char) * (len + 1))))
    		return (NULL);
    	while (s[i])
    	{
    		if (i >= start && j < len)
    		{
    			sub[j] = s[i];
    			j++;
    		}
    		i++;
    	}
    	sub[j] = '\0';
    	return (sub);
    }
    libftTester 오류 발생🤦‍♂️ 'start가 문자열 s의 길이보다 크거나 같을 때만 잘 처리해주면 된다. ft_strdup을 사용해서 빈 문자열을 반환해줬다.' 라는 글을 보고 수정을 해보았으나
    if (start >= ft_strlen(s))
    		return (ft_strdup(""));
    이러한 오류 발생 해결 size_t s_len; 을 선언해준 후
    if (start >= s_len)
    		return (ft_strdup(""));
    그래도 여전히 .. 해결 len 크기가 클 경우 낭비돼서 그럼
    if (len >= slen - start)
    		len = slen - start;
    이거 추가해주면 끝 !!
char	*ft_substr(char const *s, unsigned int start, size_t len)
{
	size_t	i;
	size_t	s_len;
	char	*sub;

	i = 0;
	if (!s)
		return (NULL);
	s_len = ft_strlen(s);
	if (start >= s_len)
		return (ft_strdup(""));
	if (len >= s_len - start)
		len = s_len - start;
	if (!(sub = (char*)malloc(sizeof(char) * (len + 1))))
		return (NULL);
	while (i < len)
		sub[i++] = s[start++];
	sub[i] = '\0';
	return (sub);
}

✏️ snull이면 null이 리턴

✏️ 할당에 실패하면 null을 리턴

if (start >= s_len)
		return (ft_strdup(""));

✏️ len(s) < start일 때 빈 문자열 반환 (null 리턴이 아닌 빈 문자열!!)

2) ft_strjoin

: malloc()으로 새로운 문자열을 할당하고 반환

새로운 문자열은 문자열 s1s2가 연결된 형태

char	*ft_strjoin(char const *s1, char const *s2)
{
	char	*res;
	size_t	len1;
	size_t	len2;

	if (!s1 && !s2)
		return (0);
	else if (!s1 || !s2)
		return (!s1 ? (char *)s2 : (char *)s1);
	len1 = ft_strlen(s1);
	len2 = ft_strlen(s2);
	res = (char *)malloc(sizeof(char) * (len1 + len2 + 1));
	if (!res)
		return (0);
	ft_memcpy(res, s1, len1);
	ft_memcpy(res + len1, s2, len2);
	res[len1 + len2] = 0;
	return (res);
}

3) ft_strtrim

: 문자열 s1의 앞에서 부터 탐색하면서 문자열 set에 포함된 문자가 있다면 제거

같은 방식으로 문자열 s1의 뒤에서부터 탐색 하면서 문자열 set에 포함된 문자가 있다면 제거

그 결과를 malloc으로 할당한 뒤 제거

  • 오류 발생-수정 전
    int		ft_check_set(char c, char const *set)
    {
    	size_t i;
    
    	i = 0;
    	while (set[i])
    	{
    		if (set[i] == c)
    			return (1);
    		i++;
    	}
    	return (0);
    }
    
    char	*ft_strtrim(char const *s1, char const *set)
    {
    	size_t	start;
    	size_t	end;
    	size_t	i;
    	char	*res;
    
    	if (!s1 || !set)
    		return ((char *)s1);
    	start = 0;
    	end = ft_strlen(s1) - 1;
    	while (s1[start] && ft_check_set(s1[start], set))
    		start++;
    	while (end > start && ft_check_set(s1[end], set))
    		end--;
    	res = (char *)malloc(sizeof(char) * (end - start + 2));
    	if (!res)
    		return (0);
    	i = 0;
    	while (start <= end)
    	{
    		res[i] = s1[start];
    		i++;
    		start++;
    	}
    	res[i] = 0;
    	return (res);
    }
    오류
    ft_strtrim:    [OK] [OK] [OK] [OK] [CRASH] [OK] [OK] [OK] [OK] [🛡 ]
    [crash]: your strtrim does not work with empty input
    내가 생각하는 오류 원인
    end = ft_strlen(s1) - 1; //s1의 길이가 0이라면 underflow가 발생 할 수 있을 것(size_t)
    수정
    char	*ft_strtrim(char const *s1, char const *set)
    {
    	size_t	start;
    	size_t	end;
    	size_t	i;
    	char	*res;
    
    	if (!s1 || !set)
    		return ((char *)s1);
    	start = 0;
    	end = ft_strlen(s1);
    	while (s1[start] && ft_check_set(s1[start], set))
    		start++;
    	while (end > start && ft_check_set(s1[end - 1], set))
    		end--;
    	res = (char *)malloc(sizeof(char) * (end - start + 1));
    	if (!res)
    		return (0);
    	i = 0;
    	while (start < end)
    	{
    		res[i] = s1[start];
    		i++;
    		start++;
    	}
    	res[i] = '\0';
    	return (res);
    }
int		ft_check_set(char c, char const *set)
{
	size_t i;

	i = 0;
	while (set[i])
	{
		if (set[i] == c)
			return (1);
		i++;
	}
	return (0);
}

char	*ft_strtrim(char const *s1, char const *set)
{
	size_t	start;
	size_t	end;
	size_t	i;
	char	*res;

	if (!s1 || !set)
		return ((char *)s1);
	start = 0;
	end = ft_strlen(s1);
	while (s1[start] && ft_check_set(s1[start], set))
		start++;
	while (end > start && ft_check_set(s1[end - 1], set))
		end--;
	res = (char *)malloc(sizeof(char) * (end - start + 1));
	if (!res)
		return (0);
	i = 0;
	while (start < end)
	{
		res[i] = s1[start];
		i++;
		start++;
	}
	res[i] = '\0';
	return (res);
}

✏️ s1null이면 null 리턴

✏️ setnull이면 s1을 그대로 리턴

✏️ 실패 시 null을 반환

4) ft_split

: 문자 c를 기준으로 문자열 s를 분할하여 새로운 문자열 배열로 반환

새로운 문자열 배열은 null로 끝나야 함

static char            **ft_freeall(char **s)
{
    unsigned int    i;

    i = 0;
    while (s[i] != NULL)
    {
        free(s[i]);
        i++;
    }
    free(s);
    return (NULL);
}

static size_t        ft_wordcnt(const char *s, char d)
{
    size_t            cnt;
    size_t            i;

    cnt = 0;
    i = 0;
    while (s[i])
    {
        if (s[i] != d)
        {
            cnt++;
            while (s[i] && s[i] != d)
                i++;
        }
        else
            i++;
    }
    return (cnt);
}

static char            *ft_worddup(const char *s, char d)
{
    size_t            len;
    char            *ptr;

    len = 0;
    while (s[len] && s[len] != d)
        len++;
    if (!(ptr = (char *)ft_calloc(len + 1, sizeof(char))))
        return (NULL);
    ft_strlcpy(ptr, s, len + 1);
    return (ptr);
}

char                **ft_split(const char *s, char d)
{
    char            **ptr;
    size_t            len;
    size_t            i;
    size_t            j;

    if (!s)
        return (NULL);
    len = ft_wordcnt(s, d);
    if (!(ptr = (char **)ft_calloc(len + 1, sizeof(char *))))
        return (NULL);
    i = 0;
    j = 0;
    while (i < len && s[j])
    {
        if (s[j] != d)
        {
            if (!(ptr[i++] = ft_worddup(&(s[j]), d)))
                return (ft_freeall(ptr));
            while (s[j] && s[j] != d)
                j++;
        }
        else
            j++;
    }
    return (ptr);
}

✏️ 분할된 문자열 배열 반환

✏️ 할당 실패 시 NULL

-fsanitize=address -g3 이걸로 테스트 해보라네

5) ft_itoa

: 정수를 문자열로 바꾸어 리턴(음수도 처리)

size_t		ft_nb_len(int nb)
{
	int len;

	len = 0;
	if (nb <= 0)
		len++;
	while (nb)
	{
		len++;
		nb = nb / 10;
	}
	return (len);
}

char		*ft_itoa(int n)
{
	int		len;
	char	*str;
	long	nb;

	len = ft_nb_len(n);
	nb = n;
	if (!(str = malloc(sizeof(char) * len + 1)))
		return (NULL);
	if (nb < 0)
	{
		str[0] = '-';
		nb = -nb;
	}
	if (nb == 0)
		str[0] = '0';
	str[len--] = '\0';
	while (nb)
	{
		str[len] = nb % 10 + '0';
		len--;
		nb = nb / 10;
	}
	return (str);
}

6) ft_strmapi

: 문자열 s의 각 문자에 f 함수를 연속적으로 적용시킨 새로운 문자열 만들기

char	*ft_strmapi(char const *s, char (*f)(unsigned int, char))
{
	char	*res;
	size_t	i;
	size_t	len;

	if (!s)
		return (0);
	len = ft_strlen(s);
	if (!(res = (char *)malloc(sizeof(char) * (len + 1))))
		return (0);
	i = 0;
	while (s[i])
	{
		res[i] = (*f)(i, s[i]);
		i++;
	}
	res[i] = 0;
	return (res);
}

✏️ s의 길이를 재서 s길이+1 만큼 resmalloc

✏️ (*f)(i, s[i]) 한 결과들을 포인터 배열에 담아서 리턴

✏️ 할당 실패 시 NULL

7) ft_putchar_fd

: 문자 c를 주어진 파일디스크립터로 출력

void	ft_putchar_fd(char c, int fd)
{
	if (fd < 0)
			return ;
	write(fd, &c, 1);
}
  • 파일 디스크립터는 0이 아닌 정수값(Non-negative Integer)을 갖는다.
  • 프로세스가 실행 중에 파일을 Open하면 커널은 해당 프로세스의 파일 디스크립터 숫자 중 사용하지 않는 가장 작은 값을 할당해준다. 그 다음 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, 파일 디스크립터(FD)값을 이용해서 파일을 지칭할 수 있다.
  • 기본적으로 할당되는 파일 디스크럽터 0 : Standard input 1 : Standard Output 2 : Standard Error
  • 출처 https://velog.io/@jungjaedev/ftputcharfd

8) ft_putstr_fd

: 문자열 s를 주어진 파일디스크립터로 출력

void	ft_putstr_fd(char *s, int fd)
{
    if (!s || fd < 0)
        return;
    write(fd, s, ft_strlen(s));
}

9) ft_putendl_fd

: 문자열 s를 주어진 파일디스크립터로 출력하고 newline으로 끝내기

void	ft_putendl_fd(char *s, int fd)
{
    if (!s || fd < 0)
        return;
    write(fd, s, ft_strlen(s));
    write(fd, "\n", 1);
}

10) ft_putnbr_fd

: 정수 n을 주어진 파일디스크립터로 출력

void	ft_putnbr_fd(int n, int fd)
{
    unsigned int nbr;

    nbr = (n < 0) ? -n : n;
    if (n < 0)
        ft_putchar_fd('-', fd);
    if (nbr >= 10)
        ft_putnbr_fd(nbr / 10, fd);
    ft_putchar_fd((nbr % 10) + '0', fd);
}
profile
코딩하는 에디

0개의 댓글