programing

문자열이 C에서 다른 문자열로 시작되는지 확인하는 방법

prostudy 2022. 7. 1. 21:07
반응형

문자열이 C에서 다른 문자열로 시작되는지 확인하는 방법

뭐 이런 거 있어요?startsWith(str_a, str_b)표준 C도서관에서요?

nullbytes로 끝나는2개의 스트링에 포인터를 붙이고 첫 번째 스트링도 두 번째 스트링의 선두에 완전히 표시되는지 여부를 알려 줍니다.

예:

"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc"    -> true

여기에는 표준 함수는 없지만 정의할 수 있습니다.

bool prefix(const char *pre, const char *str)
{
    return strncmp(pre, str, strlen(pre)) == 0;
}

우리는 걱정할 필요가 없다.str보다 짧다pre왜냐하면 C 표준(7.21.4.4/2)에 따라:

strncmp함수는 다음 값 이하를 비교합니다.n(null 문자 뒤에 오는 문자는 비교되지 않습니다)가 가리키는 배열의 문자s1가리킨 배열로s2."

여기에는 표준 C 함수가 없는 것 같습니다.그래서:

bool startsWith(const char *pre, const char *str)
{
    size_t lenpre = strlen(pre),
           lenstr = strlen(str);
    return lenstr < lenpre ? false : memcmp(pre, str, lenpre) == 0;
}

위의 내용은 알기 쉽고 알기 쉬운데, 좁은 루프에서 작업하거나 매우 큰 스트링을 사용하는 경우에는 양쪽 스트링의 전장을 전면에서 스캔하기 때문에 최적의 퍼포먼스를 얻을 수 없습니다.strlenwj32 Christoph와 같은 솔루션은 더 나은 성능을 제공할 수 있습니다(단, 벡터화에 대한 코멘트는 C에 대한 저의 지식을 넘어섭니다).또한 Fred Foo의 솔루션을 통해strlenstr(그가 옳아요. 만약 당신이 그것을 사용한다면,strncmp대신memcmp(매우) 큰 스트링이나 타이트 루프에서의 반복 사용만이 문제가 됩니다만, 문제가 되는 경우는 문제가 됩니다.

나는 아마 함께 갈 것이다.strncmp()다만, 재미삼아 원시적인 실장:

_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
    while(*prefix)
    {
        if(*prefix++ != *string++)
            return 0;
    }

    return 1;
}

사용하다strstr()기능. Stra == strstr(stra, strb)

최적화(v.2. - 수정):

uint32 startsWith( const void* prefix_, const void* str_ ) {
    uint8 _cp, _cs;
    const uint8* _pr = (uint8*) prefix_;
    const uint8* _str = (uint8*) str_;
    while ( ( _cs = *_str++ ) & ( _cp = *_pr++ ) ) {
        if ( _cp != _cs ) return 0;
    }
    return !_cp;
}

또는 다음 두 가지 접근 방식을 조합할 수도 있습니다.

_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
    char * const restrict prefix_end = prefix + 13;
    while (1)
    {
        if ( 0 == *prefix  )
            return 1;   
        if ( *prefix++ != *string++)
            return 0;
        if ( prefix_end <= prefix  )
            return 0 == strncmp(prefix, string, strlen(prefix));
    }  
}

편집: strncmp가 0을 반환하는 경우 종단0 또는 길이(block_size)에 도달했는지 알 수 없기 때문에 다음 코드가 작동하지 않습니다.

블럭별로 비교하는 방법도 있습니다.블록이 동일하지 않으면 해당 블록을 원래 함수와 비교합니다.

_Bool starts_with_big(const char *restrict string, const char *restrict prefix)
{
    size_t block_size = 64;
    while (1)
    {
        if ( 0 != strncmp( string, prefix, block_size ) )
          return starts_with( string, prefix);
        string += block_size;
        prefix += block_size;
        if ( block_size < 4096 )
          block_size *= 2;
    }
}

상수13,64,4096, 및 의 지수화block_size그냥 추측일 뿐이야사용된 입력 데이터 및 하드웨어에 대해 선택해야 합니다.

우아한 코드를 쓰는 데는 전문가가 아니지만...

int prefix(const char *pre, const char *str)
{
    char cp;
    char cs;

    if (!*pre)
        return 1;

    while ((cp = *pre++) && (cs = *str++))
    {
        if (cp != cs)
            return 0;
    }

    if (!cs)
        return 0;

    return 1;
}

승인된 버전을 실행했는데 스트링이 너무 길어서 문제가 있었기 때문에 다음 논리를 추가해야 했습니다.

bool longEnough(const char *str, int min_length) {
    int length = 0;
    while (str[length] && length < min_length)
        length++;
    if (length == min_length)
        return true;
    return false;
}

bool startsWith(const char *pre, const char *str) {
    size_t lenpre = strlen(pre);
    return longEnough(str, lenpre) ? strncmp(str, pre, lenpre) == 0 : false;
}

다음 매크로를 사용합니다.

#define STARTS_WITH(string_to_check, prefix) (strncmp(string_to_check, prefix, ((sizeof(prefix) / sizeof(prefix[0])) - 1)) ? 0:((sizeof(prefix) / sizeof(prefix[0])) - 1))

문자열이 접두사로 시작하는 경우 prexif 길이를 반환합니다.이 길이는 컴파일 시간(크기)으로 평가되므로 런타임 오버헤드가 발생하지 않습니다.

언급URL : https://stackoverflow.com/questions/4770985/how-to-check-if-a-string-starts-with-another-string-in-c

반응형