Programing

문자열이 C에서 다른 문자열로 시작하는지 확인하는 방법은 무엇입니까?

crosscheck 2020. 10. 28. 07:44
반응형

문자열이 C에서 다른 문자열로 시작하는지 확인하는 방법은 무엇입니까?


startsWith(str_a, str_b)표준 C 라이브러리 와 같은 것이 있습니까?

널 바이트로 끝나는 두 문자열에 대한 포인터를 가져 와서 첫 번째 문자열도 두 번째 문자열의 시작 부분에 완전히 나타나는지 여부를 알려줍니다.

예 :

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

분명히 이것에 대한 표준 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;
}

위의 내용은 훌륭하고 명확하지만 꽉 끼거나 매우 큰 문자열로 작업 하는 경우 두 문자열의 전체 길이를 앞에서 스캔하므로 최상의 성능을 제공하지 못할 수 있습니다 ( strlen). wj32 또는 Christoph 와 같은 솔루션 은 더 나은 성능을 제공 할 수 있습니다 (하지만 벡터화에 대한 이 설명 은 C의 범위를 벗어납니다). 또한주의 프레드 푸의 솔루션strlen에를 str(당신이 사용하는 경우 그 오른쪽이 불필요 것 strncmp대신에 memcmp). (매우) 큰 문자열 또는 타이트 루프에서 반복적으로 사용하는 경우에만 중요하지만 중요 할 때는 중요합니다.


이에 대한 표준 기능은 없지만 정의 할 수 있습니다.

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

C 표준 (7.21.4.4/2)에 따라 str짧아지는 것에 대해 걱정할 필요가 없습니다 pre.

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


나는 아마 함께 갈 strncmp()것이지만 재미를 위해 원시 구현을 :

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

    return 1;
}

나는 우아한 코드를 작성하는 데 전문가는 아니지만 ...

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;
}

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;
}

허용 된 버전을 실행하고 매우 긴 str에 문제가 있었기 때문에 다음 논리를 추가해야했습니다.

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;
}

또는 두 가지 접근 방식의 조합 :

_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));
    }  
}

EDIT: The code below does NOT work because if strncmp returns 0 it is not known if a terminating 0 or the length (block_size) was reached.

An additional idea is to compare block-wise. If the block is not equal compare that block with the original function:

_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;
    }
}

The constants 13, 64, 4096, as well as the exponentiation of the block_size are just guesses. It would have to be selected for the used input data and hardware.

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

반응형