[주의사항]

  • 엄밀히 따지면 size_t 자료형과 unsigned int 형 자료형은 다르다.
  • 문자, 문자열을 다룰땐 char 형보다 unsigned char 형으로 다루는것이 더 많은 ascii 코드로의 접근성을 확보할 수 있기 때문에 안전하다.
  • man 에서는 resctirct를 쓰는 경우가 있으나, ft 과제에서는 사용 금지.
  • gcc stack 메모리는 8mb로 제한되므로 주의 필요.(클러스터만의 특성인지, 일반적인 특성인지 모르겠음)

[ft_memset]

  • 원형 : void *ft_memset(void *b, int c, size_t len)
  • 정의 : 주소값 b 부터 len 범위 까지 c로 채워넣기
  • 반환 값 : 주소값 b
void	*ft_memset(void *b, int c, size_t len)
{
	size_t			i;
	unsigned char	*tmp_ptr;

	tmp_ptr = (unsigned char *)b;
	i = 0;
	while (len--)
		tmp_ptr[i++] = (unsigned char)c;
	return (b);
}

[ft_bzero]

  • 원형 : void ft_bzero(void *s, size_t n)
  • 정의 : 주소값 b 부터 n의 범위만큼 0(NULL)로 채워넣기
  • 반환 값 : 없음
void	ft_bzero(void *s, size_t n)
{
	char	*tmp_ptr;
	size_t	i;

	tmp_ptr = (char *)s;
	i = 0;
	while (n--)
	{
		tmp_ptr[i] = '\0';
		i++;
	}
}

[ft_memcpy]

  • 원형 : void *ft_memcpy(void dst, const void src, size_t n)
  • 정의 : dst에 src를 n 범위 만큼 copy하기. 두 주소값이 교차될 경우 undefined behavior 이 나타난다.
  • 반환 값 : 복사가 완료된 dst
void	*ft_memcpy(void *dst, const void *src, size_t n)
{
	size_t			i;
	unsigned char	*dst_ptr;
	unsigned char	*src_ptr;

	if (dst == 0 && src == 0)
		return (0);
	dst_ptr = (unsigned char *)dst;
	src_ptr = (unsigned char *)src;
	i = 0;
	while (i < n)
	{
		dst_ptr[i] = src_ptr[i];
		i++;
	}
	return (dst);
}

[Point : NULL 반환]
if (dst == 0 && src == 0) 이 조건이 아니라 if (dst == 0 || src == 0) 일때 NULL을 반환해야하는게 아닐까? 하는 의문이 들 수 있음.하지만 memcpy의 정의상 NULL을 반환하는 특이 케이스가 명시되어 있지 않다. 따라서 위의 조건문은 dst가 NULL일 수 밖에 없는 조건일때 NULl을 반환한다고 보는것이 적절하다.

[ft_memccpy]

  • 원형 : void *ft_memccpy(void dst, const void src, int c, size_t n)
  • 정의 : dst에 src를 n 범위 만큼 copy하되, 도중에 c가 src에 나타날경우 copy 를 멈춘다. 두 주소값이 교차될 경우 undefined behavior 이 나타난다.
  • 반환 값 : src 에서 c가 발견된 경우에는 거기까지 복사된 dst + 1을, c가 발견되지 않은 경우에는 NULL을 반환
void	*ft_memccpy(void *dst, const void *src, int c, size_t n)
{
	size_t			i;
	unsigned char	*dst_ptr;
	unsigned char	*src_ptr;

	dst_ptr = (unsigned char *)dst;
	src_ptr = (unsigned char *)src;
	i = 0;
	while (i < n)
	{
		dst_ptr[i] = src_ptr[i];
		if (src_ptr[i] == (unsigned char)c)
			return (dst + i + 1);
		i++;
	}
	return (0);
}

[ft_memmove]

  • 원형 : void *ft_memmove(void dst, const void src, size_t len)
  • 정의 : dst에 src를 n 범위 만큼 copy함. 두 주소값이 교차할 수도 있으나, copy는 언제나 잘 이뤄져야함.
  • 반환 값 : copy가 완료된 dst
void		*ft_memmove(void *dst, const void *src, size_t len)
{
	size_t			i;
	unsigned char	*dst_ptr;
	unsigned char	*src_ptr;

	if (dst == src || len == 0)
		return (dst);
	dst_ptr = (unsigned char *)dst;
	src_ptr = (unsigned char *)src;
	if (dst < src)
		ft_memcpy(dst_ptr, src_ptr, len);
	else
	{
		i = 0;
		while (len - i > 0)
		{
			dst_ptr[len - i - 1] = src_ptr[len - i - 1];
			i++;
		}
	}
	return (dst);
}

[Point : stack 영역을 활용한 swap]
unsigned char *tmp[len]을 선언하고 memcpy를 이용해서 더 짧게 코드를 짤 수 있다. 하지만 stack 영역은 8mb로 제한되어있는데, len에 8mb보다 큰 메모리 영역이 들어온다면? 오류가 나타날 것이다.

[Point : src > dst 인 경우]
stack 영역을 따로 활용하기 어렵기 때문에, 결국 주소값의 대소를 비교하여 copy작업을 분리해줘야한다. dst > src 인 경우는 memcpy를 활용하여 손쉽게 처리할 수 있지만, 그 반대의 경우는 그렇지 않다. 이 경우에는 src의 제일 뒤에서부터 dst의 제일 뒤로 붙이면 문제 없이 해결된다.

[ft_memchr]

  • 원형 : void *ft_memchr(const void *s, int c, size_t n)
  • 정의 : 문자열 s에서 c가 처음 출현한 주소를 찾는다.
  • 반환 값 : 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)
			return (ptr);
		ptr++;
	}
	return (0);
}

[ft_memcmp]

  • 원형 : int ft_memcmp(const void s1, const void s2, size_t n)
  • 정의 : n 범위까지 두 문자열을 비교하여 똑같으면 0을, 다르다면 해당 값의 바이트 차이를 반환하는 함수, unsigned char 로 다뤄야한다.
  • 반환 값 : 두 바이트 값의 차이
int	ft_memcmp(const void *s1, const void *s2, size_t n)
{
	unsigned char *ptr1;
	unsigned char *ptr2;

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

[ft_strlen]

  • 원형 : size_t ft_strlen(const char *str)
  • 정의 : 문자열 str의 길이를 반환하는 함수
  • 반환 값 : str의 길이
size_t	ft_strlen(const char *str)
{
	size_t i;

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

[ft_strlcpy]

  • 원형 : size_t ft_strlcpy(char dst, const char src, size_t dstsize)
  • 정의 : dstsize - 1만큼 dst에 src를 copy함. 적어도 dst[dstsize]에는 NULL terminating을 보장함.
  • 반환 값 : str의 길이
size_t	ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
	size_t len;
	size_t i;

	if (!src)
		return (0);
	len = ft_strlen(src);
	i = 0;
	if (dstsize == 0)
		return (len);
	while (src[i] && (i + 1) < dstsize)
	{
		dst[i] = src[i];
		i++;
	}
	dst[i] = '\0';
	return (len);
}

[Point : copy의 중단]
함수의 설명만 보면 i + i < dstsize 조건동안 copy만 하면 될것 같지만, 문자열을 복사하는 것이기 때문에 문자열의 종료(*src == '\0')가 나타나면 copy를 중단한다.

[ft_strlcat]

  • 원형 : size_t ft_strlcat(char dst, const char src, size_t dstsize)
  • 정의 : dst의 NULL terminating 부분부터 src를 붙여넣음. 이때 기대되는 전체 dst의 길이는 dstsize임. 따라서 dsr[dstsize] = '\0' 이 되어야함.
  • 반환 값 : 기대되는 dstsize와 실제 주어진 dst의 길이의 대소 관계에 따라 반환값이 변화하는데,
    (1) dstlen >= dstsize : copy를 할 수 없다. copy를 위해 할당되었으나, 실제 copy에 활용되지 못한 buff사이즈인 srclen + dstsize를 반환
    (2) dstlen < dstsize : copy가 가능하다. copy를 위해 활용된 buff사이즈인 dstlen + srclen 을 반환한다.
size_t	ft_strlcat(char *dst, const char *src, size_t dstsize)
{
	size_t dst_len;
	size_t src_len;
	size_t i;

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

[ft_strchr]

  • 원형 : char *ft_strchr(const char *s, int c)
  • 정의 : 문자열 s에서 c가 처음으로 나타나는 주소값을 반환한다. 만약 c가 없다면 NULL 포인터가 반환된다.
  • 반환 값 : c의 첫 출현 주소값 혹은 NULL
char	*ft_strchr(const char *s, int c)
{
	unsigned char data;
	unsigned char *str;

	str = (unsigned char *)s;
	data = (unsigned char)c;
	while (*str)
	{
		if (*str == data)
			return ((char *)str);
		str++;
	}
	if (data == '\0')
		return ((char *)str);
	return (NULL);
}

[ft_strrchr]

  • 원형 : char *ft_strrchr(const char *s, int c)
  • 정의 : 문자열 s에서 c가 나타나는 주소값 중 가장 큰 값을 반환한다. 만약 c가 없다면 NULL 포인터가 반환된다.
  • 반환 값 : 가장 큰 c의 출현 주소값 혹은 NULL
char	*ft_strrchr(const char *s, int c)
{
	int				i;
	unsigned char	data;
	unsigned char	*str;

	data = (unsigned char)c;
	str = (unsigned char *)s;
    	i = ft_strlen(s);
	if (data == '\0')
		return ((char *)(str + i));
	while (i >= 0)
	{
		if (str[i] == data)
			return ((char *)(str + i));
		i--;
	}
	return (0);
}

[ft_strnstr]

  • 원형 : char *ft_strnstr(const char haystack, const char needle, size_t len)
  • 정의 : haystack을 len만큼 탐색하여 needle 전체가 출현하는 첫 주소값을 반환한다. 이때 '\0'이후에 등장하는 문자는 고려하지 않는다.
  • 반환 값 :
    (1) 만약 needle이 empty 면haystack
    (2) needle 전체가 출현하지 않는다면 NULL
    (3) needle 전체가 출현한다면 그 첫 주소값
char	*ft_strnstr(const char *haystack, const char *needle, size_t len)
{
	size_t i;
	size_t j;

	if (*needle == 0)
		return ((char *)haystack);
	i = 0;
	while (haystack[i] && i < len)
	{
		j = 0;
		while (haystack[i + j] && i + j < len && haystack[i + j] == needle[j])
			j++;
		if (needle[j] == '\0')
			return ((char *)(haystack + i));
		i++;
	}
	return (NULL);
}

[ft_strncmp]

  • 원형 : int ft_strncmp(const char s1, const char s2, size_t n)
  • 정의 : n 범위 이하까지 s1과 s2를 비교하여 그 차이값을 반환함. 만약 n 범위에 도달하기 전에 '\0'이 출현하면 거기서 비교를 끝냄.
  • 반환 값 : s1과 s2의 차이값
int		ft_strncmp(const char *s1, const char *s2, size_t n)
{
	size_t i;

	if (n == 0)
		return (0);
	i = 0;
	while (s1[i] && s2[i] && (i + 1) < n &&
			(unsigned char)s1[i] == (unsigned char)s2[i])
		i++;
	return ((unsigned char)s1[i] - (unsigned char)s2[i]);
}

[ft_atoi]

  • 원형 : int ft_atoi(const char *str)
  • 정의 : 주어진 str의 첫번째 숫자 뭉치(portion)를 int형으로 변환하여 반환. 부호(+, -)는 한번만 출현해야 하며, 부호 출현 뒤 숫자 뭉치가 나올때까지 whitespace는 허용되지 않는다.
  • 반환 값 :
    (1) int Overflow : -1
    (2) int Underflow : 0
    (3) string의 int 변환
static int	judge_return(long res)
{
	if (res > 2147483647)
		return (-1);
	if (res < -2147483648)
		return (0);
	return (1);
}

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

	i = 0;
	while ((str[i] >= 9 && str[i] <= 13) || str[i] == 32)
		i++;
	sign = 1;
	if (str[i] == '-' || str[i] == '+')
	{
		if (str[i] == '-')
			sign = -1;
		i++;
	}
	if (!ft_isdigit(str[i]))
		return (0);
	res = 0;
	while (ft_isdigit(str[i]))
	{
		res = res * 10 + (sign * (str[i] - '0'));
		if (judge_return(res) <= 0)
			return (judge_return(res));
		i++;
	}
	return ((int)res);
}

[Point : long 형으로 결과값 저장]
str에 int형을 넘어서는 숫자가 들어올경우 이를 판단하기 위해서 long 형 데이터에 결과값을 계속 갱신하면서 judge_return 함수로 판단하기 위함.

[ft_strdup]

  • 원형 : char ft_strdup(const char s1)
  • 정의 : 충분한 메모리 공간에 s1을 복사해서 넣고, 새로 생성된 메모리 주소값을 반환한다.
  • 반환 값 :
    (1) 충분한 메모리 공간이 없다면 NULL포인터
    (2) 새로 생성된 포인터 첫 주소 값
char	*ft_strdup(const char *s1)
{
	size_t	len;
	size_t	i;
	char	*new_ptr;

	len = 0;
	while (s1[len])
		len++;
	if (!(new_ptr = (char *)malloc((len + 1) * sizeof(char))))
		return (NULL);
	i = 0;
	while (i < len)
	{
		new_ptr[i] = s1[i];
		i++;
	}
	new_ptr[i] = '\0';
	return (new_ptr);
}

[ft_calloc]

  • 원형 : void *ft_calloc(size_t count, size_t size)
  • 정의 : 각 공간이 size만큼의 크기를 갖도록 연속적인 메모리 공간 count개를 할당한다. 이때 할당된 메모리는 zero로 채워져야한다.
  • 반환 값 : 할당된 메모리의 시작 주소값
void	*ft_calloc(size_t count, size_t size)
{
	char	*new_ptr;
	size_t	i;

	if (!(new_ptr = (char *)malloc(size * count)))
		return (NULL);
	i = 0;
	while (i < size * count)
	{
		new_ptr[i] = '\0';
		i++;
	}
	return ((void *)new_ptr);
}

이하 isapha등은 생략한다.

profile
개발자

0개의 댓글