[42Seoul] Libft part1

jiyseo·2022년 4월 15일
0

42 Seoul

목록 보기
2/9

ft_isalpha

int isalpha (int c);

매개변수 : C언어에서 아스키 코드에 해당하는 문자들은 숫자로 표현이 되고, 문자를 넣으면 자동으로 아스키 코드에 있는 숫자로 들어가기 때문에 int 타입이긴 하지만 'a', 'A', '1' 등을 집어 넣어도됩니다.즉, 'a' 와 같이 char 타입으로 집어 넣어도 자동으로 int 타입으로 형변환 되어서 들어가게 됩니다. 아스키 코드 표를 참고하면 'a'는 자동으로 숫자 97로 형변환되어 들어가게 됩니다.

반환형 : 매개변수로 들어온 인자가 알파벳이라면 0이 아닌 수를 반환하고 알파벳이 아니라면 0을 반환합니다.

더 정확하게 이야기하면 isalpha 함수는알파벳 대문자 "A-Z"는 1을 반환.알파벳 소문자 'a-z"는 2를 반환.알파벳이 아닌것은 0을 반환합니다.

한번더 이야기 하면 isalpha 함수의 매개변수로아스키 코드표에 'A-Z'에 해당하는 65번~90번의 값이 들어오면 1을 반환아스키 코드표에 'a-z'에 해당하는 97번~122번의 값이 들어오면 2를 반환그 이외의 값이 들어오면 0을 반환하는 함수 입니다.

#include "libft.h"

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

ft_isdigit

c가 '0'~'9'면 1, 아니면 0

#include "libft.h"

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

ft_isalnum

알파벳이거나 '0'~'9'면 1, 아니면 0

#include "libft.h"

int	ft_isalnum(int c)
{
	if (ft_isalpha(c) || ft_isdigit(c))
		return (1);
	return (0);
}

ft_isascii

1번 부분 (code 0 ~ 31)

ASCII control characters는 인쇄가 불가능한 제어코드들입니다.

프린터 같은 주변기기들을 제어할 때 사용됩니다.


2번 부분 (code 32 ~ 127)

ASCII printable characters는 다른 어떠한 ASCII 변형 테이블에서도, 공통적으로 사용되는 인쇄 가능한 문자로 불립니다.

문자, 숫자, 구두점 및 기타 기호들을 나타냅니다. 또한 키보드에 있는 거의 모든 문자를 찾으실 수 있습니다.

(127은 DEL 명령을 나타냅니다.)


3번 부분 (code 128 ~ 255)

Extended ASCII characters는 ISO 8859-1dp를 따르며 ISO Latin-1로도 불립니다.

code 128 ~ 159는 Microsoft Windows Latin-1 확장 문자가 포함되어 있습니다.

#include "libft.h"

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

ft_isprint

2번 부분이 출력 가능한 부분

#include "libft.h"

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

ft_strlen

  • size_t 사용이유
  • 배열의 크기를 주는 것이므로 기본적으로 0보다 작을 수 없음
  • size_t는 해당 시스템에서 어떤 객체나 값이 포함할 수 있는 최대 크기의 데이터를 표현하는 타입으로 반드시 unsigned 형으로 나타낸다.아래는 C99 원문. 이 내용이 가장 중요하고 알고있으면된다.
  • sizeof() 반환형이 size_t
#include"libft.h"

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

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

ft_memset

b = string

c = 대입할 문자

len = 얼마만큼 대입할건지

return 값은 b의 주소값

#include"libft.h"

void	*ft_memset(void *b, int c, size_t len)
{
	unsigned char	*res;
	   size_t		i;

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

ft_bzero

n만큼 0을 채워넣음

#include"libft.h"

void	ft_bzero(void *s, size_t n)
{
	ft_memset(s, 0, n);
}

ft_memcpy

첫번째 인자 void * dest= 복사 받을 메모리를 가리키는 포인터

두번째 인자 const void *source= 복사할 메모리를 가리키고 있는 포인터

세번째 인자 size_t num= 복사할 데이터(값)의 길이(바이트 단위)

두번째 인자(source)에 있는 원본을 세번째 인자(num)만큼의 길이 만큼 복사해서첫번째 인자(dest)에 붙여 넣는 함수 입니다.

성공 시 dst, 실패 시 0 return

dst 와 src 중 하나라도 비어있을 시 0을 리턴하도록 했는데 오류남;;;

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

	if (!dst || !src)
		return (0);
	in_dst = (unsigned char *) dst;
	in_src = (unsigned char *) src;
	i = 0;
	while (i++ < n)
		*in_dst++ = *in_src++;
	return (dst);
}
void	*ft_memcpy(void	*dst, const void	*src, size_t	n)
{
	      size_t	i;
	unsigned char	*in_dst;
	unsigned char	*in_src;

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

둘 다 비어있을 시 0을 return 해야함

#include"libft.h"

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

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

ft_memmove

void memmove (void dest, const void* src, size_t num);

첫번째 인자 void* dest= destination.복사 한걸 붙여넣을 메모리를 가리키는 포인터 입니다. (목적지)

두번째 인자 void* src= source.복사 할 메모리를 가리키는 포인터 입니다. (출발지)

세번째 인자 size_t num= 복사할 바이트 길이 입니다.

반환형= 첫번째 인자인 dest를 반환 합니다.

함수 설명. src가 가리키는 메모리로 부터 num 바이트 사이즈 만큼 dest가 가리키는 메모리에 옮깁니다.  move 라서 잘라내고 붙여넣는다고 생각하실수 있지만, 이것도 복사하는 기능을 가진 함수 입니다.그러면 복사 만 하는거면 [memcpy]와 같다고 생각하실 수 있겠지만, memcpy는 바로 그냥 어디 거치지 않고 그 위치에 복사해서 붙여넣는다고 생각하시면 되고, memmove는 그것보다는 안전하게, 복사할것을 버퍼에 복사하고 해당 위치에 가서 버퍼에 복사된 것을 붙여 넣는 식으로 동작이 구현되어있습니다.성능을 "굳이" 따지자면 memcpy가 버퍼를 거치지 않고 복사하기 때문에 좀더 좋긴 하겠지만, 버퍼를 이용하는 memmove가 더 안정성이 좋습니다.

에러 이유

overlapped 하는 경우

dst> src 인 경우를 생각하지 않음

#include"libft.h"

void	*ft_memmove(void *dst, const void *src, size_t len)
{
	unsigned char	*dst2;
	unsigned char	*src2;

	if (dst == src || !len)
		return (dst);
	dst2 = (unsigned char *)dst;
	src2 = (unsigned char *)src;
	if (dst < src)
	{
		while (len--)
			*dst2++ = *src2++;
	}
	else if (dst > src)
	{
		while (len--)
			*(dst2 + len) = *(src2 + len);
	}
	return (dst);
}

ft_strlcpy

size_t strlcpy(char dst, const char src, size_t dstsize)

strlcpy는 문자열을 복사해주는 함수인데, dest안에 src의 값을 복사해 준다. size는 src의 길이 이하일때 이용되는 녀석이다. strlcpy는 src의 '\0'값을 만나기 전 혹은 size - 1만큼 복사가 이루어 졌을때 복사를 중지한다.

dstsize가 0일 경우 처리안함

#include"libft.h"

size_t	ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
	size_t	src_len;

	src_len = 0;
	while (src[src_len])
		src_len++;
	if (dstsize == 0)
		return (src_len);
	while (--dstsize && *src)
		*dst++ = *src++;
	*dst = '\0';
	return (src_len);
}#include"libft.h"

size_t	ft_strlcat(char	*dst, const char	*src, size_t	dstsize)
{
	unsigned int	dst_len;
	unsigned int	src_len;
	unsigned int	n;
	        char	*p;

	p = dst;
	dst_len = ft_strlen(dst);
	src_len = ft_strlen(src);
	if (dstsize <= dst_len)
		return (src_len + dstsize);
	n = dstsize - dst_len - 1;
	while (*p)
		p++;
	while (*src != '\0' && n)
	{
		*p++ = *src++;
		n--;
	}
	*p = '\0';
	return (dst_len + src_len);
}#include"libft.h"

size_t	ft_strlcat(char	*dst, const char	*src, size_t	dstsize)
{
	unsigned int	dst_len;
	unsigned int	src_len;
	unsigned int	n;
	        char	*p;

	p = dst;
	dst_len = ft_strlen(dst);
	src_len = ft_strlen(src);
	if (dstsize <= dst_len)
		return (src_len + dstsize);
	n = dstsize - dst_len - 1;
	while (*p)
		p++;
	while (*src != '\0' && n)
	{
		*p++ = *src++;
		n--;
	}
	*p = '\0';
	return (dst_len + src_len);
}#include"libft.h"

size_t	ft_strlcat(char	*dst, const char	*src, size_t	dstsize)
{
	unsigned int	dst_len;
	unsigned int	src_len;
	unsigned int	n;
	        char	*p;

	p = dst;
	dst_len = ft_strlen(dst);
	src_len = ft_strlen(src);
	if (dstsize <= dst_len)
		return (src_len + dstsize);
	n = dstsize - dst_len - 1;
	while (*p)
		p++;
	while (*src != '\0' && n)
	{
		*p++ = *src++;
		n--;
	}
	*p = '\0';
	return (dst_len + src_len);
}

ft_strlcat

두 문자열을 붙이는 함수이다. dest의 맨 뒤에 src를 size만큼만 붙인다. 만약 size가 dest의 길이 이하라면 문자열을 붙이는 과정이 사라지고 size가 더 크다면 size - 1만큼 src를 붙이고 마지막에 '\0'값을 넣어주고 리턴 값은 dest의 길이 + src의 길이이다.

#include"libft.h"

size_t	ft_strlcat(char	*dst, const char	*src, size_t	dstsize)
{
	unsigned int	dst_len;
	unsigned int	src_len;
	unsigned int	n;
	        char	*p;

	p = dst;
	dst_len = ft_strlen(dst);
	src_len = ft_strlen(src);
	if (dstsize <= dst_len)
		return (src_len + dstsize);
	n = dstsize - dst_len - 1;
	while (*p)
		p++;
	while (*src != '\0' && n)
	{
		*p++ = *src++;
		n--;
	}
	*p = '\0';
	return (dst_len + src_len);
}

ft_strncmp

길이를 지정하여 두 문자열을 비교하는 함수

일치할 시 0 return

#include"libft.h"

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

ft_toupper/ ft_tolower

ft_toupper : 소문자인 알파벳들을 대문자로 바꿔주는 함수

ft_tolower : 대문자인 알파벳들을 소문자로 바꿔주는 함수

int	ft_toupper(int	c)
{
	if (c >= 'a' && c <= 'z')
		c -= 'a' - 'A';
	return (c);
}
int	ft_tolower(int	c)
{
	if (c >= 'A' && c <= 'Z')
		c += 'a' - 'A';
	return (c);
}

ft_strchr

문자열 내에 일치하는 문자가 있는지 검사하는 함수

문자열에서 찾은 문자위치의 포인터를 리턴

틀린 이유 - 비교하는 c가 int로 들어오기 때문에 이를 char로 바꿔주고 비교해야함

c를 unsigned char로 바꾸어 비교해줌

→ 자꾸 NULL이 리턴됨 ...

s가 const char여서 주소값을 옮길 시 작동하지 않음 → 따라서 char로 다른 변수를 선언해 준 후 s를 char의 형태로 저장함

→ 그래도 안됨

그냥 i써서 함 ,.

int a = NULL;
char a = NULL = 0;
char a = 0 = '\0'
while (!
s) ≠ while (*s ≠ ‘\0’) 의 차이 ?

당연함 헷갈렸었음 ..

#include"libft.h"

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

	str = (char *)s;
	while (*str)
	{
		if (*str == (char)c)
			return ((char *)str);
		str++;
	}
	if ((char)c == *str)
		return ((char *)str);
	return (NULL);
}

ft_strrchr

strrchr() 함수는 문자열에서 찾은 문자 위치의 포인터를 리턴

strrchr() 함수는 문자열 s에서 마지막으로 있는 문자 c의 포인터를 리턴합니다.

안이 ... 이것도 헷갈림 while(*s) 이거여야되는데 while(!(**s))로 씀 .. 아 딮빡

#include"libft.h"

char	*ft_strrchr(const char	*s, int	c)
{
	char	*last;

	last = 0;
	while (*s)
	{
		if (*s == (char)c)
			last = (char *)s;
		s++;
	}
	return (last);
}

아니 이게 왜 안돼??

는 c 가 ‘\0’인 경우를 안해준듯?

#include"libft.h"

char	*ft_strrchr(const char	*s, int	c)
{
	char	*last;

	last = 0;
	while (*s)
	{
		if (*s == (char)c)
			last = (char *)s;
		s++;
	}
	if (*s == (char)c)
		last = (char *)s;
	return (last);
}

ft_memchr

C언어 메모리 관련 함수 memchr()은 메모리 영역에서 임의의 문자를 검색하고 있으면 그 위치의 포인터를 구합니다.

  • 헤더: string.h
  • 형태: void memchr(const void s, int c, size_t n)
  • 인수: void *s 검사할 메모리의 포인터int c 검색 문자size_t n 검사할 영역의 크기
  • 반환: void * 처음 발견된 위치의 포인터. 발견하지 못하면 NULL

이 함수를 작성하면서 헷갈렸던 점은 void형 포인터 반환일때 &buffer[10] 작성이 불허하다는 것이였다.

그 이유는 &buffer[10]가 &(buffer + 10)를 평가하기 때문입니다. 왜냐하면 배열 첨자 연산자는 연산자 &의 주소보다 우선 순위가 높기 때문이다. 그러나 버퍼 유형이 void 이며 크기 정보가 없기 때문에 void 포인터에서는 포인터 계산을 수행할 수 없습니다. 버퍼에 타입캐스트 연산자(char )를 사용하면 다음과 같이 필요한 크기 정보가 제공됩니다.

(char )buffer + 10은 (char)의 버퍼 + 10 크기 또는 가변 버퍼가 가리키는 버퍼의 11번째 요소의 주소와 동일합니다.

즉, 정리하자면

&buffer[10]

대신에

(char *)buffer + 10

로 작성을 해야한다.

#include"libft.h"

void	*ft_memchr(const void	*s, int	c, size_t	n)
{
	size_t	i;

	i = 0;
	while (i < n)
	{
		if (((unsigned char *)s)[i] == (unsigned char)c)
			return ((void *)s + i);
		i++;
	}
	return ((void *)0);
}

ft_memcmp

int memcmp(const void s1, const void s2, size_t n)

s1 이 가리키는 처음 n 바이트의 데이터와 s2 가 가리키는 처음 n 바이트의 데이터를 비교하여 이들이 같다면 0 을 리턴하고 다르다면 0 이 아닌 값을 리턴한다. 이 때 리턴되는 값은 아래를 참고.

두 개의 메모리 블록의 관계에 따라 아래와 같이 정수 값을 리턴한다.

  • 만일 두 메모리 블록이 정확히 같다면 0 을 리턴한다.
  • 만일 두 메모리 블록이 다를 경우, ptr1 과 ptr2 가 가리키는 메모리 블록에서 앞에서 부터 처음으로 다른 바이트를 살펴 보는데, 그 바이트를 unsigned char 로 해석하였을 때, 그 값이 ptr1 이 더 크면 0 보다 큰 값을, 아니면 0 보다 작은 값을 리턴한다.

틀린 이유

  1. cp_s1 cp_s2가 while문을 돌며 주소값을 하나씩 + 해주어야하는데 이걸 안함
  2. return 할 때 cp_s1 cp_s2의 값의 차를 return 해야하는데 주소값의 차를 리턴함
#include"libft.h"

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

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

ft_strnstr

char strnstr(const char big, const char *little, size_t len);

이 함수는 big 문자열에 len 길이 중에서 little 문자열을 찾는 것이다.

반환 값

만약 little 값이 비어 있으면 big를 반환한다.

big 문자열에서 little 문자열을 찾지 못하면 NULL을 반환한다.

little 문자열을 찾으면 big에 little 문자열 시작 부분 위치 주소를 반환한다.

  • 문자열 내에서 부분문자열을 탐색하는 함수
  • strnstr() 함수는 종료전까지의 문자들 중 big 문자열 내에서 찾은 little 문자열 중 첫번째로 나온 결과를 찾는다. 문자열은 최대 len의 수까지만 탐색한다.
  • 문자열들은 \0을 만나면 더이상 찾지 않는다

while ((str[i] == find[j]) && i < len)

while (str[i] && i + ft_strlen(find) < len)

char	*ft_strnstr(const char	*str, const char	*find, size_t	len)
{
	size_t	i;
	size_t	j;

	if (!find[0])
		return ((char *)str);
	i = 0;
	while (str[i] && i + ft_strlen(find) <= len)
	{
		if (str[i] == find[0])
		{
			j = 0;
			while (find[j] || str[i + j])
			{
				if (str[i + j] != find[j])
					break ;
				else if (j == ft_strlen(find) - 1)
					return ((char *)str + i);
				j++;
			}
		}
		i++;
	}
	return (NULL);
}

while 문에서 i + ft_strlen(find) <= len 이 부분에서 등호를 쓰지 않아서 틀린 것이다 ..!!

#include"libft.h"

char	*ft_strnstr(const char	*str, const char	*find, size_t	len)
{
	size_t	i;
	size_t	j;

	if (!find[0])
		return ((char *)str);
	i = 0;
	while (str[i] && i + ft_strlen(find) <= len)
	{
		if (str[i] == find[0])
		{
			j = 0;
			while (find[j] || str[i + j])
			{
				if (str[i + j] != find[j])
					break ;
				else if (j == ft_strlen(find) - 1)
					return ((char *)str + i);
				j++;
			}
		}
		i++;
	}
	return (NULL);
}

ft_atoi

atoi = char to int = 문자열을 정수 타입으로

atoi 함수는 nptr 로 지정된 문자열을 int 형으로 변환한다. 이때 변환범위는 숫자로 인식가능한 선까지이다.

예를들어 아규먼트로 "1234ab" 가 주어졌다면 숫자로 인식가능한 문자열범위는 "1234" 이므로 1234 로 변환되게 된다.

만약 변환시킬만한 적당한 문자가 존재하지 않는다면 0을 리턴한다.

atoi() 함수는 입력 문자를 숫자로 해석하여 생성되는 int 값을 리턴합니다. 함수가 입력을 해당 유형의 값으로 변환할 수 없는 경우 리턴값은 0입니다. 리턴값은 오버플로의 경우 정의되지 않습니다.

#include"libft.h"

const char	*skip_whitespace(const char *str)
{
	while (*str == ' ' || (*str >= 9 && *str <= 13))
		str++;
	return (str);
}

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

	n = 0;
	sign = 1;
	str = skip_whitespace(str);
	if (*str == '-')
		sign = -1;
	if ((*str == '-') || (*str == '+'))
		str++;
	while ((*str != '\0') && ('0' <= *str) && (*str <= '9'))
	{
		n = (n * 10) + (*str - '0');
		if (n > 2147483647 && sign == 1)
			return (-1);
		if (n > 2147483648 && sign == -1)
			return (0);
		str++;
	}
	return (n * sign);
}

ft_calloc

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

calloc은 할당된 공간의 값을 모두 0으로 바꾼다.

배열을 할당하고 모두 0으로 초기화할 필요가 있을경우에는 calloc을 쓰면 편하다.

#include "libft.h"

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

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

ft_strdup

char strdup(const char s1)

💻Parameters

  • s : 복사할 문자열

    💻Return value

  • string을 복사한 메모리주소(복사된 문자열의 주소를 가리키는 포인터)

  • 실패 시 NULL

malloc + strcpy

#include"libft.h"

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

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

ft_substr

SUBSTR 함수는 문자단위로 시작위치와 자를 길이를 지정하여 문자열을 자른다.

  • 함수 : SUBSTR("문자열", "시작위치", "길이")
#include"libft.h"

char	*ft_substr(char const	*s, unsigned int	start, size_t	len)
{
	size_t	i;
	size_t	j;
	char	*res;

	i = 0;
	j = 0;
	if (!s)
		return (NULL);
	res = (char *)malloc(sizeof(char) * (len + 1));
	if (!res)
		return (NULL);
	while (s[i])
	{
		if (i >= start && j < len)
		{
			res[j] = s[i];
			j++;
		}
		i++;
	}
	res[j] = '\0';
	return (res);
}
profile
코딩뿡뿡이

0개의 댓글