[42libft] part1 총 정리

퐁퐁이·2021년 12월 24일
0

42SEOUL

목록 보기
4/12
post-thumbnail

[Libft] part1

blackhole 1st step

1-1

1) ft_memset

: ptr 위치부터 num개의 바이트 만큼 value로 초기화

void	*ft_memset(void *ptr, int value, size_t num)
{
	unsigned char	*new;
	unsigned char	src;
	size_t			i;

	new = ptr;
	src = value;
	i = 0;
	while (i++ < num)
		*new++ = src;
	return (ptr);
}

✏️ 포인터, 설정할 값, 크기

✏️ 원하는 특정 값으로 메모리 세팅 - 메모리의 내용을 모두 0으로 만들 때 주로 사용
✏️ value: 인자가 int로 전달되지만 함수 내부적으로 unsigned char(1 바이트)로 형변환되어 사용

✏️ memset 함수에 설정할 크기를 지정할 때 보통 숫자 대신 sizeof를 사용

  • +)
    char *cPtr = malloc(sizeof(char));    // char의 크기 1바이트만큼 동적 메모리 할당
    
    memset(cPtr, 0, sizeof(char));    // char의 크기 1바이트만큼 0으로 설정(올바른 방법)
    memset(cPtr, 0, sizeof(char *));  // 32비트: char 포인터의 크기 4바이트만큼 0으로 설정(잘못된 방법)
                                      // 64비트: char 포인터의 크기 8바이트만큼 0으로 설정(잘못된 방법)
    free(cPtr); 

2) ft_bzero

: s의 위치부터, n 개의 바이트 만큼 0으로 초기화

void	ft_bzero(void *s, size_t n)
{
	unsigned char	*dst;
	size_t			i;

	dst = s;
	i = 0;
	while (i++ < n)
		*dst++ = 0;
} 

✏️ 메모리를 0으로 세팅

3) ft_memcpy

: src가 가리키는 곳 부터 n바이트 만큼을 dst가 가리키는 곳에 복사

void	*ft_memcpy(void *dst, const void *src, size_t n)
{
	unsigned char	*new_dest;
	unsigned char	*new_src;
	size_t			i;

	if (!dst && !src)
		return (0);
	new_dest = dst;
	new_src = (unsigned char *)src;
	i = 0;
	while (i++ < n)
		*new_dest++ = *new_src++;
	return (dst);
}

✏️ srcnull 문자를 검사하지 않음 → 언제나 정확히 n 바이트 만큼 복사

4) ft_memccpy

: n바이트의 데이터를 dst에 복제할 때, 데이터에서 문자 c를 만나면 c까지 복제하고 복제 중단

  • 오류 발생-수정 전
    void	*ft_memccpy(void *dst, const void *src, int c, size_t n)
    {
    	size_t	i;
    	int		flag;
    
    	i = 0;
    	flag = 0;
    	while (i < n && ((unsigned char *)src)[i] && !flag)
    	{
    		flag = ((unsigned char *)src)[i] == ((unsigned char)c) ? 1 : 0;
    		i++;
    	}
    	if (flag)
    	{
    		ft_memcpy(dst, src, i);
    		return (dst + i);
    	}
    	else
    	{
    		ft_memcpy(dst, src, n);
    		return (0);
    	}
    }
    
    ft_memccpy : 1.OK 2.OK 3.OK 4.KO 5.OK 6.OK 7.OK LibftTest에서 오류 떴다..
void	*ft_memccpy(void *dst, const void *src, int c, size_t n)
{
	char			*ptr1;
	unsigned char	*ptr2;
	size_t			i;

	if (!dst && !src)
		return (0);
	ptr1 = dst;
	ptr2 = (unsigned char *)src;
	i = 0;
	while (i < n)
	{
		ptr1[i] = ptr2[i];
		if (ptr2[i] == (unsigned char)c)
			return (dst + i + 1);
		i++;
	}
	return (NULL);
}

✏️ 복제된 dst에서 복제가 끝난 다음 번지를 return

✏️ n 바이트 만큼 중 c를 찾지 못하면 NULL 값 반환

5) ft_memmove

: src메모리 영역에서 dest 메모리 영역으로 n 바이트 만큼 복사한다. 이 때, src 배열은 srcdest의 메모리 영역과 겹치지 않는 메모리 영역부터 먼저 복사한다.

void	*ft_memmove(void *dst, const void *src, size_t n)
{
	unsigned char *s;
	unsigned char *d;

	if (dst == src || !n)
		return (dst);
	s = (unsigned char *)src;
	d = (unsigned char *)dst;
	if (dst < src)
	{
		while (n--)
			*d++ = *s++;
	}
	else
	{
		while (n--)
			*(d + n) = *(s + n);
	}
	return (dst);
}

✏️ 복사하는 기능을 가진 함수

✏️ memcpy와의 차이점:

memcpy()는 버퍼를 거치지 않고 (빠르다는 장점)

memmove()는 버퍼를 이용한다. (안전하다는 장점 - 메모리가 겹치지 않음)

위 코드는 버퍼를 쓰지 않음 ㅎ

✏️ dst > src인 경우:

src 시작 주소가 dest 시작 주소보다 앞에 있을 때, 오버랩의 가능성 → 뒤에서 부터 한 바이트씩 복사

6) ft_memchr

: ptr이 가리키는 메모리 처음부터 n 바이트 까지 탐색하면서 처음으로 c와 일치하는 값의 주소 리턴

void	*ft_memchr(const void *s, int c, size_t n)
{
	unsigned char *ptr;

	ptr = (unsigned char *)s;
	while (n--)
	{
		if (*ptr != ((unsigned char)c))
			ptr++;
		else
			return (ptr);
	}
	return 0;
}

✏️ c는 int로 값이 전달되나, 한 바이트씩 비교하기 때문에 unsigned char로 변환되어 사용

✏️ 값을 찾지 못한다면 NULL 을 리턴한다.

7) ft_memcmp

: ptr1 이 가리키는 처음 num 바이트의 데이터와 ptr2 가 가리키는 처음 num 바이트의 데이터를 비교한다.

int		ft_memcmp(const void *s1, const void *s2, size_t n)
{
	const unsigned char *ptr1;
	const unsigned char *ptr2;

	if (!n)
		return (0);
	ptr1 = (unsigned char *)s1;
	ptr2 = (unsigned char *)s2;
	while (n--)
	{
		if (*ptr1 != *ptr2)
			return (*ptr1 - *ptr2);
		ptr1++;
		ptr2++;
	}
	return (0);
}

✏️ 두 개의 메모리 블록을 비교

✏️ 두 메모리 블록이 정확히 같다면 → 0 을 리턴

✏️ 두 메모리 블록이 다를 경우 → 그 값이 ptr1 이 더 크면 0 보다 큰 값을 아니면 0 보다 작은 값을 리턴

(ptr1과 ptr2 가 가리키는 메모리 블록에서 앞에서 부터 처음으로 다른 바이트를 살펴 보는데, 그 바이트를 unsigned char 로 해석 하였을 때)

✏️ strncmp와의 차이점

-memcmp : 두 문자열 중 하나가 끝나더라도 상관없이 서로 다른 값이 나오거나, n개가 될 때 까지 비교 수행

-strncmp : s1과 s2가 모두 NULL 값이 나오면 남은 카운트에 관계없이 0 반환

-예) a[20] "abcde" , b[20] "abcde" 가 있을 때 memcmp는 쓰레기 값까지 비교를 하게된다.

8) ft_strlen

: 문자열의 길이를 구함

size_t	ft_strlen(const char *str)
{
	size_t i;

	i = 0;
	while (str[i] != '\0')
		i++;
	return (i);
}

9) ft_strlcpy

: srcdscnull을 포함해서 (size-1)개 까지 복사 후 마지막에 null을 붙여줌

size_t ft_strlcpy(char *dst, const char *src, unsigned int size)
{
	size_t	src_len;
	size_t	i;

	if (!dst || !src)
		return (0);
	src_len = 0;
	while (src[src_len] != '\0')
	{
		src_len++;
	}
	if (size == 0)
	{
		return (src_len);
	}
	i = 0;
	while (src[i] != '\0' && i < (size - 1))
	{
		dst[i] = src[i];
		i++;
	}
	dst[i] = '\0';
	return (src_len);
}

✏️ null 을 보장하여 문자열 복사

✏️ src의 길이가 size보다 작으면 → 부족한 부분을 null로 채움

추가해야함 [💥 ]

if (!dst || !src)
		return (0);

10) ft_strlcat

: dst의 길이를 포함해서 새로운 dst의 길이를 설정하고 (size)

빈 공간 만큼 src를 이어붙인다. 마지막에 null을 보장하여 넣어준다.

size_t ft_strlcat(char *dst, const char *src, unsigned int size)
{
	size_t	i;
	size_t	dest_len;
	size_t	src_len;

	dest_len = ft_strlen(dst);
	src_len = ft_strlen(src);
	i = 0;
	if (size < dest_len + 1)
		return (size + src_len);
	if (size > dest_len + 1)
	{
		while (src[i] != '\0' && dest_len + 1 + i < size)
		{
			dst[dest_len + i] = src[i];
			i++;
		}
	}
	dst[dest_len + i] = '\0';
	return (dest_len + src_len);
}

✏️ null 을 보장하여 문자열 이어붙이기

✏️ size = dst 길이 + 붙일 데이터 길이 + NULL

✏️ 리턴값

size < strlen(dst)  : strlen(src) + size

size > strlen(dst)  : strlen(src) + strlen(dst)

11) ft_strchr

: 문자열 s에서 첫 번째로 찾은 문자 c의 포인터를 리턴

char	*ft_strchr(const char *str, int c)
{
	char	find;
	int		i;

	i = 0;
	find = (unsigned char)c;
	while (str[i] != '\0')
	{
		if (str[i] == find)
			return ((char *)str + i);
		i++;
	}
	if (str[i] == find)
		return ((char *)str + i);
	return (0);
}

✏️ 문자열에서 특정한 문자가 가장 먼저 나타나는 곳의 위치 리턴

✏️ cint 형태로 형변환 되어서 전달되지만 함수 내부적으로는 다시 char 형태로 처리됨

✏️ 만일 문자가 없다면 NULL 포인터 리턴

1-2

12) ft_strnstr

: big의 처음부터 n 까지 little 문자열이 포함되어있는지 검색, 가장 먼저 발견된 위치 리턴

  • 오류발생-수정전
    char	*ft_strnstr(const char *str, const char *to_find, size_t len)
    {
        size_t i;
        size_t j;
    
        i = 0;
        if (to_find[0] == '\0')
            return ((char *)str);
        while (str[i] && i < len)
        {
            j = 0;
            while ((str[i] == to_find[j] || to_find[j] == '\0') && i < len)
            {
                i++;
                j++;
                if (to_find[j] == '\0')
                    return ((char *)&str[i - j]);
            }
            i++;
        }
        return (NULL);
    }
    LibtTester 에서 오류 .. ft_strnstr : 1.OK 2.KO 3.OK 4.OK 5.OK 6.OK 7.OK 8.OK 9.OK 10.KO 11.OK 12.OK
char	*ft_strnstr(const char *big, const char *little, size_t n)
{
	size_t	i;
	size_t	j;
	size_t	little_len;

	i = 0;
	little_len = ft_strlen(little);
	if (!little_len)
		return ((char *)big);
	while (big[i] && i + little_len <= n)
	{
		if (big[i] == little[0])
		{
			j = 0;
			while (big[i + j] && little[j])
			{
				if (big[i + j] != little[j])
					break ;
				else if (j == little_len - 1)
					return ((char *)big + i);
				j++;
			}
		}
		i++;
	}
	return (NULL);
}

✏️ 문자열 내에서 부분문자열 탐색

✏️ 검색에서 마지막 null문자는 포함하지 않음

✏️ 만약 little이 발견되지 않는다면 null을 리턴

✏️ littlenull이면 big을 그대로 반환

✏️ big의 문자열 길이 혹은 n 보다 little의 문자열 길이가 더 길면 null 반환

13) ft_strncmp

: 두 문자열의 처음부터 n까지만 정확히 일치하는지 비교

int		ft_strncmp(char *s1, char *s2, unsigned int n)
{
    while (*s1 != '\0' && *s2 != '\0' && n > 0)
    {
        if (*s1 != *s2)
            break;
        s1++;
        s2++;
        n--;
    }
    if (n == 0)
        return (0);
    return (*(unsigned char *)s1 - *(unsigned char *)s2);
}

✏️ 일치하면 0 반환, 일치하지 않으면 (s1[i]-s2[i]) 차이값 리턴

이런 const를 빼먹었군

int ft_strncmp(const char *s1, const char *s2, unsigned int n)

14) ft_atoi

: 문자열을 정수(int)로 변환

  • 오류발생-수정전
    int ft_is_space(const char c)
    {
    	if (c == ' ' || (c >= 9 && c <= 13))
    		return (1);
    	else
    		return (0);
    }
    
    int ft_check_str(const char c, const char *str)
    {
    	while (*str)
    	{
    		if (*str == c)
    			return (1);
    		str++;
    	}
    	return (0);
    }
    
    int ft_atoi(const char *str)
    {
    	int sign;
    	unsigned long long result;
    	int i;
    
    	sign = 1;
    	result = 0;
    	i = 0;
    	while (*str != 0 && ft_is_space(*str))
    		str++;
    	if (ft_check_str(*str, "+-") != 0)
    	{
    		if (*str == '-')
    			sign *= -1;
    		str++;
    	}
    	while (str[i] != '\0' && str[i] >= '0' && str[i] <= '9')
    	{
    		result = result * 10 + (str[i] - '0');
    		i++;
    	}
    	if (result > 9223372036854775807)
    		return (sign == '-' ? 0 : -1);
    	return (sign * result);
    }
    libft-unit-test 오류 헤더파일 #include <limits.h> 추가하고
    while (str[i] != '\0' && str[i] >= '0' && str[i] <= '9')
    	{
    		result = result * 10 + (str[i] - '0');
    		if (!(INT_MIN <= result * sign && result * sign <= INT_MAX))
    			return ((sign < 0) ? 0 : -1);
    		i++;
    	}
    이렇게 수정하니까 OK 되긴하는데 딱히 필요없는 과정이 아닌가.. 싶음
#include <limits.h>

int		ft_is_space(const char c)
{
	if (c == ' ' || (c >= 9 && c <= 13))
		return (1);
	else
		return (0);
}

int		ft_check_str(const char c, const char *str)
{
	while (*str)
	{
		if (*str == c)
			return (1);
		str++;
	}
	return (0);
}

int		ft_atoi(const char *str)
{
	int			sign;
	long long	result;
	int			i;

	sign = 1;
	result = 0;
	i = 0;
	while (ft_is_space(*str))
		str++;
	if (ft_check_str(*str, "+-") != 0)
	{
		if (*str == '-')
			sign *= -1;
		str++;
	}
	while (str[i] != '\0' && str[i] >= '0' && str[i] <= '9')
	{
		result = result * 10 + (str[i] - '0');
		if (!(INT_MIN <= result * sign && result * sign <= INT_MAX))
			return ((sign < 0) ? 0 : -1);
		i++;
	}
	return (sign * result);
}

15) ft_isalpha

int		ft_isalpha(int c)
{
    return (((65 <= c) && (90 >= c)) || ((97 <= c) && (122 >= c)));
}

16) ft_isdigit

int		ft_isdigit(int c)
{
    return (c >= '0' && c <= '9');
}

17) ft_isalnum

int		ft_isalnum(int c)
{
	if (c >= 'a' && c <= 'z')
		return (1);
	if (c >= 'A' && c <= 'Z')
		return (1);
	if (c >= '0' && c <= '9')
		return (1);
	return (0);
}

18) ft_isascii

int		ft_isascii(int c)
{
    return (c >= 0 && c <= 127);
}

19) ft_isprint

int		ft_isprint(int c)
{
    return (c >= 32 && c <= 126);
}

20) ft_toupper

int		ft_toupper(int c)
{
	if (c >= 97 && c <= 122)
		c -= 32;
	return (c);
}

21) ft_tolower

int		ft_tolower(int c)
{
	if (c >= 65 && c <= 90)
		c += 32;
	return (c);
}

1-3

22) ft_calloc

: malloc으로 할당된 공간의 값을 모두 0으로 초기화

void	*ft_calloc(size_t cnt, size_t size)
{
    void *ptr;

    ptr = malloc(size * cnt);
    if (ptr == 0)
        return (0);
    ft_memset(ptr, 0, size * cnt);
    return (ptr);
}

✏️ malloc은 할당된 공간의 값을 바꾸지 않는다

23) ft_strdup

: 문자열 str 길이 +1 크기를 malloc으로 할당 후 문자열 str을 복사한 후 반환

char	*ft_strdup(const char *s)
{
	size_t	i;
	char	*res;

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

✏️ 문자열을 새로운 메모리에 할당하여 복사

✏️ malloc + strcpy

profile
코딩하는 에디

0개의 댓글