[Libft] C 언어 라이브러리 구현_Part2_추가함수 구현1

2021. 5. 23. 17:06·IT/42Seoul

혹시나 문제가 된다면 바로 비공개 처리하겠습니다. 지적이나 댓글 환영합니다!

 

이번 포스팅에서는 문자열 관련 함수들을 구현해보겠다.

소개할 함수 3개의 공통점은 모두 동적할당(malloc)을 사용하여 편집된 문자열을 새로 만드는 것이다.

이번 함수들은 메뉴얼이 이미 과제 페이지에 영어로 상세히 적혀있는 대신, 전보다 구현이 복잡한 특징을 가졌다.

따라서 이번 시간에는 함수의 역할 대한 정리보다는 함수를 어떤 방식으로 구현했는지, 구현에서 어떤 문제들을 마주쳤고 이를 어떻게 해결했는 지 위주로 설명하겠다. (면접용 연습)

주의사항이라고 적은 사항들이 대부분 내가 실수했으나 고쳐서 어떻게 해결했는 지에 대한 내용들이다.

 

참고로, 내가 정의한 libft.h 헤더에는 <unistd.h>와 <stdlib.h>가 include 되어있다. 따라서 libft.h를 호출하면, 따로 정의하지 않고도 <unistd.h> 에 정의된 size_t 타입과 <stdlib.h>의 malloc/free를 사용할 수 있다.

 

 

 

 

(1) ft_substr : 부분문자열 생성

: 주어진 시작 지점에서 주어진 길이만큼 원본 문자열을 잘라, 부분문자열을 생성한다.

 


- 구현 코드 예시 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "libft.h"
 
char    *ft_substr(char const *s, unsigned int start, size_t len)
{
    char    *sub;
    size_t    i;
    size_t    size;
 
    i = 0;
    size = ft_strlen(s);
    if (start >= size)
    {
        if (!(sub = malloc(sizeof(char))))
            return (0);
    }
    else
    {
        if (size - start < len)
            len = size - start;
        if (!(sub = malloc(sizeof(char) * (len + 1))))
            return (0);
        while (i < len && s[start + i])
        {
            sub[i] = s[start + i];
            i++;
        }
    }
    sub[i] = '\0';
    return (sub);
}
Colored by Color Scripter
cs

- 예외처리 : 부분문자열을 생성할 시작지점이 문자열의 길이보다 같거나 크다면, 부분문자열을 생성할 수 없다. 따라서 이 경우에는 크기를 1만큼 동적할당 해준 뒤 그 공간에 '\0'을 넣은 후 포인터를 리턴하게 만들었다. (free할 수 있도록, 동적할당된 메모리를 리턴)

 

- 예외처리 : 널가드

더보기

동적할당이 실패할 경우(커널의 메모리 공간 부족 등의 여러 이유로) 0을 리턴한다.

  ex) if (!(sub)) return (0);     

=> 동적할당이 실패한 경우는 sub가 null(=0 =false)이 된다. 이때 !(sub)의 값은 true로, if 조건문의 코드를 실행시킨다.

 

- 주의할 점 : 매개변수로 받은 len이, 처리될 수 있는 최대 길이(strlen(s) - start)보다 길 경우를 예외처리 해주어야 한다. 내 친구는 이 부분을 예외처리 하지 않았다가 동료평가에서 0점을 받았다. 예를 들어, 문자열이 "abcd", start 지점이 1으로 주어졌는데, len 에서는 10000이 주어져, 실제로 문자열을 복사 가능한 메모리 3칸이 아닌 10000개의 메모리를 할당하는 상황을 가정하자. 이런 경우 매우 비효율적이고 불필요하게 메모리를 많이 차지한다. 따라서 시작점으로부터 끝까지의 문자열의 길이가 주어진 len 보다 짧을 경우, len 대신 그 길이만큼만 메모리를 할당하게 끔 코드를 수정하였다.

 

- 반복문을 사용하여, 원본문자열의 start 지점부터 최대 len만큼의 문자들이, 동적할당된 메모리에 복사될 수 있도록 하였다. 

- 부분문자열의 복사가 끝난 후에, 포인터의 끝에 null을 넣어 리턴하였다.

 

 

 

 

 

(2) ft_strjoin : 2개의 문자열을 병합

: malloc으로 동적할당하여, 문자열 2개를 나란히 합친 새로운 문자열을 생성한다.

 

 


- 구현 코드 예시 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "libft.h"
 
char        *ft_strjoin(char const *s1, char const *s2)
{
    int        i;
    int        j;
    int        index;
    int        len;
    char    *str;
 
    i = 0;
    j = 0;
    index = 0;
    len = ft_strlen(s1) + ft_strlen(s2);
    str = malloc(sizeof(char) * (len + 1));
    if (!(str))
        return (0);
    while (s1[i])
        str[index++] = s1[i++];
    while (s2[j])
        str[index++] = s2[j++];
    str[index] = '\0';
    return (str);
}
 
Colored by Color Scripter
cs

- 주의사항 : 문자열의 길이 len이 아닌, len + 1 만큼 동적할당하는 것을 유의해야 한다. (끝의 null을 채워주기 위한 공간까지 할당)

더보기

예를 들어, 문자열 abcde라는 문자의 길이는 5이다. 그러나 5칸 + null을 끝에 채우기 위한 1칸의 메모리가 필요하므로 실제 할당할 길이는 len + 1이 되야한다.

또한 문자열이 빈 문자열이라면, \0으로 된 1칸짜리 문자열과 다름이 없다. 따라서 이를 복사하기 위해서는 1칸의 공간을 동적할당 해준 뒤 '\0'을 첫칸에 채워주면 된다.

 

- 두 문자열의 길이를 더한 길이 + 1(널문자 넣을 공간) 만큼 malloc으로 동적할당한다. 

- str(동적할당 된 메모리)에 첫번째 문자열을 복사해준 뒤, 이어서 그 자리부터 두번째 문자열을 복사해서 붙여준다.

- 복사가 완료된 str의 끝에 null을 넣어준 뒤 str의 포인터를 리턴한다. 

 

 

 

 

(3) ft_strtrim

: 주어진 문자열의 앞뒤에서, 주어진 문자집합(set)에 포함된 문자들을 전부 제거한 문자열을 구한다.

 

 


- 구현 코드 예시 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "libft.h"
 
static int        is_charset(char const *set, char c)
{
    int i;
 
    i = 0;
    while (set[i])
    {
        if (set[i] == c)
            return (1);
        i++;
    }
    return (0);
}
 
static size_t    get_start(char const *s1, char const *set)
{
    size_t    start;
 
    start = 0;
    while (is_charset(set, s1[start]) && s1[start])
        start++;
    return (start);
}
 
static size_t    get_end(char const *s1, char const *set)
{
    size_t    end;
 
    end = ft_strlen(s1) - 1;
    while (is_charset(set, s1[end]) && end >= 0)
        end--;
    return (end);
}
 
char            *ft_strtrim(char const *s1, char const *set)
{
    char    *p;
    size_t    index;
    size_t    start;
    size_t    end;
    size_t    size;
 
    if (*set == 0)
        return (ft_strdup(s1));
    start = get_start(s1, set);
    if (start == ft_strlen(s1))
        size = 1;
    else
    {
        end = get_end(s1, set);
        size = end - start + 2;
    }
    index = 0;
    if (!(p = malloc(sizeof(char) * size)))
        return (0);
    while (start <= end && s1[start])
        p[index++] = s1[start++];
    p[index] = '\0';
    return (p);
}
 
Colored by Color Scripter
cs

 


- 주의사항 : 구한 start 값이 ft_strlen(s1)과 같게 나올 경우, 주어진 문자열 s1 모두에서 set의 문자열이 나온다는 뜻이다. 이때 charset의 문자열을 제거한 문자열을 만들게 되면, 1칸만 동적할당 해준 뒤, 그 속에 null을 넣어주고 그 포인터를 리턴해야한다.

 

- 주의사항 : 이때 start를 ft_strlen(s1)과 "=="라는 비교연산자로 비교하게 되는데, ft_strlen()의 리턴형은 size_t이기 때문에, 비교할 값인 start 또한 같은 형식으로 선언해주었다.

 

- 주의사항 : 동적할당할 공간의 사이즈를 구할 때, start와 end 지점이 같을 때에도 해당 지점을 포함하여 null을 할당할 공간까지 총 2칸을 할당하게된다. 따라서 size 는 end - start + 2 가 된다.

 

- 주의사항 : set이 null일 경우는 ft_strdup()함수를 이용하여 s1의 사본의 포인터를 리턴해주는 식으로 예외처리 해주었다

이때, 원본인 s1를 리턴하지 않고 malloc된 사본을 리턴하는 것은 나중에 free가 가능하게 하기 위함이다 

 

- 주의사항 : 처음 구현할 때, 주어진 문자열 s1에서 set에 포함된 문자열을 전부 제거하는 줄 오해하고 잘못 구현한 적이 있다. 반드시 앞뒤에서부터 각각 탐색했을 때, 더이상 나오지 않을때까지 set에 포함된 문자들을 제거한다는 것을 유의해야한다.

 

 

- get_start 함수를 통해, 앞에서부터 탐색했을 때, set의 문자열이 더이상 나오지 않는 시작 지점을 구한다.

- get_end 함수를 통해, 뒤에서부터 탐색했을 때, set의 문자열이 더이상 나오지 않는 끝 지점을 구한다

- 필요한 총 공간을 구하여 동적할당한 뒤, 그 공간에 start지점에서 end지점까지의 값들을 반복문을 통해 복사해준다.

 

 

 

- 보완점 : get_start() 와 get_end() 대신에 이미 이전에 구현한 strchr()과 strrchr()을 사용하면 됬는데, 괜히 함수를 더 만들어 코드의 재사용성과 효율성을 떨어뜨린 것 같다. 동료평가 때 피드백을 받아 알게 되었다. 다시 코드를 짜게 된다면 이 점을 보완하고 싶다. 

 

저작자표시 (새창열림)

'IT > 42Seoul' 카테고리의 다른 글

[Libft] C 언어 라이브러리 구현_Part2_추가함수 구현3  (0) 2021.05.23
[Libft] C 언어 라이브러리 구현_Part2_추가함수 구현2  (0) 2021.05.23
[Libft] C 언어 라이브러리 구현_Part1_malloc을 사용한 함수  (0) 2021.05.20
[Libft] C 언어 라이브러리 구현_Part1_문자 판별 + 변환 관련 함수  (0) 2021.05.20
[Libft] C 언어 라이브러리 구현_Part1_문자열 관련 함수  (0) 2021.05.20
'IT/42Seoul' 카테고리의 다른 글
  • [Libft] C 언어 라이브러리 구현_Part2_추가함수 구현3
  • [Libft] C 언어 라이브러리 구현_Part2_추가함수 구현2
  • [Libft] C 언어 라이브러리 구현_Part1_malloc을 사용한 함수
  • [Libft] C 언어 라이브러리 구현_Part1_문자 판별 + 변환 관련 함수
남서아 (구 - 밥한그릇배따시게)
남서아 (구 - 밥한그릇배따시게)
학습하고 정리한 내용 중, 공유할만한 것들을 포스팅합니다. / 소프트웨어 학사 (2025년도 2월 졸업)
  • 남서아 (구 - 밥한그릇배따시게)
    남서아 기술블로그
    남서아 (구 - 밥한그릇배따시게)
  • 전체
    오늘
    어제
  • 공지사항

    • 개발자 정보 및 포트폴리오
    • 포스팅 목적
  • 링크

    • Portfolio
    • 분류 전체보기 (99)
      • IT (59)
        • 클라우드 & 인프라 (2)
        • CS 공부 (12)
        • 42Seoul (19)
        • 개발 언어 및 도구 (4)
        • 개발 환경 및 설치 (5)
        • 튜토리얼 및 가이드 (10)
        • Data & AI (5)
        • ETC (2)
      • Experience (4)
      • English (32)
        • 회화 (5)
        • 자격증 공부 (26)
        • 후기 (1)
      • 근황 (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
남서아 (구 - 밥한그릇배따시게)
[Libft] C 언어 라이브러리 구현_Part2_추가함수 구현1
상단으로

티스토리툴바