#include "libft.h"
int ft_isalpha(int c)
{
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}
a~z, A~Z 라면 return 1, 아니라면 return 0
#include "libft.h"
int ft_isdigit(int c)
{
return (c >= '0' && c <= '9');
}
0~9라면 return 1, 아니라면 return 0
#include "libft.h"
int ft_isalnum(int c)
{
return (ft_isdigit(c) || ft_isalpha(c));
}
if (isdigit && isalpha) return 1
#include "libft.h"
int ft_isascii(int c)
{
return (c >= 0 && c <= 127);
}
ascii값 이내라면 return 1
#include "libft.h"
int ft_isprint(int c)
{
return (c >= 32 && c <= 126);
}
ascii 값 내에서 출력 가능한 값이라면 return 1
#include "libft.h"
size_t ft_strlen(const char *s)
{
size_t i;
i = 0;
while (s[i])
i++;
return (i);
}
문자열의 길이 반환함수
#include "libft.h"
void *ft_memset(void *b, int c, size_t len)
{
size_t i;
i = 0;
while (i < len)
{
((unsigned char *)b)[i] = (unsigned char)c;
i++;
}
return (b);
}
주어지는 길이만큼 주어지는 공간에 주어지는 정수값으로 초기화 하는 함수
memset은 1바이트씩 이동하면서 값을 할당하는 포인터 연산을 해야하는데 usigned char 자료형을 사용하는
이유는 1바이트씩 증가시키기 위해서 char or unsigned char를 사용하는데 일반 char 을 사용하는 경우 음수로 인한 예외를 막기 위해서 usigned char을 사용함
#include "libft.h"
void ft_bzero(void *s, size_t n)
{
ft_memset(s, 0, n);
}
n 만큼 0으로 초기화
#include "libft.h"
void *ft_memcpy(void *dst, const void *src, size_t n)
{
size_t i;
i = 0;
if (dst == 0 && src == 0)
return (NULL);
while (i < n)
{
((unsigned char *)dst)[i] = ((unsigned char *)src)[i];
i++;
}
return (dst);
}
메모리의 일부분을 복사함.
strcpy같은 경우는 문자의 값에 따라서 함수가 종료되고, memscpy는 지정한 byte수에 따라서 함수가 종료가 됨
#include "libft.h"
void *ft_memmove(void *dst, const void *src, size_t len)
{
unsigned char *buf_src;
unsigned char *buf_dst;
size_t i;
i = 0;
buf_src = (unsigned char *)src;
buf_dst = (unsigned char *)dst;
if (dst == 0 && src == 0)
return (NULL);
while (i < len)
{
if (src > dst)
buf_dst[i] = buf_src[i];
else
buf_dst[len - 1 - i] = buf_src[len - 1 - i];
i++;
}
return (buf_dst);
}
메모리 이동 함수
복사할 것을 버퍼에 복사하고, 해당 위치에 가서 버퍼에 복사 된 것을 붙여넣음
메모리를 src에서 dst로 len 바이트 길이 만큼 복사함
memcpy 와 memmove의 차이점은 memcpy는 바로 붙여넣지만 memmove는 버퍼에 저장해놨다가 붙여넣는다. 안정성으로는 memmove가 뛰어나다
#include "libft.h"
size_t ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t srcsize;
size_t i;
srcsize = ft_strlen(src);
i = 0;
if (!dst || !src)
return (0);
if (dstsize == 0)
return (srcsize);
while (src[i] && i + 1 < dstsize)
{
dst[i] = src[i];
i++;
}
dst[i] = '\0';
return (srcsize);
}
src를 dst에 null을 포함해서 (size-1)개 까지 복사 후에 null을 붙여준다.
src의 길이가 size보다 적으면 부족한 부분을 null로 채운다
반환값은 항상 srcsize이다.
#include "libft.h"
size_t ft_strlcat(char *dst, const char *src, size_t dstsize)
{
size_t i;
size_t dst_len;
size_t src_len;
dst_len = ft_strlen(dst);
src_len = ft_strlen(src);
i = 0;
if (dstsize < dst_len + 1)
return (dstsize + src_len);
if (dstsize > dst_len + 1)
{
while (src[i] && dst_len + i + 1 < dstsize)
{
dst[dst_len + i] = src[i];
i++;
}
}
dst[dst_len + i] = '\0';
return (dst_len + src_len);
}
dest의 길이를 포함해서 새로운 dest의 길이를 설정하고 빈 공간 만큼 src를 이어붙인다.
마지막에 null을 보장해서 넣어준다.
dstsize < dst_len + 1인 경우 null공간 + dst_len보다 dstsize가 작음을 의미하므로 기타 작업 수행하지 않고 dstsize+src_len을 반환함
dstsize > dst_len + 1인 경우 기타 작업 수행 후 dstsize+src_len을 반환함
#include "libft.h"
int ft_strncmp(const char *s1, const char *s2, size_t n)
{
size_t i;
unsigned char *ptr1;
unsigned char *ptr2;
i = 0;
ptr1 = (unsigned char *)s1;
ptr2 = (unsigned char *)s2;
while (i < n)
{
if (!ptr1[i] || !ptr2[i] || ptr1[i] != ptr2[i])
return (ptr1[i] - ptr2[i]);
i++;
}
return (0);
}
문자열 비교 함수
#include "libft.h"
int ft_toupper(int c)
{
return (c - 32 * (c >= 'a' && c <= 'z'));
}
대문자로
#include "libft.h"
int ft_tolower(int c)
{
return (c + 32 * (c >= 'A' && c <= 'Z'));
}
소문자로
#include "libft.h"
char *ft_strchr(const char *s, int c)
{
size_t i;
size_t len;
i = 0;
len = ft_strlen(s);
while (i <= len)
{
if (s[i] == (char)c)
return ((char *)(s + i));
i++;
}
return (NULL);
}
문자열에서 특정한 문자가 가장 먼저 나타나는 곳의 위치를 찾음
#include "libft.h"
char *ft_strrchr(const char *s, int c)
{
size_t i;
i = ft_strlen(s);
while (s[i] != (char)c && i > 0)
i--;
if (s[i] == (char)c)
return ((char *)(s + i));
return (NULL);
}
문자열에서 문자를 검색하되 가장 마지막으로 나타나는 위치를 찾음
reverse strchr
#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 (0);
}
메모리 블록에서 문자를 찾는다
ptr이 가리키는 메모리 처음부터 n바이트까지 탐색하면서 처음으로 value와 일치하는 값의 주소를 리턴한다.
#include "libft.h"
int ft_memcmp(const void *s1, const void *s2, size_t n)
{
size_t i;
unsigned char *p1;
unsigned char *p2;
if (n == 0)
return (0);
i = 0;
p1 = (unsigned char *)s1;
p2 = (unsigned char *)s2;
while (i + 1 < n && p1[i] == p2[i])
i++;
return ((p1[i] - p2[i]));
}
두 개의 메모리 블록을 비교한다.
#include "libft.h"
char *ft_strnstr(const char *haystack, const char *needle, size_t len)
{
size_t i;
size_t j;
size_t needle_len;
i = 0;
needle_len = ft_strlen(needle);
if (!*needle)
return ((char *)haystack);
while (haystack[i])
{
if (haystack[i] == needle[0])
{
j = 0;
while (needle[j] && haystack[i + j] && (i + j) < len)
{
if (haystack[i + j] != needle[j])
break ;
j++;
}
if (j == needle_len)
return ((char *)haystack + i);
}
i++;
}
return (NULL);
}
문자열 내에서 부분문자열을 탐색한다.
#include "libft.h"
int ft_atoi(const char *str)
{
int i;
int num;
int sign;
i = 0;
num = 0;
sign = 1;
while (str[i] == ' ' || (str[i] >= 9 && str[i] <= 13))
i++;
if (str[i] == '+' || str[i] == '-')
{
if (str[i] == '-')
sign *= -1;
i++;
}
while (str[i] >= '0' && str[i] <= '9')
{
num = num * 10 + (str[i] - '0') * sign;
i++;
}
return (num);
}
라피신 코드랑 같음
#include "libft.h"
void *ft_calloc(size_t count, size_t size)
{
void *ptr;
if (count <= 0 || size <= 0)
ptr = (void *)malloc(1);
else
ptr = (void *)malloc(count * size);
if (!ptr)
return (NULL);
ft_bzero(ptr, count * size);
return (ptr);
}
count * size 만큼 malloc하고, 0으로 채움
#include "libft.h"
char *ft_strdup(const char *s1)
{
char *copy;
int len;
int i;
i = 0;
len = ft_strlen(s1);
copy = (char *)malloc(sizeof(char) * (len + 1));
if (!copy)
return (NULL);
while (s1[i])
{
copy[i] = s1[i];
i++;
}
copy[i] = '\0';
return (copy);
}
라피신 코드
#include "libft.h"
char *ft_substr(char const *s, unsigned int start, size_t len)
{
char *substr;
size_t i;
size_t s_len;
s_len = ft_strlen(s);
if (len >= s_len)
len = s_len;
if (start >= s_len)
return (ft_strdup(""));
substr = (char *)malloc(sizeof(char) * (len + 1));
if (!s || !substr)
return (NULL);
i = 0;
while (i < len && s[start])
substr[i++] = s[start++];
substr[i] = '\0';
return (substr);
}
제공받은 len이 s의 길이보다 길다면 len = ft_strlen(s)
제공받은 start가 s를 넘는다면 “”을 반환함
substr에 s[start]부터의 문자를 집어넣고 ‘\0’을 입력 후 반환
char const vs const char
const char * : 상수형 문자에 대한 포인터, 포인터가 가리키는 변수의 값을 바꿀 수 없음
char const * : 문자에 대한 상수형 포인터, 포인터 값을 바꿀 수 없음
#include "libft.h"
char *ft_strjoin(char const *s1, char const *s2)
{
char *new_s;
size_t s1_len;
size_t s2_len;
if (!s1 || !s2)
return (NULL);
s1_len = ft_strlen(s1);
s2_len = ft_strlen(s2);
new_s = (char *)malloc(sizeof(char) * (s1_len + s2_len + 1));
if (!new_s)
return (NULL);
ft_memcpy(new_s, s1, s1_len);
ft_memcpy(new_s + s1_len, s2, s2_len);
new_s[s1_len + s2_len] = '\0';
return (new_s);
}
s1과 s2를 연결한 새로운 문자열을 반환한다.
s1, s2 전부 NULL일 경우 0을 반환한다.
하나만 NULL일 경우 나머지 문자열만 복제하여 반환한다.
#include "libft.h"
char *ft_strtrim(char const *s1, char const *set)
{
size_t start;
size_t end;
char *res;
if (!s1)
return (NULL);
if (!set)
return ((char *)s1);
start = 0;;
while (s1[start] && ft_strchr(set, s1[start]))
start++;
end = ft_strlen(s1);
while (ft_strchr(set, s1[end - 1]) && end > start)
end--;
res = ft_substr(s1, start, (end - start));
return (res);
}
s1이 null이면 0을 반환한다
set이 null이면 s1을 복제하여 반환한다
문자열 전체에 대한 함수가 아니다.
복사된 문자열의 사본을 반환
#include "libft.h"
static char *ft_strndup(char const *s, char c)
{
size_t i;
char *copy;
i = 0;
while (s[i] && s[i] != c)
i++;
copy = (char *)malloc(sizeof(char) * (i + 1));
if (!copy)
return (NULL);
i = 0;
while (s[i] && s[i] != c)
{
copy[i] = s[i];
i++;
}
copy[i] = '\0';
return (copy);
}
static int count_words(char const *s, char c)
{
int i;
int nb_word;
nb_word = 0;
i = 0;
while (s[i])
{
while (s[i] == c)
i++;
if (s[i] && s[i] != c)
{
nb_word++;
while (s[i] && s[i] != c)
i++;
}
}
return (nb_word);
}
static char **free_arr(char **s)
{
int i;
i = 0;
while (s[i])
{
free(s[i]);
i++;
}
free(s);
return (NULL);
}
char **ft_split(char const *s, char c)
{
char **ary;
int i;
i = 0;
if (!s)
return (NULL);
ary = (char **)malloc(sizeof(char *) * (count_words(s, c) + 1));
if (!ary)
return (NULL);
while (*s)
{
while (*s && *s == c)
s++;
if (*s && *s != c)
{
ary[i++] = ft_strndup(s, c);
if (!ary)
return (free_arr(ary));
while (*s && *s != c)
s++;
}
}
ary[i] = 0;
return (ary);
}
문자열과 구분자가 주어지면 구분자를 통해서 문자열을 쪼개서 배열로 만들어 반환한다.
#include "libft.h"
int count_nbr(long long n)
{
int cnt_nbr;
if (n == 0)
return (1);
cnt_nbr = 0;
if (n < 0)
cnt_nbr = 1;
while (n)
{
n /= 10;
cnt_nbr++;
}
return (cnt_nbr);
}
char *ft_itoa(int n)
{
long long nbr;
char *res;
int len;
len = count_nbr((long long)n);
nbr = (long long)n;
if (n < 0)
nbr *= -1;
res = (char *)malloc(sizeof(char) * (len + 1));
if (!res)
return (NULL);
res[len--] = '\0';
while (len >= 0)
{
res[len] = nbr % 10 + '0';
nbr /= 10;
len--;
}
if (n < 0)
res[0] = '-';
return (res);
}
정수의 길이를 세어서 문자열로 만들어 반환한다.
뒤에서 부터 붙여넣기 한다.
#include "libft.h"
char *ft_strmapi(char const *s, char (*f)(unsigned int, char))
{
size_t len;
size_t i;
char *str;
i = 0;
len = ft_strlen(s);
str = (char *)malloc(sizeof(char) * (len + 1));
if (!str)
return (NULL);
while (i < len)
{
str[i] = f(i, s[i]);
i++;
}
str[i] = '\0';
return (str);
}
제공받은 문자열 s의 값을 함수에 적용해서 새로운 문자열 str을 만들기
#include "libft.h"
void ft_striteri(char *s, void (*f)(unsigned int, char *))
{
size_t i;
i = 0;
while (*(s + i))
{
f(i, s + i);
i++;
}
}
제공받은 s라는 문자열을 제공받은 f라는 함수에 적용하면 됨
#include "libft.h"
void ft_putchar_fd(char c, int fd)
{
write(fd, &c, 1);
}
제공받은 fd로 문자 c출력
#include "libft.h"
void ft_putstr_fd(char *s, int fd)
{
int i;
i = 0;
while (s[i])
write(fd, &s[i++], 1);
}
제공받은 fd로 문자열 s출력
#include "libft.h"
void ft_putendl_fd(char *s, int fd)
{
ft_putstr_fd(s, fd);
ft_putchar_fd('\n', fd);
}
제공받은 fd로 문자열 s를 출력하고 개행문자 출력
#include "libft.h"
void rec_putnbr(int nb, int fd)
{
char c;
if (nb == 0)
return ;
c = '0' + nb % 10;
rec_putnbr(nb / 10, fd);
ft_putchar_fd(c, fd);
}
void ft_putnbr_fd(int n, int fd)
{
char c;
if (n < 0)
{
write(fd, "-", 1);
c = '0' - n % 10;
rec_putnbr(-(n / 10), fd);
}
else
{
c = '0' + n % 10;
rec_putnbr(n / 10, fd);
}
ft_putchar_fd(c, fd);
}
제공받은 fd로 정수 출력
#include "libft.h"
t_list *ft_lstnew(void *content)
{
t_list *lst;
lst = (t_list *)malloc(sizeof(t_list));
lst->content = content;
lst->next = 0;
return (lst);
}
새로운 리스트 생성
#include "libft.h"
void ft_lstadd_front(t_list **lst, t_list *new)
{
if (!new)
return ;
new->next = *lst;
*lst = new;
}
리스트의 가장 처음 요소에 제공받은 리스트 추가
#include "libft.h"
int ft_lstsize(t_list *lst)
{
int cnt;
cnt = 0;
while (lst)
{
lst = lst->next;
cnt++;
}
return (cnt);
}
리스트의 크기 반환
#include "libft.h"
t_list *ft_lstlast(t_list *lst)
{
if (!lst)
return (lst);
while (lst->next)
lst = lst->next;
return (lst);
}
리스트의 마지막 요소 반환
#include "libft.h"
void ft_lstadd_back(t_list **lst, t_list *new)
{
t_list *ptr;
if (!*lst)
{
*lst = new;
return ;
}
ptr = *lst;
while (ptr->next)
ptr = ptr->next;
ptr->next = new;
}
리스트의 마지막 요소에 제공받은 리스트 추가
#include "libft.h"
void ft_lstdelone(t_list *lst, void (*del)(void *))
{
t_list *tmp;
if (!del)
return ;
tmp = lst->next;
del(lst->content);
free(lst);
lst = tmp;
}
리스트의 처음 요소 삭제 후 공간 해제
#include "libft.h"
void ft_lstclear(t_list **lst, void (*del)(void *))
{
t_list *curr;
t_list *next;
curr = *lst;
while (curr)
{
next = curr->next;
ft_lstdelone(curr, del);
curr = next;
}
*lst = NULL;
}
모든 리스트의 요소 삭제 후 공간 해제
#include "libft.h"
void ft_lstiter(t_list *lst, void (*f)(void *))
{
while (lst)
{
f(lst->content);
lst = lst->next;
}
}
리스트를 순회하며 제공받은 함수를 적용
#include "libft.h"
t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *))
{
t_list *tmp;
t_list *res;
if (!lst)
return (NULL);
res = NULL;
while (lst)
{
tmp = ft_lstnew(f(lst->content));
if (!tmp)
{
ft_lstclear(&lst, del);
return (NULL);
}
ft_lstadd_back(&res, tmp);
lst = lst->next;
}
return (res);
}
임시적인 리스트 tmp와 결과값을 저장할 리스트 res를 선언한다
tmp에 lst의 요소를 함수에 적용한 값을 담는데 실행이 되지 않았다면 lst를 삭제하고 NULL을 반환한다.
성공했다면 res에 붙여넣기 한다.이후 lst를 옮긴다.
CC = cc
CFLAGS = -Wall -Wextra -Werror
NAME = libft.a
RM = rm -f
AR = ar
ARFLAGS = crs
INCLUDES = ./libft.h
SRCS_NM = ft_isalpha.c \
ft_isdigit.c \
ft_isalnum.c \
ft_isascii.c \
ft_isprint.c \
ft_strlen.c \
ft_memset.c \
ft_bzero.c \
ft_memcpy.c \
ft_memmove.c \
ft_strlcpy.c \
ft_strlcat.c \
ft_strncmp.c \
ft_toupper.c \
ft_tolower.c \
ft_strchr.c \
ft_strrchr.c \
ft_memchr.c \
ft_memcmp.c \
ft_strnstr.c \
ft_atoi.c \
ft_calloc.c \
ft_strdup.c \
ft_substr.c \
ft_strjoin.c \
ft_strtrim.c \
ft_split.c \
ft_itoa.c \
ft_strmapi.c \
ft_striteri.c \
ft_putchar_fd.c \
ft_putstr_fd.c \
ft_putendl_fd.c \
ft_putnbr_fd.c
SRCS_BN = ft_lstnew.c \
ft_lstadd_front.c \
ft_lstsize.c \
ft_lstlast.c \
ft_lstadd_back.c \
ft_lstdelone.c \
ft_lstclear.c \
ft_lstiter.c \
ft_lstmap.c
OBJS = $(SRCS_NM:.c=.o)
OBJS_BONUS = $(SRCS_BN:.c=.o)
ifdef WITH_BONUS
OBJ_FILES = $(OBJS) $(OBJS_BONUS)
else
OBJ_FILES = $(OBJS)
endif
all : $(NAME)
sleep 1
.c.o : $(SRCS)
$(CC) $(CFLAGS) -c -o $@ $<
$(NAME) : $(OBJ_FILES)
$(AR) $(ARFLAGS) $@ $^
clean :
$(RM) $(RMFLAG) $(OBJS) $(OBJS_BONUS)
fclean: clean
$(RM) $(RMFLAG) $(NAME)
re: fclean all
bonus:
@make WITH_BONUS=1 all
.PHONY : all clean fclean re bonus
제출할 때는 sleep 1 지우기