strcase cmp 알고리즘에 결함이 있습니까?
나는 그것을 다시 구현하려고 노력하고 있습니다.strcasecmp
C의 함수를 보고 비교 과정에서 불일치로 보이는 것을 발견했습니다.
부터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의 최적화된 기능을 사용하지 않아서 그런 것 같은데 의문이 남습니다.
동작이 정확합니다.
언제.
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
'programing' 카테고리의 다른 글
세로 스크롤 기반 jquery로 클래스 추가/제거? (0) | 2023.09.15 |
---|---|
jQuery 및 HTML을 사용하여 CSV로 내보내기 (0) | 2023.09.15 |
MySQL 데이터베이스에 파일을 삽입하는 방법? (0) | 2023.09.15 |
XPath contains()를 여기서 사용하는 방법? (0) | 2023.09.15 |
모든 jQuery AJAX 요청에 사용자 지정 http 헤더 추가 (0) | 2023.09.15 |