Makefile
을 이용하면 일일이 gcc
명령어를 사용하지 않고 컴파일을 진행할 수 있고, Incremental build
기능은 전과 후를 비교해 이전과 차이가 없는 대상은 컴파일하지 않는다. 즉, 차이가 생긴 대상만 컴파일을 진행시킬 수 있다.ar(archive)
은 묶음파일을 만들고 조작하고 추출한다새로운 오브젝트 파일이면 추가, 기존 파일이면 치환함.
인덱스를 생성하지 않으면 링크 속도가 느려지고, 시스템 환경에 따라서는 에러가 발생.
void *ft_memset(void *s, int c, size_t n);
#include "libft.h"
void *ft_memset(void *s, int c, size_t n)
{
size_t idx;
idx = 0;
while (idx < n)
{
*((unsigned char *)s + idx) = c;
idx++;
}
return (s);
}
메모리 주소의 시작점부터 n
바이트만큼 c
값으로 채우는 함수
void ft_bzero(void *s, size_t n);
#include "libft.h"
void ft_bzero(void *s, size_t n)
{
size_t idx;
idx = 0;
while (idx < n)
{
*((unsigned char *)s + idx) = 0;
idx++;
}
}
n
바이트만큼 0
으로 채우는 함수void *ft_memcpy(void *dest, const void *src, size_t n);
#include "libft.h"
void *ft_memcpy(void *dest, const void *src, size_t n)
{
unsigned char *d;
const unsigned char *s;
d = dest;
s = src;
if (dest == '\0' && src == '\0')
return (0);
while (n--)
*d++ = *s++;
return (dest);
}
src
가 가르키는 메모리에 접근해서 n바이트 만큼 dest가 가르키는 메모리에 복사하는 함수src
의 null 문자 종료
를 고려하지 않는다.n
바이트 만큼 복사한다.memmove
를 사용해야한다.memcpy
와 strcpy
의 차이는 byte string, string이므로 null
값을 고려해야한다.void *ft_memccpy(void *dest, const void *src, int c, size_t n);
#include "libft.h"
void *ft_memccpy(void *dest, const void *src, int c, size_t n)
{
unsigned char *d;
const unsigned char *s;
unsigned char find;
d = dest;
s = src;
find = c;
while (n--)
{
*d = *s;
if (*s == find)
return (d + 1);
d++;
s++;
}
return (NULL);
}
src
데이터에서 n
바이트만큼 dest
에 복사한다.src
데이터에서 문자 c
가 있다면 복사를 중단하고 dest
의 다음 번지를 return
한다. c
를 찾지 못하고 n
바이트만큼 복사를 마치면 NULL
을 return
한다.void *ft_memmove(void *dest, const void *src, size_t n);
#include "libft.h"
void *ft_memmove(void *dest, const void *src, size_t n)
{
unsigned char *new_d;
unsigned char *new_s;
if (dest == src || n == 0)
return (dest);
if (dest < src)
{
new_d = (unsigned char *)dest;
new_s = (unsigned char *)src;
while (n--)
*new_d++ = *new_s++;
}
else
{
new_d = (unsigned char *)dest + (n - 1);
new_s = (unsigned char *)src + (n - 1);
while (n--)
*new_d-- = *new_s--;
}
return (dest);
}
n
바이트만큼 복사할 때 사용한다.src
와 dest
의 메모리 영역과 겹치지 않는 메모리 영역부터 먼저 복사하기 때문에. dest
와 src
가 overlap
되는 경우에도 데이터를 안전하게 복사 할 수 있다는 점이 memcpy
와 다르다.void *ft_memchr(const void *s, int c, size_t n);
void *ft_memchr(const void *s, int c, size_t n)
{
unsigned char find;
unsigned char *ptr;
find = c;
ptr = (unsigned char *)s;
while (n--)
{
if (*ptr == find)
return ((void *)ptr);
ptr++;
}
return (NULL);
}
s
가 가르키는 메모리 블록에서 n
바이트까지 문자 c
가 있는지 탐색한다. 문자 c
를 처음으로 찾은 주소를 return
하고, 없다면 NULL
을 return
한다. c
를 찾은 주소를 return
할 때 return (ptr);
로 작성해 발생한 오류이다. void
로 형변환을 해주고 반환하기 위해 return (void *)prt
로 바꿔 해결했다.int ft_memcmp(const void *s1, const void *s2, size_t n);
#include "libft.h"
int ft_memcmp(const void *s1, const void *s2, size_t n)
{
unsigned char *u1;
unsigned char *u2;
int idx;
u1 = (unsigned char *)s1;
u2 = (unsigned char *)s2;
idx = 0;
while (n--)
{
if (u1[idx] != u2[idx])
return (u1[idx] - u2[idx]);
idx++;
}
return (0);
}
s1
, s2
가 가르키는 메모리의 시작점부터 n
바이트까지 값을 비교하는 함수이다.n
바이트까지 동일하다면 0
을 return
하고, 일치하지 않으면 해당 바이트에서의 unsigned char
로 해석했을 때 s1
이 더 크다면 0
보다 큰 값을 반환하고, 작다면 0
보다 작은 값을 반환한다.strncmp
와 memcmp
가 다른 점은 strncmp
의 경우 s1
과 s2
둘 중 하나가 NULL
인 경우 n
바이트까지 비교하지 않고, 그 때의 값을 비교하지만 memcmp
는 NULL
인 경우를 고려하지 않고 n
바이트까지 비교한다.size_t ft_strlen(const char *s);
#include "libft.h"
size_t ft_strlen(const char *s)
{
size_t idx;
idx = 0;
while (s[idx])
idx++;
return (idx);
}
size_t ft_strlcpy(char *dst, char *src, size_t size);
#include "libft.h"
size_t ft_strlcpy(char *dst, char *src, size_t size)
{
size_t idx;
idx = 0;
if (!dst || !src)
return (0);
if (!size)
return (ft_strlen(src));
while (src[idx] && idx < size - 1)
{
dst[idx] = src[idx];
idx++;
}
dst[idx] = '\0';
return (ft_strlen(src));
}
size - 1
만큼 src
의 데이터를 dest
로 복사한 후, src
의 길이를 반환하는 함수dest
문자열은 반드시 NULL
로 종료한다.size_t ft_strlcat(char *dst, const char *src, size_t size);
#include "libft.h"
size_t ft_strlcat(char *dst, const char *src, size_t size)
{
size_t idx;
size_t dst_len;
size_t src_len;
dst_len = ft_strlen(dst);
src_len = ft_strlen(src);
if (size < dst_len + 1)
return (src_len + size);
idx = 0;
while (src[idx] && idx < size - dst_len - 1)
{
dst[dst_len + idx] = src[idx];
idx++;
}
dst[dst_len + idx] = '\0';
return (dst_len + src_len);
}
src
의 메모리의 시작점부터 최대 size - dst_len - 1
개까지 dst
의 뒷 부분에 복사한다.dest
문자열은 반드시 NULL
로 종료시킨다.size
가 dst_len
보다 작거나 같다면 src_len + size
를 반환한다.size
가 dst_len
보다 크다면 복사가 이루어지고 dst_len + src_len
을 반환한다.char *ft_strchr(const char *s, int c);
#include "libft.h"
char *ft_strchr(const char *s, int c)
{
char find;
int idx;
find = (unsigned char)c;
idx = 0;
while (s[idx])
{
if (s[idx] == find)
return ((char *)s + idx);
idx++;
}
if (s[idx] == find)
return ((char *)s + idx);
return (0);
}
NULL
포인터를 반환한다.NULL
문자도 찾는 문자 c
가 될 수 있기때문에 문자열의 마지막 위치를 찾을 때 사용하기도 한다.char *ft_strrchr(const char *s, int c);
#include "libft.h"
char *ft_strrchr(const char *s, int c)
{
char find;
int idx;
int s_len;
s_len = ft_strlen(s);
find = c;
idx = s_len - 1;
if (s[idx + 1] == find)
return ((char *)s + idx + 1);
while (s_len--)
{
if (s[idx] == find)
return ((char *)s + idx);
idx--;
}
return (0);
}
NULL
포인터를 반환한다.NULL
문자도 찾는 문자 c
가 될 수 있기때문에 문자열의 마지막 위치를 찾을 때 사용하기도 한다.char *ft_strnstr(const char *big, const char *little, size_t len);
#include "libft.h"
char *ft_strnstr(const char *big, const char *little, size_t len)
{
size_t l_len;
l_len = ft_strlen(little);
if (*big == '\0')
return (NULL);
if (*little == '\0')
return ((char *)big);
while (len-- >= l_len && *big != '\0')
{
if (*big == *little && ft_strncmp(big, little, l_len) == 0)
return ((char *)big);
big++;
}
return (NULL);
}
big
문자열의 len
길이 중에서 little
과 일치하는 영역을 찾고, 그 시작 위치를 반환하는 함수big
이 비어있거나 동일한 영역이 없다면 NULL
을 반환한다.little
이 비어있다면 big
의 시작 위치를 반환한다.len
이 little
의 길이보다 작다면 비교하는 의미가 없으므로 NULL
을 반환한다.const char big = "";
const char little = "";
ft_strnstr: 0x0 (NULL)
strnstr: 0x10bdbff8c (big의 포인터 주소)
/* 9번 라인에 위치한 코드로 인해 NULL을 반환해버렸던 것... */
if (*big == '\0')
return (NULL);
/* 문제가된 조건을 수정하고 while, if 문의 코드를 좀 더 간결하게 다듬었다. */
char *ft_strnstr(const char *big, const char *little, size_t len)
{
size_t l_len;
if (*little == '\0')
return ((char *)big);
l_len = ft_strlen(little);
while (*big && l_len <= len--)
{
if (!ft_strncmp(big, little, l_len))
return ((char *)big);
big++;
}
return (NULL);
}
int ft_atoi(const char *nptr);
#include "libft.h"
int ft_isspace(char c)
{
if (c == ' ' || c == '\t' || c == '\n' || c == '\v' || \
c == '\r' || c == '\f')
return (1);
else
return (0);
}
int ft_atoi(const char *nptr)
{
long nbr;
long minus;
int idx;
nbr = 0;
minus = 1;
idx = 0;
while (ft_isspace(nptr[idx]) && nptr[idx] != '\0')
idx++;
if (nptr[idx] == '-')
minus = -1;
if (nptr[idx] == '+' || nptr[idx] == '-')
idx++;
while (nptr[idx] != '\0' && ('0' <= nptr[idx] && nptr[idx] <= '9'))
{
nbr = (nbr * 10) + (nptr[idx] - '0');
if (nbr > 2147483647 && minus == 1)
return (-1);
if (nbr > 2147483648 && minus == -1)
return (0);
idx++;
}
return (minus * nbr);
}
문자열
을 정수
로 변환하는 함수ft_isspace(char c)
함수를 통해 문자열의 공백을 탐색한다.+
와 -
부호에 대한 처리를 해줘야한다.0과 9 사이의 문자가 아닌 경우
와 NULL
값을 만나기 전까지 탐색한다.int
의 음수
범위인 -2147483648
은 양수
로 표현이 불가능하므로 따로 예외 처리함.int ft_isalpha(int c);
#include "libft.h"
int ft_isalpha(int c)
{
if ((65 <= c && c <= 90) || (97 <= c && c <= 122))
return (1);
return (0);
}
c
가 alphabat
인지 검사하여 1
과 0
으로 반환하는 함수isdigit, isalnum, isascii, isprint도 동일한 원리로 구현
int ft_toupper(int c);
#include "libft.h"
int ft_toupper(int c)
{
if (97 <= c && c <= 122)
return (c - 32);
return (c);
}
c
가 소문자에 해당되면 대문자로 변환하는 함수tolower는 대문자에 해당되면 소문자로 변환하는 함수
void *ft_calloc(size_t nmemb, size_t size);
#include "libft.h"
void *ft_calloc(size_t nmemb, size_t size)
{
void *p;
p = malloc(nmemb * size);
if (!p)
return (p);
ft_bzero(p, nmemb * size);
return (p);
}
size
크기의 변수를 nmemb
개 만큼 저장할 수 있는 메모리 공간을 할당하고 할당된 공간을 0
으로 초기화한다.nmemb: number of members
. 즉, count라고 생각하면된다.char *ft_strdup(const char *s)
char *ft_strdup(const char *s)
{
int s_len;
int idx;
char *p;
s_len = ft_strlen(s);
p = (char *)malloc(sizeof(char) * (s_len + 1));
if (!p)
return (NULL);
idx = 0;
while (s[idx])
{
p[idx] = s[idx];
idx++;
}
p[idx] = '\0';
return (p);
}
s
를 복사한 후에 복사된 문자열을 가르키는 포인터를 반환하는 함수strdup
는 malloc
을 사용해 문자열을 복사하기때문에 사용하지 않으면 free
로 메모리를 해제해줘야한다.