[C] strcat / strncat / strlcat 사용법과 구현
본문 바로가기

C

[C] strcat / strncat / strlcat 사용법과 구현

728x90
반응형

문자열을 쓰다 보면 가끔 문자열을 합치고 싶을 때가 있습니다.

이때를 위해 C언어에서는 strcat 함수들을 제공하죠

 

strcat 부류 함수들은 문자열 뒤에 다른 문자열을 이어 붙여주는 함수입니다.

 

strcat 함수들은 보통 strcat, ncat, lcat으로 분류 됩니다.

 

strcat은 문자열에 문자열을 이어 붙여주는 함수

strncat은 문자열에 문자열을 n번 이어 븉여주는 함수

strlcat은 문자열에 문자열을 n - 1 번 이어 붙여주는 함수

이렇게 설명할 수 있겠네요

 

이번 포스팅에서는 이 함수들에 대해서 공부해 보는 시간을 가져보겠습니다.

 

strcat 

#include <string.h>

char	*strcat(char *restrict s1, const char *restrict s2)


int	main(void)
{
    char s1[12] = "hello";
    char s2[7] = " world";
    strcat(s1, s2);
    printf("%s\n", s1); // 출력 결과 "hello world"
}

출력을 해보시면 s1 문자열이 "hello world" 로 변해있는것을 확인하실 수 있습니다.

이런식으로 문자열 뒤에 다른 문자열을 이어 붙여주는게 strcat 함수인데요

strcat함수에는 치명적인 단점이 있습니다.

바로 s1 문자열의 크기가 s2 문자열을 담지 못하는 크기라면 오류가 나는 것인데요

이는 아래 구현 부분에서 살펴 보겠습니다.

 

strcat 구현

#include <string.h>
#include <stdio.h>

char	*ft_strcat(char *restrict s1, const char *restrict s2)
{
    size_t	i;
    size_t	j;
    
    i = strlen(s1);
    j = 0;
    while (s2[j])
    {
    	s1[i + j] = s2[j];
        j++;
    }
    s1[i + j] = '\0';
    return (s1);
}

int	main(void)
{
    char s1[6] = "hello";
    char s2[7] = " world";
    
    strcat(s1, s2); // 오류
    printf("%s\n", s1);
    ft_strcat(s1, s2);
    printf("%s\n", s1);
}

위 코드를 실행해 보시면 오류가 날텐데요

s1 문자열의 크기는 6인데 s2의 문자열 크기가 7입니다.

s1 문자열이 "hello\0" 이렇게 6개의 문자를 할당받은 상태에서 " world\0" 7개의 문자를 추가로 할당받기엔

공간이 부족한거죠

 

이러한 결함을 매꾸고자 만든 함수가 strncat 함수입니다.

 

strncat

 

#include <string.h>

char	*strncat(char *restrict s1, const char *restrict s2, size_t n)

int	main(void)
{
    char s1[9] = "hello";
    char s2[7] = " world";
    strncat(s1, s2, 3);
    printf("%s\n", s1);	// 출력 결과 hello wo
}

strcat의 경우 s2 문자열을 전부 s1 문자열 뒤에 복사 시키는 반면

strncat의 경우 n번만 뒤에 복사시키기 때문에 보다 안전하다고 할 수 있습니다.

물론 strcat처럼 똑같이 s1 문자열의 크기가 부족하다면 또같이 오류가 나겠지만요

서로 대동소이한 편입니다.

 

strncat 구현

 

#include <string.h>

char	*ft_strncat(char *restrict s1, const char *restrict s2, size_t n)
{
    size_t	i;
    size_t	j;
    
    i = strlen(s1);
    j = 0;
    while (s2[j] && j < n)
    {
    	s1[i + j] = s2[j];
        j++;
    }
    s1[i + j] = '\0';
    return (s1);
}

보시면 strcat과 다른 점이 while 조건문에 j < n 조건 하나 추가 된것을 보실 수 있습니다.

단순히 이어붙이는 횟수 조건 하나만 추가 된게 strncat 함수이기 때문이죠

 

 

 

strlcat

#include <string.h>

size_t	strlcpy(char *restrict dst, const char *restrict src, size_t dstsize)

사용법은 strncat과 좀 다릅니다.

dstsize 만큼 복사하는게 아닌 dst 문자열 크기 기준

dstsize 인덱스 - 1 까지 복사하게 됩니다.

즉 dstsize가 5라고 해서 5만큼 복사하는게 아닌

dst문자열 기준 4(5 - 1)인덱스 까지 복사한다는 뜻이 됩니다.

 

함수에서 반환디는 값 또한 특이한데요

dstsize < dst 길이 -> src길이 + dstsize

dstsize > dst 길이 -> src길이 + dst 길이

 

뭔가 좀 이상하지만 이 두 반환값은 반드시 src 길이 이상 값을 반환한다는 공통점이 있습니다.

이 반환값들을 토대로 구현한다면 그다지 어렵지 않게 구현할 수 있습니다.

 

strlcat 구현

#include <string.h>
#include <stdio.h>

size_t	ft_strlcat(char *restrict dst, const char *restrict src, size_t dstsize)
{
	size_t	len_dst;
	size_t	len_src;
	size_t	j;

	len_dst = strlen(dst);
	len_src = strlen(src);
	j = 0;
	while (src[j] && len_dst + j + 1 < dstsize)
	{
		dst[len_dst + j] = src[j];
		j++;
	}
	dst[len_dst + j] = '\0';
	if (len_dst > dstsize)
		return (len_src + dstsize);
	return (len_src + len_dst);
}

int	main(void)
{
    char s1[50] = "hello";
    char s2[7] = "world";
    char s3[50] = "hello";

    size_t j = strlcat(s1, s2, 8);
    printf("%zu\n", j);			// 10
    printf("%s\n", s1);			// hellowo
    j = ft_strlcat(s3, s2, 8);
    printf("%zu\n", j);			// 10
    printf("%s\n", s3);			// hellowo
}

반환값만 다르지 ncat이랑 크게 다를게 없는 함수라는걸 알 수 있습니다.

반환값이 좀 특이하긴 한데 찾아봐도 명확한 이유는 없는것 같네요

제 추측이지만 반환값은 아무래도 한번이라도 복사했냐 안했냐를 식별하기 위해 저렇게 만들지 않았나 싶습니다.

728x90
반응형