문자열 관련 함수 : strlen, strlcpy, strlcat, strchr, strrchr, strnstr, strncmp

dqQQQ

·

2023. 11. 25. 12:24

개요

string과 str관련 함수를 알아보겠습니다.


문자와 문자열

 


strlen


SYNOPSIS

  • 함수 원형 : size_t ft_strlen(const char *s)
  • 함수 라이브러리 : #include <string.h>
  • const char *s : 길이를 셀 문자열
  • 리턴값 : 문자열의 길이

 

DESCRIPTION

파라메터로 들어온 문자열의 길이를 센 다음 리턴해준다.

 

strlen CODE

size_t    ft_strlen(const char *s)
{
    size_t    i;

    i = 0;
    while (*(s + i))
        i++;
    return (i);
}

딱히 설명할 부분은 없어보인다.




strlcpy


SYNOPSIS

  • 함수 원형 : size_t ft_strlcpy(char *dst, const char *src, size_t dstsize)
  • 함수 라이브러리 : #include <string.h>
  • char *dst : 복사를 할 문자열
  • const char *src : 복사를 해줄 문자열
  • size_t dstsize : 복사해줄 개수
  • 리턴값 : src의 길이

 

DESCRIPTION

src 문자열을 널값을 고려하여 dstsize만큼 dst로 복사후에 src의 길이를 리턴

 

strlcpy CODE

size_t    ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
    size_t    i;
    size_t    tmp;

    tmp = 0;
    i = 0;
    if (!dst || !src)
        return (0);
    while (*(src + tmp))
        tmp++;
    while (i < tmp && i + 1 < dstsize)
    {
        *(dst + i) = *(src + i);
        i++;
    }
    if (dstsize > 0)
        *(dst + i) = 0;
    return (tmp);
}

널값을 고려해주기 때문에 안정성이 좋다.

while에서 i + 1을 해준것은 dstsize가 널값까지 생각한 파라메터이기 때문에 널 값 전까지만 복사를 진행한다.

dstsize가 0이라면 널값도 포함을 안시키게 인자를 넣은 것이므로 dst값을 아예 바꾸지 않고 src길이만 리턴한다.




strlcat


SYNOPSIS

  • 함수 원형 : size_t ft_strlcat(char *dst, const char *src, size_t dstsize)
  • 함수 라이브러리 : #include <string.h>
  • char *dst : 이어질 문자열
  • const char *src : dst뒤에 이을 문자열
  • size_t dstsize : 이어질 개수
  • 리턴값 : dst 기존 길이 + src 길이

 

DESCRIPTION

src문자열을 널값을 고려하여 dstsize만큼 dst문자열 뒤에 이어 붙인다음

dst 기존 길이와 src 기존 길이를 더한 값을 리턴한다.

 

strlcat CODE

size_t    ft_strlcat(char *dst, const char *src, size_t dstsize)
{
    size_t i;

    i = 0;
    while (*dst && i < dstsize)
    {
        dst++;
        i++;
    }
    while (*src && i + 1 < dstsize)
    {
        *dst = *src;
        dst++;
        src++;
        i++;
    }
    if (i < dstsize)
        *dst = 0;
    while (*src)
    {
        i++;
        src++;
    }
    return (i);
}

널값을 고려해주기 때문에 안정성이 좋다.

while에서 i + 1을 해준것은 dstsize가 널값까지 생각한 파라메터이기 때문에 널 값 전까지만 복사를 진행한다.

dst의 길이보다 dstsize가 작다면 이어붙일 수가 없다. 간단하게 말하면 dst를 수정하는 일 없이 리턴값만 계산하여 리턴한다.

dstsize가 dst길이보다 큰 경우에는 dst의 널 위치부터 src문자열을 널값을 고려하여 이어붙인다.

만약 다 이어붙였는데도 dstsize보다 작은경우에는 리턴값을 계산해주기 위해서 src의 널값까지 계산해준다.




strchr


SYNOPSIS

  • 함수 원형 : char *ft_strchr(const char *s, int c)
  • 함수 라이브러리 : #include <string.h>
  • const char *s : 비교를 진행할 문자열
  • int c : 찾을 문자
  • 리턴값 : c를 만났다면 해당 주소값 못 만났다면 널

 

DESCRIPTION

s문자열에서 c문자를 찾으면 해당 주소값을 리턴하고 함수를 종료하고 끝까지 검사해도 없다면 널값을 리턴

 

strchr CODE

char    *ft_strchr(const char *s, int c)
{
    char    *ret;

    ret = (char *)s;
    while (*ret != c)
    {
        if (!*ret)
            return ((void *)0);
        ret++;
    }
    return (ret);
}

딱히 설명할 부분은 없어보인다.




strrchr


SYNOPSIS

  • 함수 원형 : char *ft_strrchr(const char *s, int c)
  • 함수 라이브러리 : #include <string.h>
  • const char *s : 비교를 진행할 문자열
  • int c : 찾을 문자
  • 리턴값 : c를 만났다면 해당 주소값 못 만났다면 널

 

DESCRIPTION

s문자열을 뒤에서부터 검사하면서 c문자를 찾으면 해당 주소값을 리턴하고 함수를 종료하고 끝까지 검사해도 없다면 널값을 리턴

 

strrchr CODE

char    *ft_strrchr(const char *s, int c)
{
    char    *ret;

    ret = (char *)s;
    while (*ret)
        ret++;
    while (*ret != c)
    {
        if (ret == s)
            return ((void *)0);
        ret--;
    }
    return (ret);
}

뒤에서부터 검사하는거 말고는 strchr과 동일하다.




strnstr


SYNOPSIS

  • 함수 원형 : char *ft_strnstr(const char *haystack, const char *needle, size_t len)
  • 함수 라이브러리 : #include <string.h>
  • const char *haystack : 비교를 진행할 문자열
  • const char *needle : 찾을 문자열
  • size_t len : 비교를 진행할 개수
  • 리턴값 : needle을 만났다면 해당 주소값 못 만났다면 널

 

DESCRIPTION

haystack문자열을 검사하면서 needle문자열을 찾으면 해당 주소값을 리턴하고 함수를 종료하고 끝까지 검사해도 없다면 널값을 리턴

 

strnstr CODE

char    *ft_strnstr(const char *haystack, const char *needle, size_t len)
{
    size_t    i;
    char    *ret;

    if (!*haystack && !*needle)
        return ((char *)"");
    if (!haystack || !*haystack)
        return ((void *)0);
    ret = (char *)haystack;
    i = ft_strlen(needle);
    if (!needle)
        return (ret);
    while (i <= len)
    {
        if (!ft_memcmp((const char *)ret, needle, i))
            return (ret);
        ret++;
        len--;
    }
    return ((void *)0);
}

strlen을 이용해서 찾을 문자열의 길이를 구한다음

memcmp를 이용해서 비교한다. 찾으면 해당 주소값 리턴하고 끝까지 검사해도 없다면 널값을 리턴하도록한다.




strncmp


SYNOPSIS

  • 함수 원형 : int ft_strncmp(const char *s1, const char *s2, size_t n)
  • 함수 라이브러리 : #include <string.h>
  • const char *s1 : 비교를 진행할 문자열
  • const char *s2 : 비교를 진행할 문자열
  • size_t n : 비교를 진행할 개수
  • 리턴값 : 검사 진행중에 다른 값이 나오면 *s1에서 *s2를 뺀 값, 검사 후에도 안나오면 0반환

 

DESCRIPTION

s1메모리와 s2메모리를 한 바이트씩 n개만큼 비교해서 다른 값이 나올 경우 *s1에서 *s2를 뺀 값을 리턴하고 종료

만약 n개만큼 비교를 해도 다른 값을 찾지 못했다면 0을 반환한다.

 

strncmp CODE

int    ft_strncmp(const char *s1, const char *s2, size_t n)
{
    unsigned char    c1;
    unsigned char    c2;

    while (n)
    {
        c1 = *s1++;
        c2 = *s2++;
        if (c1 != c2)
            return (c1 - c2);
        if (!c1 || !c2)
            break ;
        n--;
    }
    return (0);
}

strcmp와 같은 원리이다. 다른 점으로는 개수를 지정해준다는 것밖에없다.



3줄 요약

1. 문자와 문자열의 개념을 잘 잡아야한다.

2. 스트링 관련 함수는 string.h가 있을 정도로 유용하고 많이 있다.

3. str*** 함수들을 한번 구현해봄으로써 사용할 때 정확히 알고 사용할것같다. 좋은 경험이다.