- [42경산/C언어] Libft 라이브러리 구현 가이드: 표준 C 라이브러리 함수 재구현과 Makefile 설계2025년 03월 12일 23시 45분 12초에 업로드 된 글입니다.작성자: kugorang
TL;DR — 3줄 핵심 요약
• 문제: Libft는 표준 C 라이브러리 함수 40여 개를 직접 다시 만드는 과제다. "동작한다"와 "표준과 같다"는 다르고, 평가는 경계값에서 갈린다.
• 기술/원인: C 문자열은 '\0'로 끝나는 바이트 배열이고, 포인터는 그 배열의 주소다. 함수 대부분은 이 주소를 진행시키며 바이트를 읽고, 종료 문자를 만나면 멈춘다. 그래서 버퍼 크기, 널 종료, 겹침 여부가 결과를 바꾼다.
• 해결/인사이트: 세 가지만 지키면 대부분 통과한다. ① 반환 타입과 값(size_t, char*, int)을 표준과 맞춘다 ② 크기가 0인 경우와 널 종료를 따로 처리한다 ③ memcpy와 memmove, strlcpy와 strncpy의 차이를 구분한다.
Part 1: libc 함수 다시 만들기

문자 판별과 변환
- ft_isalpha, ft_isdigit, ft_isalnum: 문자가 속한 범위를 비교해 0 또는 1을 반환한다. 표준은 "0이 아니면 참"이라 값이 1일 필요는 없다.
- ft_isascii: 0~127 범위인지 확인한다. C 표준이 아니라 POSIX/BSD 확장이다.
- ft_isprint: 공백(32)부터 물결표(126)까지.
- ft_toupper, ft_tolower: 소문자 a(97)와 대문자 A(65)의 차이가 32라는 성질을 쓴다.
int ft_isalpha(int c) { return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); } int ft_tolower(int c) { if (c >= 'A' && c <= 'Z') return (c + 32); return (c); }char가 부호 있는 타입인 플랫폼에서는 음수 문자가 들어올 수 있다. 표준 함수는 unsigned char 범위를 가정하므로, 필요하면 (unsigned char)로 캐스팅한다.
길이와 메모리 채우기
size_t ft_strlen(const char *s) { size_t i = 0; while (s[i]) i++; return (i); } void *ft_memset(void *b, int c, size_t len) { unsigned char *p = (unsigned char *)b; size_t i = 0; while (i < len) p[i++] = (unsigned char)c; return (b); }- ft_strlen의 반환은 int가 아니라 size_t다. int면 아주 긴 문자열에서 넘친다.
- ft_bzero(s, n)은 memset(s, 0, n)과 같다. 4.2BSD에서 온 함수로 POSIX.1-2008에서 제거되었다.
- len이 0이면 아무것도 쓰지 않고 포인터를 그대로 반환한다.
복사: memcpy와 memmove
void *ft_memmove(void *dst, const void *src, size_t len) { unsigned char *d = (unsigned char *)dst; const unsigned char *s = (const unsigned char *)src; if (d < s) while (len--) *d++ = *s++; else if (d > s) { while (len--) d[len] = s[len]; } return (dst); }- memcpy: 영역이 겹치면 결과가 정의되지 않는다. 앞에서 뒤로만 복사한다.
- memmove: 겹쳐도 안전하다. dst가 src보다 앞이면 순방향, 뒤면 역방향으로 복사한다.
- 역방향 복사에서 size_t를 쓰면 len이 0일 때 0-1이 매우 큰 값이 되므로 while (len--) 형태로 처리한다.
안전한 문자열 복사: strlcpy와 strlcat
size_t ft_strlcpy(char *dst, const char *src, size_t dstsize) { size_t i = 0; while (src[i] && i + 1 < dstsize) { dst[i] = src[i]; i++; } if (dstsize > 0) dst[i] = '\0'; while (src[i]) i++; return (ft_strlen(src)); }- dstsize - 1글자까지 복사하고 항상 널을 붙인다(단, dstsize가 0이면 아무것도 쓰지 않고 src 길이만 반환).
- 반환값은 src의 전체 길이다. 반환값이 dstsize 이상이면 잘렸다는 뜻이다.
- strncpy와의 차이: strncpy는 소스가 길면 널을 보장하지 않고, 짧으면 남는 공간을 0으로 채운다.
검색과 비교
- ft_strchr: 첫 번째 등장 위치. '\0'을 찾으면 문자열 끝을 가리키는 포인터를 반환한다.
- ft_strrchr: 마지막 등장 위치. 끝에서부터 찾거나, 순방향으로 훑으며 마지막 위치를 기억한다.
- ft_strnstr: haystack의 앞 len 문자 안에서만 needle을 찾는다. BSD 확장이라 표준에 없다. needle이 빈 문자열이면 haystack을 반환한다.
- ft_strncmp: n개까지 사전식 비교. 차이를 (unsigned char)s1[i] - (unsigned char)s2[i]로 반환한다.
- ft_memchr, ft_memcmp: 널을 만나도 멈추지 않고 n바이트를 본다.
변환과 할당
int ft_atoi(const char *str) { long n = 0; int sign = 1; while (*str == ' ' || (*str >= 9 && *str <= 13)) str++; if (*str == '-' || *str == '+') if (*str++ == '-') sign = -1; while (*str >= '0' && *str <= '9') n = n * 10 + (*str++ - '0'); return ((int)(n * sign)); }- ft_calloc(count, size): count * size를 계산하기 전에 0인지 확인하고, 곱셈이 넘치지 않는지 검사해야 한다. 넘치면 NULL을 반환한다.
- ft_strdup: strlen + 1 바이트를 할당해 복사한다. 할당 실패 시 NULL.
Part 2와 Part 3
- ft_substr: 문자열의 start부터 len만큼 잘라 새로 할당한다. start가 길이보다 크면 빈 문자열.
- ft_strjoin: 두 문자열을 이어 붙인 새 문자열. 크기는 len1 + len2 + 1.
- ft_strtrim: 양 끝에서 set에 포함된 문자를 제거한 새 문자열.
- ft_split: 구분자로 나눈 문자열 배열. 마지막에 NULL 포인터를 둔다.
- ft_itoa: 정수를 문자열로. INT_MIN(-2147483648)은 -n이 넘치므로 long으로 처리한다.
- ft_strmapi, ft_striteri: 인덱스와 함께 각 문자에 함수를 적용한다.
- ft_putchar_fd, ft_putstr_fd, ft_putendl_fd, ft_putnbr_fd: write(fd, ...) 기반 출력. 개행 유무가 함수마다 다르다.
- 보너스(연결 리스트): ft_lstnew, ft_lstadd_front, ft_lstsize, ft_lstlast, ft_lstadd_back, ft_lstdelone, ft_lstclear, ft_lstiter, ft_lstmap
자주 틀리는 지점
- ft_strlen, ft_strlcpy의 반환을 int로 선언
- ft_memmove에서 len이 0일 때 역방향 루프가 폭주
- ft_strlcat에서 dst가 널로 끝나 있지 않은 경우를 처리하지 않음
- ft_split에서 할당 실패 시 이미 만든 배열을 해제하지 않음
- ft_itoa에서 INT_MIN 처리 누락
- ft_strnstr에서 len이 needle 길이보다 작은 경우 검사 누락
- Makefile에서 .PHONY 누락, 보너스 규칙 누락
자주 묻는 질문 (FAQ)
Q1. libft 함수들을 그냥 표준 라이브러리로 호출하면 안 되나요?
A. 과제 규칙상 허용된 함수만 쓸 수 있고, 목적이 동작 원리를 이해하는 것이다. 또 이후 과제에서 같은 함수를 쓰기 때문에 직접 만든 구현이 필요하다. man 페이지와 동작을 비교하며 만들면 표준과의 차이를 확인할 수 있다.
Q2. ft_strlcpy와 ft_strncpy 중 무엇을 써야 하나요?
A. 크기를 아는 버퍼에 넣을 때는 strlcpy가 안전하다. 항상 널로 끝나고, 반환값으로 잘림을 알 수 있다. strncpy는 소스가 길면 널이 없을 수 있어 이어서 쓰면 위험하다.
Q3. 보너스 연결 리스트는 꼭 해야 하나요?
A. 평가 점수에 포함되지만 필수는 아니다. 다만 이후 과제(push_swap 등)에서 연결 리스트를 직접 다루므로, lstnew·lstadd_back·lstclear 정도는 반드시 익혀 두는 편이 좋다. lstclear는 노드와 content를 모두 해제해야 누수가 없다.
728x90728x90'42경산 & 알고리즘 > 42 과제 회고' 카테고리의 다른 글
다음글이 없습니다.이전글이 없습니다.댓글