Search
Duplicate
📚

Libft

Holy Graph
0Circle
간략한 내용
다양한 C 라이브러리 구현 Makefile
적정 기간
1 week
제작에 참여한 사람
진행 중인 사람
최종 편집일
May 08
통과한 사람
1 more property

들어가기 앞서...

libc에 있는 모듈들을 직접 구현해보기
최대한 라이브러리의 의미를 생각하며 구현하기
재사용 가능한 함수들은 최대한 이용하여 라이브러리 내에 static 함수 최소화 하기

1. 팁 및 Tester

1) 구현 순서 가이드

1.
lstnewlstdelonelstclearlstlastlstadd_backlstmap
2.
memsetbzerocalloc
3.
strlcpysubstrstrjoinsplit
4.
memcmpstrnstr
5.
strchrstrtrim

2) const char * vs char const * vs char * const (by )

int main(void) { // s1, s2 equivalent -> cannot change value, afford to change address // s3 -> afford to change value, cannot change address const char *s1 = "123"; char const *s2 = "456"; char *const s3 = "789"; // upper one error // *s1 = '0'; // ++s1; // upper one error // *s2 = '0'; // ++s2; // lower one error // *s3 = '0'; // ++s3; return (0); }
C
복사

3) dest vs dst

destination = source;dest = src; 로 줄여쓰기도 함.

4) Tester

2. libf.a

1) memset

//c header #include <string.h> void* memset(void* dest, int value, size_t size);
C
복사
dest 의 주소부터 size 바이트를 value 값으로 채운다. 이 때, valueunsigned char 로 형변환된다. 따라서 int값으로 초기화는 불가능하다!
int main(void) { int memset_with_0[5]; int memset_with_1[5]; memset(memset_with_0, 0, sizeof(memset_with_0)); memset(memset_with_1, 1, sizeof(memset_with_1)); //memset_with_0 출력 printf("memset_with_0 : "); for (int i = 0; i < 5; i++) printf("%d ", *(memset_with_0 + i)); //memset_with_1 출력 printf("\nmemset_with_1 : "); for (int i = 0; i < 5; i++) printf("%d ", *(memset_with_1 + i)); return 0; }
C
복사
위와 같이 두 배열을 01로 초기화 한다면 아래와 같이 출력이 된다.
0 0 0 0 0 16843009 16843009 16843009 16843009 16843009
Plain Text
복사
결과에서 보이듯이 1로 초기화 하고 싶었지만 기대한 결과값이 나오지 않는다! memset 함수는 1바이트 단위로 값을 초기화 하기 때문이다! 따라서 모든 값을 0으로 초기화하거나 char값으로 초기화 할 때 사용하면 된다.

by &

memsetchar형의 배열에 대한 초기화는 어떤 값을 넣어도 무방하다. 다만 memset 초기화의 대상이 int일 때만 문제가 된다! 아래에서 제시할 것들은 int형 배열에 대한 초기화를 기준으로 제시한 것이다.
memset으로 올바르게 형변환 되어 이용할 수 있는 수는 0-1이다. 01바이트 기준 2진수로 0000000000000000이고, 4바이트로는 0000000000000000000000000000000000000000000000000000000000000000이다. 1바이트 단위로 읽어도 어차피 0으로 초기화 될 수 밖에 없다. -11바이트 기준 2진수로 1111111111111111이고, 4바이트로는 1111111111111111111111111111111111111111111111111111111111111111이다. 이 역시 어차피 -1로 해석이 될 수 밖에 없는 구조를 띈다.
위의 예제에서 int 배열을 1로 초기화 하려고 했을 때, 왜 1이 되지 않는지 살펴보자. memset1바이트 단위로 초기화 시킨다. 그럴 때 4바이트 크기를 갖는 int 데이터 하나는  0000001000000010000000100000001  0000001 00000001 00000001 00000001 과 같은 형태를 띄게 된다.
제일 앞에 0000 생략됨..
2진수로 표현된 값을 확인해보면 위의 그림과 같이 1648300916483009의 값을 가진채로 int 배열이 초기화 되는 것이다. 이를 염두해 두고 memset1바이트 단위의 초기화를 수행하기 때문에 char 형태의 배열에 용의한 것이고, 따라서 string.h에 들어있는 함수인 것도 이 이유 때문임을 유추할 수 있다.

2) bzero

함수 원형

//c header #include <string.h> void bzero(void* dest, size_t size);
C
복사

함수 설명

memset과 같은 역할을 한다. C 언어 비표준이며 deprecated된 함수이므로 사용하지 말자. memsetC 언어 표준함수이며 bzero, ZeroMemory 보다 memset 함수 사용을 권장한다. deprecated 함수가 무엇인지는 아래 링크를 통해 이해할 수 있다.
DESCRIPTION The bzero() function writes n zeroed bytes to the string s. If n is zero, bzero() does nothing.
JavaScript
복사
함수 이름처럼 str 주소값부터 메모리 공간을 size 크기의 바이트만큼 0 으로 채운다.

3) calloc

함수 설명

SYNOPSIS #include <stdlib.h> void* calloc(size_t count, size_t size);
JavaScript
복사
DESCRIPTION : The aligned_alloc() The malloc(), calloc(), valloc(), realloc(), and reallocf() functions allocate memory. The allocated memory is aligned such that it can be used for any data type. The aligned_alloc() function allocates memory with the requested alignment. The free() function frees allocations that were created via the preceding allocation functions. 할당 된 메모리는 모든 데이터 유형에 사용할 수 있도록 정렬됩니다.(alignment = 배열 , be aligned = 배열로 되다.) alignment_alloc () 함수는 요청된 배열로 메모리를 할당합니다. free () 함수는 이전 할당 함수를 통해 생성된 할당을 해제합니다.
JavaScript
복사
DESCRIPTION : calloc The calloc() function contiguously allocates enough space for count objects that are size bytes of memory each and returns a pointer to the allocated memory. The allocated memory is filled with bytes of value zero. calloc () 함수는 각각 메모리의 크기 바이트인 count 객체에 대해 충분한 공간을 연속적으로 할당하고 할당된 메모리에 대한 포인터를 반환합니다. 할당된 메모리는 값이 0인 바이트로 채워집니다.
JavaScript
복사
RETURN VALUES If successful, calloc(), malloc(), realloc(), reallocf(), valloc(), and aligned_alloc() functions return a pointer to allocated memory. If there is an error, they return a NULL pointer and set errno to ENOMEM. -동적할당이 성공하면 calloc (), malloc (), realloc (), reallocf (), valloc ()alignment_alloc () 함수가 할당된 메모리에 대한 포인터를 반환합니다. 오류가 있으면 NULL 포인터를 반환하고 errno를 ENOMEM으로 설정합니다. The free() function does not return a value. -free () 함수는 값을 반환하지 않습니다.
JavaScript
복사

malloc 과 calloc의 사용 방법 차이

SYNOPSIS #include <stdlib.h> void * malloc(size_t size);
JavaScript
복사
char *str = (char*) malloc (sizeof(char) * 10); char *str_2 = (char*) calloc (10, sizeof(char));
JavaScript
복사

NULL과 0과 '\0'의 차이

if(!(calloc_ft = malloc(size * count))) return ('\0'); (x)
JavaScript
복사
if(!(calloc_ft = malloc(size * count))) return (NULL); (o)
JavaScript
복사
문자열에서만 '\0'을 쓴다.
NULL0 주소를 의미하기 때문에 포인터 변수를 초기화 시에 사용한다.
char *ptr = NULLchar *ptr = 0 은 같은 의미라 볼 수 있다.
int a = NULLint a = 0 의 의미는 다르다.
NULL에 관한 추가적인 설명은 아래 링크를 통해 확인할 수 있다.
NULL C Type support Defined in header <stddef.h> Defined in header <string.h> Defined in header <wchar.h> Defined in header <time.h> Defined in header <locale.h> Defined in header <stdio.h> Defined in header <stdlib.h>
C
복사

4) memcpy

함수 원형

//c header #include <string.h> void* memcpy(void* restrict dest, const void* restrict src, size_t size);
C
복사

함수 설명

src가 가리키는 곳 부터 size바이트만큼 dest에 복사한다.

Return Value

dest 를 리턴한다.

5) memccpy

함수 원형

//c header #include <string.h> void* memccpy(void* restrict dest, const void* restrict src, int ch, size_t size);
C
복사

함수 설명

src 가 가리키는 곳 부터 size 바이트만큼 dest에 복사한다. 만약 src에서 문자 ch를 만나면 ch까지만 복사를 진행하고 복제를 중단한다.

Return Value

복사된 dest변수에서 복사가 끝난 다음 주소를 리턴한다. 만약 문자 ch를 만나지 않았다면, size 바이트를 복사하고 NULL을 리턴한다.

6) memmove

함수 원형

//c header #include <string.h> void* memmove(void* dest, const void* src, size_t size);
C
복사

함수 설명

src 가 가리키는 곳 부터 size 바이트 만큼 dest 가 가리키는 곳으로 옮긴다. 버퍼를 이용하므로 destsrc 가 겹쳐도 문제 없다.

Return Value

dest 를 리턴한다.

7) memchr

함수 원형

//c header #include <string.h> void* memchr(const void* dest, int ch, size_t size);
C
복사

함수 설명

dest 가 가리키는 곳 부터 size 바이트 까지 중 처음으로 ch 와 일치하는 값을 찾는다. chunsigned char로 해석된다.

Return Value

문자 ch 를 만났다면 해당 주소를 리턴한다. 만약 문자 ch를 만나지 않았다면 NULL을 리턴한다.

8) memcmp

함수 원형

//c header #include <string.h> int memcmp(const void* ptr1, const void* ptr2, size_t size);
C
복사

함수 설명

두 메모리 블록을 비교한다. ptr1이 가리키는 size바이트의 데이터와 ptr2가 가리키는 size바이트의 데이터를 비교한다.

Return Value

두 메모리 블록이 같으면 0을 리턴한다.
두 메모리 블록이 같지 않다면 *ptr1 - *ptr2 값을 리턴한다.
→ 두 메모리 블록이 다른 곳에서 ptr1의 값이 더 크면 0 보다 큰 값을 리턴한다.
→ 두 메모리 블록이 다른 곳에서 ptr2의 값이 더 크면 0 보다 작은 값을 리턴한다.

테스트 케이스

const char s1[] = "atoms\0\0\0\0"; // extra null bytes at end const char s2[] = "atoms\0abc";
C
복사

9) strlcpy

함수 원형

//c header #include <string.h> size_t strlcpy(char* dest, const char* src, size_t size);
C
복사

함수 설명

원리는 strncpy와 비슷하지만 strncpy함수보다 오류가 적은 함수이다.
strncpy의 경우 NULL 문자 삽입을 보장하지 않는다.
strlcpysize0이 아닌 경우 size - 1 까지 복사를 진행하고 마지막에 NULL을 삽입해준다.

Return Value

src의 길이를 리턴한다.

10) strlen

함수 원형

//c header #include <string.h> size_t strlen(const char* str);
C
복사

함수 설명

문자열 str의 길이를 구한다. 아래와 같은 구문에서는 100을 리턴하지 않고 12를 리턴하게 된다.
char str[100] = "Hello World!";
C
복사
strlen 함수는 문자열의 마지막 NULL 문자에 의해 길이를 결정하기 때문이다!

Return Value

문자열의 길이(부호없는 정수형)을 리턴한다.

11) strlcat

함수 원형

//c header #include <string.h> size_t strlcat(char* dest, const char* src, size_t size);
C
복사

함수 설명

dest의 마지막 위치에 size - strlen(dest) - 1 만큼 복사하고 끝에 NULL을 삽입한다.

Return Valu e

sizedest의 크기보다 작을 때, strlen(src) + size를 리턴한다.
sizedest의 크기보다 클 때, strlen(src) + strlen(dest)를 리턴한다.

12) strchr

함수 원형

#include <string.h> char* strchr(const char *s, int c);
C
복사

함수 설명

s가 가리키는 문자열에서 첫 번째 c (char로 변환)를 찾는다. c는 검색할 문자를 의미하고 int로 형 변환 되어서 전달되지만, 함수 내부적으로 다시 char로 처리된다. 마지막 NULL 문자도 문자열의 일부로 간주하기 때문에 이 함수는 문자열의 맨 끝 부분을 가리키는 포인터를 얻기 위해 사용할 수도 있다.

Return Value

s 에서 검색한 문자가 가장 먼저 나타나는 곳을 가리키는 포인터를 리턴한다. 만일 문자가 없다면 NULL 포인터를 리턴한다.

13) strrchr

함수 원형

#include <string.h> char* strrchr(const char *s, int c);
C
복사

함수 설명

s가 가리키는 문자열에서 마지막 c (char로 변환)를 찾는다. c는 검색할 문자를 의미하고 int로 형 변환 되어서 전달되지만, 함수 내부적으로 다시 char로 처리된다. 마지막 NULL 문자도 문자열의 일부로 간주하기 때문에 이 함수는 문자열의 맨 끝 부분을 가리키는 포인터를 얻기 위해 사용할 수도 있다.

Return Value

s 에서 문자열의 끝 부분부터 검색하는데, 찾고자 하는 문자가 가장 먼저 나타나는 곳을 가리키는 포인터를 리턴한다. 만일 문자가 없다면 NULL 포인터를 리턴하게 된다.

14) strnstr

함수 원형

#include <string.h> char* strnstr(const char *haystack, const char *needle, size_t len);
C
복사

함수 설명

문자열 haystack에서 NULL로 끝나는 문자열 needle의 첫 번째 부분을 찾는다. 여기서 haystacklen 문자 이하로 검색된다. NULL 문자 뒤에 나타나는 문자는 검색되지 않는다.

Return Value

만약 needle값이 비어 있으면 haystack를 반환합니다.
haystack문자열에서 needle 문자열을 찾지 못하면 NULL을 반환합니다.
needle 문자열을 찾으면, haystack에서 needle 문자열 시작 부분 위치 주소를 반환합니다.

테스트 케이스

#include<string.h> #include<stdio.h> int main() { char *haystack = "This"; char *needle = "is"; char *k = strnstr(haystack, needle, 4); printf("%c", *k); // output : i return (0); }
C
복사
#include<string.h> #include<stdio.h> int main() { char *haystack = "This"; char *needle = "is"; char *k = strnstr(haystack, needle, 3); printf("%c", *k); // output : segmentation fault return (0); }
C
복사
#include <stdio.h> #include <string.h> int main (void) { char str1[10] = "book"; char str2[5] = "oo"; char str3[5] = "o"; char str4[5] = "go"; char str5[5] = "og"; char str5[5] = "ob"; char str6[5] = "ookg"; printf("book - oo : %p\n", strnstr(str1, str2, 4)); printf("book - o : %p\n", strnstr(str1, str3, 4)); printf("book - go : %p\n", strnstr(str1, str4, 4)); printf("book - og : %p\n", strnstr(str1, str5, 4)); printf("book - ob : %p\n", strnstr(str1, str5, 4)); printf("book - ookg : %p\n", strnstr(str1, str6, 4)); printf("book - oo - 0byte : %p\n", strnstr(str1, str2, 0)); return (0); }
C
복사
book - oo : 0x7ffee3c9daef book - o : 0x7ffee3c9daef book - go : 0x0 book - og : 0x0 book - ob : 0x0 book - ookg : 0x0 book - oo - 0byte : 0x0
C
복사

15) strncmp

함수 원형

#include <string.h> int strncmp(const char *s1, const char *s2, size_t n);
C
복사

함수 설명

strncmp 함수는 문자열을 n자 이하로 비교한다. s1, s2는 각각 서로 비교할 문자열들이다. n은 (처음부터) 비교할 최대 문자의 개수이다. 매뉴얼에 쓰여 있는 lexicographically의 뜻은 아래와 같다. 더 자세한 것은 아래 링크를 참고하자.
DESCRIPTION The strcmp() and strncmp() functions lexicographically compare the null-terminated strings s1 and s2.

Return Value

만일 n개의 문자가 모두 일치한다면, 0을 리턴한다.
비교한 n개의 문자 중 최초로 일치하지 않는 문자의 값이 s1이 더 큰 경우 0보다 큰 값을, s2가 더 큰 경우 0보다 작은 값을 리턴합니다.

테스트 케이스

const char s1[] = "atoms\0\0\0\0"; // extra null bytes at end const char s2[] = "atoms\0abc";
C
복사

16) atoi

함수 원형

#include <stdlib.h> int atoi(const char *str);
C
복사

함수 설명

궁극적인 목표는 숫자로 표현되는 문자열의 초기 부분을 str에서 int로 변환하는 것이다. 숫자로 표현할 수 있는 문자가 나오기 전까지 공백 문자들을 모두 무시한다. 공백 문자를 무시한 후, 주어지는 문자들이 부호 혹은 숫자가 아니라면 변환이 이뤄지지 않는다. 또한 문자열이 공백 문자로만 이루어져 있어도 변환이 이루어 지지 않는다. 변환에 숫자를 이용하고, 더 이상 숫자가 나오지 않는다면 변환을 마치게 된다.

Return Value

부호를 처리한 int형 정수

테스트 케이스

printf("%d", ft_atoi("22433723768547758107")); printf("%d", ft_atoi("9223372036854775808")); printf("%d", ft_atoi("9223372036854775808"));
C
복사

17) isalpha

함수 원형

#include <ctype.h> int isalpha(int c);
C
복사

함수 설명

어떤 문자에 대해서 알파벳인지 판단한다. 매개 변수의 자료형이 char가 아닌 int인 이유는 toupper에서 볼 수 있다.

Return Value

알파벳이 아니라면 0 리턴
알파벳이라면 0이 아닌 정수 리턴 → 컴파일러나 버전에 따라 다름
→ 대문자인 경우 1 리턴, 소문자인 경우 2 리턴, 알파벳이 아닌 경우 0 리턴
→ 알파벳인 경우 1 리턴, 알파벳이 아닌 경우 0 리턴

18) isdigit

함수 원형

#include <ctype.h> int isdigit(int c);
C
복사

함수 설명

매개 변수 c에 들어오는 값이 숫자인지 판단한다. 그렇다면 아래 예시를 확인해보자.
#include <ctype.h> int main(void) { printf("%d\n", isdigit(3)); printf("%d\n", isdigit(a)); return (0); }
C
복사
숫자가 아니라면 0 리턴, 숫자라면 1 리턴이라는 관점에서 아래와 같은 결과를 기대할수도 있겠지만 그렇지 않다.
1 0
C
복사
실제 결과는 아래와 같다.
0 0
C
복사
isdigit 함수는 숫자인지 아닌지를 판단한다고 했다. 여기서의 숫자란 아스키 코드의 숫자를 말한다. 즉, '0' ~ '9'(48 ~ 57)에 해당하는지 확인한다.
따라서 아래의 예시의 결과는 다음과 같다
#include <ctype.h> #include <stdio.h> int main(void) { printf("%d\n", isdigit('1')); printf("%d\n", isdigit(1)); printf("%d\n", isdigit(49)); return (0); }
C
복사
1 0 1
C
복사

Return Value

숫자가 아니라면 0 리턴
숫자라면 1 리턴

19) isalnum

함수 원형

#include <ctype.h> int isalnum(int c);
C
복사

함수 설명

c가 알파벳 또는 숫자인지 확인한다.

Return Value

알파벳 또는 숫자이면 0이 아닌 값을 반환
둘 다 해당하지 않으면 0 반환

테스트 케이스

#include <ctype.h> #include <stdio.h> int main(void) { printf("%d\n", isalnum('a')); printf("%d\n", isalnum('!')); printf("%d\n", isalnum('1')); printf("%d\n", isalnum(1)); printf("%d\n", isalnum(49)); return (0); }
C
복사
1 0 1 0 1
C++
복사

20) isascii

함수 원형

#include <ctype.h> int isascii(int c);
C
복사

함수 설명

c아스키 문자인지 확인한다. 0~127 사이의 값을 말한다.

Return Value

아스키 문자라면 0이 아닌 값을 반환
아스키 문자가 아니라면 0을 반환

테스트 케이스

#include <ctype.h> #include <stdio.h> int main(void) { printf("%d\n", isascii('a')); printf("%d\n", isascii('!')); printf("%d\n", isascii('1')); printf("%d\n", isascii(0)); printf("%d\n", isascii(49)); printf("%d\n", isascii(128)); return (0); }
C++
복사
1 1 1 1 1 0
C
복사

21) isprint

함수 원형

#include <ctype.h> int isprint(int c);
C
복사

함수 설명

c가 공백을 포함하여 출력 가능한 문자인지 확인한다. 32 ~ 126 사이의 값을 말한다.

Return Value

출력 가능한 문자이면 0이 아닌 정수를 반환
그렇지 않으면 0을 반환

테스트 케이스

#include <ctype.h> #include <stdio.h> int main(void) { printf("%d\n", isprint('a')); printf("%d\n", isprint('!')); printf("%d\n", isprint('1')); printf("%d\n", isprint(0)); printf("%d\n", isprint(49)); printf("%d\n", isprint(128)); printf("%d\n", isprint(127)); //del printf("%d\n", isprint(32)); //공백 return (0); }
C++
복사
1 1 1 0 1 0 0 1
C
복사

22) toupper

함수 원형

#include <ctype.h> int toupper(int c);
C
복사

함수 설명

c로 들어온 값이 소문자에 해당한다면 이를 대문자로 변환한다. 이 때 매개 변수의 자료형이 char가 아닌 int인 이유는 EOF를 처리 해야하기 때문이다. char-128에서 127까지의 범위를 갖고 있으므로, 총 256개의 표현을 할 수 있는 타입이다. 따라서 char를 받게 되면 총 256가지의 경우로 반환을 할 수 있게 되는데, 이에 대해선 아스키 코드 및 확장에 대해서만 표현할 수 있기 때문에 EOF에 대해서는 처리 불가하게 된다. 결국, 256가지 (아스키 코드 및 확장)에 추가로 1가지 (EOF)를 처리하기 위해서는 int 타입이 필요하다.
EOFEnd Of File의 약자로 더 이상 데이터가 없음을 지칭한다. 따라서 파일의 끝을 나타내기 위해 사용되며, 파일의 끝에 도달했을 때 언제나 특별한 값을 반환하도록 만들어져 있다. (보통 -1을 반환한다.)

Return Value

소문자에 대응하는 대문자
소문자에 대응하는 대문자가 없으면, 매개 변수를 그대로 리턴

23) tolower

함수 원형

#include <ctype.h> int tolower(int c);
C
복사

함수 설명

c로 들어온 값이 대문자에 해당한다면 이를 소문자로 변환한다. 이 때 매개 변수의 자료형이 char가 아닌 int인 이유는 EOF를 처리 해야하기 때문이다. char-128에서 127까지의 범위를 갖고 있으므로, 총 256개의 표현을 할 수 있는 타입이다. 따라서 char를 받게 되면 총 256가지의 경우로 반환을 할 수 있게 되는데, 이에 대해선 아스키 코드 및 확장에 대해서만 표현할 수 있기 때문에 EOF에 대해서는 처리 불가하게 된다. 결국, 256가지 (아스키 코드 및 확장)에 추가로 1가지 (EOF)를 처리하기 위해서는 int 타입이 필요하다.
EOFEnd Of File의 약자로 더 이상 데이터가 없음을 지칭한다. 따라서 파일의 끝을 나타내기 위해 사용되며, 파일의 끝에 도달했을 때 언제나 특별한 값을 반환하도록 만들어져 있다. (보통 -1을 반환한다.)

Return Value

대문자에 대응하는 소문자
대문자에 대응하는 소문자가 없으면, 매개 변수를 그대로 리턴

3. makefile

# **************************************************************************** # # # # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # # By: jseo <jseo@student.42seoul.kr> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/12/22 14:44:25 by jseo #+# #+# # # Updated: 2021/01/01 00:47:04 by jseo ### ########.fr # # # # **************************************************************************** # NAME = libft.a SRCS = ft_atoi.c \ ft_bzero.c \ ft_calloc.c \ ft_isalnum.c \ ft_isalpha.c \ ft_isascii.c \ ft_isdigit.c \ ft_isprint.c \ ft_itoa.c \ ft_memccpy.c \ ft_memchr.c \ ft_memcmp.c \ ft_memcpy.c \ ft_memmove.c \ ft_memset.c \ ft_putchar_fd.c \ ft_putendl_fd.c \ ft_putnbr_fd.c \ ft_putstr_fd.c \ ft_split.c \ ft_strchr.c \ ft_strdup.c \ ft_strjoin.c \ ft_strlcat.c \ ft_strlcpy.c \ ft_strlen.c \ ft_strmapi.c \ ft_strncmp.c \ ft_strnstr.c \ ft_strrchr.c \ ft_strtrim.c \ ft_substr.c \ ft_tolower.c \ ft_toupper.c BNS_SRCS = ft_lstsize.c \ ft_lstadd_back.c \ ft_lstadd_front.c \ ft_lstclear.c \ ft_lstdelone.c \ ft_lstiter.c \ ft_lstlast.c \ ft_lstmap.c \ ft_lstnew.c OBJS = $(SRCS:%.c=%.o) BNS_OBJS = $(BNS_SRCS:%.c=%.o) FLAGS = -Wall -Wextra -Werror $(NAME) : $(OBJS) gcc $(FLAGS) -c $(SRCS) -I./ ar rc $(NAME) $(OBJS) all : $(NAME) bonus : $(NAME) gcc $(FLAGS) -c $(BNS_SRCS) -I./ ar rc $(NAME) $(BNS_OBJS) clean : rm -f $(OBJS) $(BNS_OBJS) fclean : clean rm -f $(NAME) re : fclean all .PHONY : all clean fclean re
Plain Text
복사

4. libft.h

/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* libft.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: jseo <jseo@student.42seoul.kr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/12/22 15:13:53 by jseo #+# #+# */ /* Updated: 2020/12/25 20:20:54 by jseo ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef LIBFT_H # define LIBFT_H # include <stdlib.h> # include <unistd.h> typedef struct s_list { void *content; struct s_list *next; } t_list; int ft_atoi(const char *s); void ft_bzero(void *s, size_t n); void *ft_calloc(size_t cnt, size_t n); int ft_isalnum(int c); int ft_isalpha(int c); int ft_isascii(int c); int ft_isdigit(int c); int ft_isprint(int c); char *ft_itoa(int n); void *ft_memccpy(void *dst, const void *src, int c, size_t n); void *ft_memchr(const void *s, int c, size_t n); int ft_memcmp(const void *s1, const void *s2, size_t n); void *ft_memcpy(void *dst, const void *src, size_t n); void *ft_memmove(void *dst, const void *src, size_t n); void *ft_memset(void *s, int c, size_t n); void ft_putchar_fd(char c, int fd); void ft_putendl_fd(char *s, int fd); void ft_putnbr_fd(int n, int fd); void ft_putstr_fd(char *s, int fd); char **ft_split(char const *s, char c); char *ft_strchr(const char *s, int c); char *ft_strdup(const char *s); char *ft_strjoin(char const *s1, char const *s2); size_t ft_strlcat(char *dst, const char *src, size_t dstsize); size_t ft_strlcpy(char *dst, const char *src, size_t dstsize); size_t ft_strlen(const char *s); char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); int ft_strncmp(const char *s1, const char *s, size_t n); char *ft_strnstr(const char *s1, const char *set, size_t n); char *ft_strrchr(const char *s, int c); char *ft_strtrim(char const *s1, char const *set); char *ft_substr(char const *s, unsigned int start, size_t len); int tolower(int c); int toupper(int c); int ft_lstsize(t_list *lst); void ft_lstadd_back(t_list **lst, t_list *new); void ft_lstadd_front(t_list **lst, t_list *new); void ft_lstclear(t_list **lst, void (*del)(void *)); void ft_lstdelone(t_list *lst, void (*del)(void *)); void ft_lstiter(t_list *lst, void (*f)(void *)); t_list *ft_lstlast(t_list *lst); t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); t_list *ft_lstnew(void *content); #endif
C
복사

1) #ifndef

두 헤더 파일을 함께 include하게 되면 오류가 발생된다. 이 때 #ifndef, #define, #endif를 이용하여 중복포함이 방지된다.
memory.h : memset, memcmp, memcpy .... 가 정의 되어있다.
string.h : memset, memcmp, memcpy, memmove....가 정의 되어있다.

2) #ifndef를 이용한 헤더 파일의 중복 문제 방지

/* header1.h */ #ifndef HEADER_H #define HEADER_H { printf("Hi\n"); #endif
C
복사
/* header2.h */ #include "header1.h" return (0) }
C
복사
/* main.c */ #include <stdio.h> int main(void) #include "header1.h" #include "header2.h"
C
복사
/* main.c */ #include <stdio.h> int main(void) #include "header1.h"// 매크로 심볼이 정의되어 있지 않은 상태 // #ifndef HEADER_H 이후 수행 // #define에서 HEADER_H를 정의 #include "header2.h"// 매크로 심볼이 정의되어 있는 상태 // #include ""header1.h"를 수행 // #ifndef 조건에 맞지 않음 // #ifndef HEADER_H 이후 수행하지 않음 // #endif 로 바로 나옴 // #include "header2.h" 내의 #include "header1.h" 수행하지 않음
C
복사