C언어로 문자열 trim 함수 구현하기

C언어로 문자열 trim 함수 구현하기

trim은 문자열 양쪽의 공백들을 제거하는 함수다. 여기서 말하는 공백은 스페이스바 문자 ' ' 뿐만 아니라, '\r', '\n', '\t' 문자들도 포함된다. 아래의 예시처럼 공백이 제거된다.

"        hello world !   " # 입력 문자열
"hello world !"            # trim 실행 후

C언어로 trim 함수 알고리듬을 구현해보자.

void trim(char* str);

C스타일 문자열을 파라미터 str로 전달받는 함수 원형이다. 반환형을 char*로 지정해서 파라미터 str의 주소를 그대로 return 해도 되지만, 여기서는 그냥 void로 설정했다.

1. 문자열 앞부분

{
    char* head = str;
    while (*head != '\0' && (' ' == *head || '\t' == *head || '\n' == *head || '\r' == *head)) {
        ++head;
    }
...

head 변수를 하나 만들고 str의 맨 처음부터 시작해서, 최초로 공백이 아닌 문자의 위치를 선형탐색한다. 연산자 우선순위는 &&||보다 먼저인 점에 유의한다.

2. ‘\0’ 문자 검색

...
    char* tail = head;
    while (*tail != '\0') {
        ++tail;
    }
    --tail;
...

tail 변수를 만들고 head부터 시작하여, 문자열의 끝(\0) 을 찾는다. 그리고 나서 --tail; 을 실행하여 한 글자 이전으로 가리키게 한다.

3. 문자열 끝부분

...
    while (head < tail) {
        if (' ' != *tail && '\t' != *tail && '\n' != *tail && '\r' != *tail) {
            break;
        }
        --tail;
    }
...

문자열을 역으로 탐색하여, 최초로 공백이 아닌 문자를 가리키게 한다.

4. 공백 제거하기

이제 포인터 head, tail의 값이 정해졌으니, 이 범위에서 문자열을 얻을 수 있다. 새로운 문자열 메모리를 동적할당하여 그곳에 복사해도 되겠지만, 성능을 위해서 str 데이터를 변경하는 게 더 바람직할 것이다. 왜냐하면 아래와 같은 특징이 있기 때문이다. 문자열 str의 길이가 trim 처리된 길이보다 항상 크거나 같다.

strtrim(str)| str | \geq | trim(str) |

...
    while (head <= tail) {
        *str++ = *head++;
    }
    *str = '\0';
}

str의 끝에는 \0 문자 넣는 것을 잊지 말자.

소스코드: https://gist.github.com/jubin-park/b68b75ea92cc795b7cb426e363cb0885

댓글