programing

strcase cmp 알고리즘에 결함이 있습니까?

topblog 2023. 9. 15. 20:41
반응형

strcase cmp 알고리즘에 결함이 있습니까?

나는 그것을 다시 구현하려고 노력하고 있습니다.strcasecmpC의 함수를 보고 비교 과정에서 불일치로 보이는 것을 발견했습니다.

부터man strcmp

strcmp() 함수는 두 문자열 s1과 s2를 비교합니다.로케일은 고려되지 않습니다(로케일 인식 비교는 strcoll(3) 참조).s1이 s2보다 작거나 일치하거나 s2보다 크면 0보다 작거나 같거나 큰 정수를 반환합니다.

부터man strcasecmp

strcasecmp() 함수는 문자열 s1과 s2의 바이트 단위 비교를 수행하며 문자의 경우는 무시합니다.s1이 s2보다 작거나 일치하거나 s2보다 크면 0보다 작거나 같거나 큰 정수를 반환합니다.

int strcmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2);

이 정보를 고려하면 다음 코드의 결과를 이해할 수 없습니다.

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

int main()
{
    // ASCII values
    // 'A' = 65
    // '_' = 95
    // 'a' = 97

    printf("%i\n", strcmp("A", "_"));
    printf("%i\n", strcmp("a", "_"));
    printf("%i\n", strcasecmp("A", "_"));
    printf("%i\n", strcasecmp("a", "_"));
    return 0;
}

출력:

-1  # "A" is less than "_"
1   # "a" is more than "_"
2   # "A" is more than "_" with strcasecmp ???
2   # "a" is more than "_" with strcasecmp

다음과 같이 표시됩니다. 현재 문자가s1문자입니다. 현재 문자 여부에 관계없이 항상 소문자로 변환됩니다.s2편지인지 아닌지.

누가 이 행동을 설명해 줄 수 있습니까?첫 번째 줄과 세 번째 줄이 같아야 하는 거 아닌가요?

미리 감사드립니다!

PS:
사용중입니다gcc 9.2.0만자로에
그리고 제가 컴파일을 할 때.-fno-builtin대신 받는 깃발:

-30
2
2
2

프로그램이 gcc의 최적화된 기능을 사용하지 않아서 그런 것 같은데 의문이 남습니다.

동작이 정확합니다.

POSIX 사양에 따라:

언제.LC_CTYPE사용 중인 로케일의 범주는 POSIX 로케일에서 가져온 것이며, 이 함수들은 문자열이 소문자로 변환된 후 바이트 비교를 수행한 것처럼 동작해야 합니다.그렇지 않으면 결과가 지정되지 않습니다.

이는 Linux man 페이지의 NOTES 섹션의 일부이기도 합니다.

POSIX.1-2008 표준에는 다음과 같은 기능이 있습니다.

사용 중인 로케일의 LC_CTYPE 범주가 POSIX 로케일에서 가져온 경우, 이러한 함수는 문자열이 소문자로 변환된 후 바이트 비교를 수행한 것처럼 동작합니다.그렇지 않으면 결과가 지정되지 않습니다.

왜요?

@HansOlsson이 그의 답변에서 지적했듯이, 문자들 간에 대소문자 구분이 없는 비교를 하고, 다른 모든 비교들이 그들의 "자연스러운" 결과를 가질 수 있도록 합니다.strcmp()분류가 깨질 겁니다

한다면'A' == 'a'(를 구분하지) 그러면 (대소문자를 구분하지 않는 비교의 정의)면'_' > 'A'그리고.'_' < 'a'(ASCII 문자 집합의 "자연" 결과) 둘 다 참일 수 없습니다.

다른 링크인 strcasecmp의 http://man7.org/linux/man-pages/man3/strcasecmp.3p.html 에서는 소문자로 변환하는 것이 올바른 동작이라고 합니다(적어도 POSIX 로케일에서는).

이러한 동작의 이유는 strcasecmp를 사용하여 문자열 배열을 정렬하는 경우 합리적인 결과를 얻기 위해 필요하기 때문입니다.

그렇지 않으면 qsort와 같은 방법으로 "A", "C", "_", "b"를 정렬하려고 하면 결과는 비교 순서에 따라 달라집니다.

s1의 현재 문자가 문자인 경우 s2의 현재 문자가 문자인지 여부에 관계없이 항상 소문자로 변환되는 것으로 보입니다.

요입니다. 그리고 그게 바로 그 사람이strcasecmp()기능이 있어야 합니다!그것은.POSIX가닌닌가의 가 아닌 C표준이지만 "오픈 그룹 베이스 사양, 이슈 6"에서:

POSIX 로케일에서 strcase cmp() 및 strncase cmp()는 문자열이 소문자로 변환된 후 바이트 비교를 수행한 것처럼 동작해야 합니다.결과는 다른 로케일에서 지정되지 않습니다.

덧붙여서, 이 동작은 (Visual Studio/MSCV에서 사용되는) 기능과도 관련이 있습니다.

_stricmp 함수는 일반적으로 각 문자를 소문자로 변환한 후 string1과 string2를 비교하고 이들의 관계를 나타내는 값을 반환합니다.

ASCII 10 의 10진수 A이다 ㅇ65위해서_이다 ㅇ95…에 a이다 ㅇ97,그렇게strcmp()해야 할 일을 하는 겁니다사전적으로 말하면_다다 보다 .a다더큰큰더보다 더 큰A.

strcasecmp()고려할 것A있는 그대로a *, 로 a 보다 큽니다._출력 또한 정확합니다.

*POSIX.1-2008 표준에는 다음과 같은 기능이 있습니다(strcase cmp()).

사용 중인 로케일의 LC_CTYPE 범주가 POSIX 로케일에서 가져온 경우, 이러한 함수는 문자열이 소문자로 변환된 후 바이트 비교를 수행한 것처럼 동작합니다.그렇지 않으면 결과가 지정되지 않습니다.

출처 : http://man7.org/linux/man-pages/man3/strcasecmp.3.html

언급URL : https://stackoverflow.com/questions/60342445/is-the-strcasecmp-algorithm-flawed

반응형