42Seoul - Libft
본 과정 첫 번째 과제인 Libft이다.
설명 전, 하면서 알아두고 가면 좋은 개념들을 먼저 소개하고 설명하겠다.
* Size_t 변수형 : 32비트 환경에선 4바이트, 64비트 환경에선 8바이트이다. 부호 없는 정수 자료형.
Size_t는 문자열이나 메모리의 사이즈를 구하는데 이용이 된다.
그리고 unsigned int를 strlen, 메모리 사이즈 구하는데 이용하면 err가 발생한다.
왜냐면 함수를 정의 할 때 size_t가 반환 값이기 때문이다.
실제 정의 : typedef unsigned int size_t
* Unsigned char를 사용하는 이유 : 우리는 byte단위로 포인터를 쪼개서 확인해야하기 때문에 사용한다.
char보다 unsinged char를 쓰는 이유는 0x00과 0x11을 쓰기 위해서 이다.
이것은 나중에 함수 설명하며 부연 설명을 하겠다.
* Void 포인터를 사용하는 이유 : Void 포인터를 사용하여 모든 변수형을 받아들일 수 있도록 사용하기 위해서 이다.
1. ft_memset
원형 : void *ft_memset(void *ptr, int value, size_t num)
기능 : 지정한 시작 주소값부터 value를 num만큼 채워준다.
설명 : value는 int형이라 4byte이다. 그래서 저것을 unsigned char형으로 강제 형 변환을 해준다.
왜냐면 Memset함수는 1byte를 기준으로 작동하고 0(00), -1(11)만 읽을 수 있기때문이다.
그래서 char형이 아닌 숫자를 넣으면 원하지 않는 값이 나올 수도 있다.
예를 들어 int에 1을 넣으면 ptr에서는 0x01이라 적힌다.
그리고 4byte를 읽으니 0x01010101이 읽혀 원하지 않는주소값을 가리키게 된다.
2. ft_bzero
원형 : void ft_bzero(void *ptr, size_t size)
기능: size byte만큼 ptr주소값을 1 Byte씩 더해가며 0으로 채운다.
3. ft_memcpy
원형 : void *ft_memcpy(void *dest, const void *src, size_t num)
기능: src메모리영역에서 dest메모리영역으로 n byte만큼 복사.
설명 : strcpy랑 다른 점은 strcpy는 문자열 끝을 null로 구분하지만 memcpy는 n byte라고 명시를 해준다.
밑의 예시와 같이 메모리 영역이 겹쳐지게 되면 안된다. 그럴 때 memmove를 이용한다.
그리고 null값까지 고려하여 num을 정해야 한다. 아니면 예외적인 상황이 나올 수 있다.
* 예외 상황(Null고려 X)
4. ft_memccpy
원형 : void *ft_memccpy(void *dest, const void *src, int val, size_t num)
기능: src메모리영역에서 dest메모리영역으로 n byte만큼 복사하는데 src에서 val을 만나면 val까지만 복사.
설명 : 복사하는데 src에서 계속 복사하다가 val을 만나면 val까지 복사하고 복사를 멈춘다.
그리고 리턴 값은 복사가 끝난 다음 dest의 주소값 이다. src에서 val을 만나지 못하면 NULL반환.
5. ft_memmove
원형 : void *ft_memmove(void *dest, const void* src, size_t num)
기능: src의 메모리에 있는 데이터들을 dest 메모리로 num byte만큼 옮기는 것. memcpy와는 다름.
설명 : memcpy와의 차이는 memmove는 메모리를 복사하는데 overlap이 발생하더라도 복사가 가능하다는 점이다.
두 가지 경우를 그림으로 보자.
* src > dest 경우
* src < dest 경우
6. ft_memchr
원형 : void *ft_memchr(const void *str, int c, size_t num)
기능: str이 가진 시작 주소값에서 부터 num만큼의 바이트를 검사하여 c와 겹치는 것이 있을 경우
c부터 시작하는 주소값을 반환한다. 없을 시 null반환.
7. ft_memcmp
원형 : int ft_memcmp(const void *str1, const void *str2, size_t num)
기능: str1과 str2의 내용을 num byte만큼 비교하여 같으면 리턴 값 0, 다르면 (str1 값) - (str2 값)을 반환.
8. ft_strlcpy
원형 : size_t ft_strlcpy(char *dest, const char *src, size_t size)
기능: dest의 메모리 주소에 src의 메모리 주소의 값을 복사한다. size는 dest의 길이를 뜻한다.
설명 : strncpy는 NULL을 보장해주지 않는다. 따라서 이것을 보완하기위해서 strlcpy를 이용한다.
src의 길이값을 리턴해주고 마지막에 NULL을 넣어준다.
9. ft_strlcat
원형 : size_t ft_strlcat(char *dest, const char *src, size_t size)
기능: strcat과 같은 기능을 한다. dest의 기존 데이터에 src를 붙혀 넣는다. 그러나 size < dest길이 + null일 때는 그냥 size에 src길이를 더한 값을 반환한다. 그리고 아무 일도 일어나지 않는다. 그래서 strcat보다 보안이 확실하다.
10. ft_strchr
원형 : char *ft_strchr(const char *str, int c)
기능: str에서 원하는 문자를 찾으면 그 문자의 주소값을 반환. 찾지 못하면 NULL포인터 반환.
11. ft_strrchr
원형 : char *ft_strrchr(const char *str, int c)
기능: str에서 원하는 문자가 제일 마지막으로 나타나는 곳을 찾으면 그 문자의 주소값을 반환.
찾지 못하면 NULL포인터 반환.
설명 : strncpy는 NULL을 보장해주지 않는다. 따라서 이것을 보완하기위해서 strlcpy를 이용한다.
src의 길이값을 리턴해주고 마지막에 NULL을 넣어준다.
12. ft_strnstr
원형: char *ft_strnstr(const char *big, const char *little, size_t len)
기능: big문자열 중에서 len길이만큼 중에서 little이 있는지 확인. 리턴 값은 big의 주솟값.
little이 비어있으면 big 첫 번째 주소, little 찾지 못하면 null, little찾으면 그 부분의 big 주솟값 리턴.
설명 : 리턴 값중 null을 리턴하고 문자열을 출력하면 segment에러가 발생한다. 따라서 0리턴은 주솟값으로 출력해줘야 한다. 나머지 2개의 케이스는 양호하다.
13. ft_strncmp
원형: char *ft_strnstr(const char *big, const char *little, size_t len)
기능: 두 개의 문자열을 처음부터 num까지 비교하여 같으면 0, str1 > str2경우 (+), str1 < str2경우 (-)를 리턴해준다.
설명: 함수에서 보면 같으면 index를 계속 더해주고 만약 다른게 나올 시 2가지 경우가 나올 수 있다. (+),(-)를 상황에 맞 게 반환한다. 그리고 len이 0일 경우는 무조건 같은 것이기때문에 0을 반환한다.
14. ft_malloc
원형 : void *ft_calloc(size_t count, size_t size)
기능 : size의 크기의 변수를 count개 저장할 수 있는 메모리를 할당하고 그것을 0으로 초기화하는 함수.
설명 : 메모리를 할당하기 위해 malloc을 이용한다. Malloc으로 변수에 맞는 바이트를 얼마나 할당할 것인지
Count와 size라는 매개변수로 지정해준다. 그리고 메모리를 할당하고 return해준다. 사용 후 free꼭 해줘야한다.
15. ft_strdup
원형 : char *ft_strdup(const char *str)
기능 : 문자열 str을 인자로 받아서 그것을 메모리를 직접 할당한 곳에 복사를 해주는 함수.
설명 : malloc을 이용하여 문자열이 들어갈 만큼의 메모리를 할당하고 문자열을 복사해서 값을 넣어줌.
Heap영역에 만들어지는 메모리 공간이다. Strcpy는 복사할 문자열이 공간보다 크면 짤리는 경우가 있다.
그러나 strdup는 동적할당을 이용하기 때문에 문자열이 짤리지 않는고 메모리를 효율적으로 활용가능하다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
1. ft_substr
원형 : char *ft_substr(char const *str, unsigned int start, size_t len)
기능 : 문자열 str의 인덱스 중 start부터 len만큼 함수 내부 포인터에 옮기고 그 값을 반환해준다.
설명 : 예외적인 부분이 있다. start > ft_strlen(str)일 경우는 NULL을 반환해준다.
그리고 마지막에 strlcpy를 이용하여 문자열을 반환해준다. strlcpy내부적으로 '\0'을 넣어준다.
2. ft_strjoin
원형 : char *ft_strjoin(char const *s1, char const *s2)
기능 : s1문자열과 s2문자열을 합쳐서 그 문자열을 반환해주는 함수.
3. ft_strtrim
원형 : char *ft_strtrim(char const *s1, char const *set)
기능 : s1문자열 양 끝에 있는 set이라는 문자열 패턴을 삭제하고 난 결과를 리턴해주는 함수.
설명 : 예외적인 부분이 있다. set이 NULL일 경우 s1을 그대로 반환하기 위해 내부적으로 할당을 해주는 strdup함수를 사용하였다. 뒤에서 부터 체크 할 때 체크하는 부분이 시작까지 올 경우,
그리고 (앞에서 체크한 부분) < (뒤에서 체크한 부분) 일 경우를 처리해줘야한다.
4. ft_split
원형 : char **ft_split(char const *s, char c)
기능: 문자열 s를 문자 c를 분기점으로 나눠 이중 포인터로 반환을 해준다.
설명 : 총 4개의 함수로 구성하였다.
1. word_num(원형 : size_t word_num(const char *str, char c))
--> 이중 포인터의 메모리를 할당하기 위해 얼마만큼의 공간이 필요한지 갯수를 세주는 함수.
2. ft_strcpy(원형 : void ft_strcpy(char *dest, char const *src, size_t start, size_t last))
--> 만들어진 이중 포인터에 데이터를 집어넣을 때 쉽게 데이터의 메모리 이동을 할 때 필요한 함수.
3. memfree(원형 : void *mem_free(char **fail_arr, size_t num))
--> 데이터를 집어 넣을 때 할당이 안될 때 전에 할당했던 것을 풀어주는 함수.
4. semi_split(원형 : void semi_split(const char *origin_str, char c, char **split_str))
--> 데이터를 집어 넣는 함수.
5. ft_itoa
원형 : char *ft_itoa(int n)
기능: 매개변수로 들어온 정수 n을 문자열로 바꿔주는 함수.
설명 : 주의 할 점은 n = -2147483648일 경우이다. 나는 이것을 long long으로 변수형을 바꿔 처리했다.
또 다른 방법으로는 예외 함수를 한 개 더 만들어 처리할 수 있다.
5. ft_strmapi
원형 : char *ft_strmapi(char const *s, char (*f)(unsigned int, char))
기능: 문자열 s에 함수 f를 적용할 수 있는 함수.
설명 : 이 함수는 다양한 곳에 응용 될 수 있다. 내가 f라는 함수를 만들면 문자열 s에 적용시킬 수 있다.
예를 들어 a -> b로 b -> c로 바꿀라면 f(1, s[i])를 받아서 s[i] + 1해주는 함수를 만들면 된다.
6. ft_putchar_fd, ft_putstr_fd, ft_putendl_fd, ft_putnbr_fd
설명 : 이 함수들은 내가 파일디스크럽터를 정해줄 수 있다.
* 파일디스크럽터란?
정의 : 리눅스 혹은 유닉스 계열의 시스템에서 프로세스(process)가 파일(file)을 다룰 때 사용하는 개념으로, 프로세스에 서 특정 파일에 접근할 때 사용하는 추상적인 값.
작동 : 프로그램이 프로세스로 메모리에서 실행될 때, 기본적으로 할당되는 파일디스크립터는 표준입력(Standard Input), 표준 출력(Standard Output), 표준에러(Standard Error)이며 이들에게 각각 0, 1, 2라는 정수가 할당.