일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 암시적 변환
- 메타테이블
- Vector
- c++
- 언리얼
- 영화 리뷰
- effective stl
- 예외
- resource management class
- Effective c++
- implicit conversion
- 스마트 포인터
- more effective c++
- 게임
- 비교 함수 객체
- Smart Pointer
- 참조자
- 티스토리챌린지
- 영화
- virtual function
- operator new
- 반복자
- lua
- 상속
- 다형성
- 오블완
- 루아
- UE4
- exception
- reference
Archives
- Today
- Total
스토리텔링 개발자
[Effective STL] 35. 대소문자 구분하지 않는 법 본문
728x90
항목 35. 대소문자를 구분하지 않는 문자열 비교는 mismatch 아니면 lexicographical_compare를 써서 간단히 구현할 수 있다.
대소문자를 구분하지 않기
- 구분하지 않는 정도를 얼만큼이나 원하는가.
- 국제화(internationalization) 사항은 무시하고 단지 strcmp 동작 정도만 원한다면 쉽다.
- 다국어 처리까지 원한다거나, 기본 로케일 이외의 로케일을 사용한다면 어렵다.
- 하지만 이번 항목에서 다루는 것은 쉬운 버전이다.
문자열을 비교하는 인터페이스 두 가지
- strcmp와 비슷한 인터페이스
- 음수, 0, 양수를 반환한다.
- operator<와 비슷한 인터페이스
- true, false를 반환한다.
첫 번째 버전
// 대소문자 구분 없이 문자 비교 함수
int ciCharCompare(char c1, char c2)
{
// 소문자로 바꾼다.
// tolower의 매개 변수와 반환값은 int이지만,
// int가 EOF가 아니기만 하면 이 값은 unsigned char가 되어도 괜찮다.
int lc1 = tolower(static_cast<unsigned char>(c1));
int lc2 = tolower(static_cast<unsigned char>(c2));
// 비교
if(lc1 < lc2) return -1;
if(lc1 > lc2) return 1;
return 0;
}
// 대소문자 구분 없이 문자열 비교 impl 함수
int ciStringCompareImpl(const string& s1, const string& s2); // 아래에서 정의
// 대소문자 구분 없이 문자열 비교 함수
int ciStringCompare(const string& s1, const string& s2)
{
if(s1.size() <= s2.size())
return ciStringCompareImple(s1, s2);
else
return -ciStringCompareImpl(s2, s1);
}
int ciStringCompareImpl(const string& s1, const string& s2)
{
using PSCI = pair<string::const_iterator, string::cosnt_iterator>;
// mismatch : 두 범위에서 첫 번째로 일치하지 않는 요소를 찾는다.
PSCI p = mismatch(s1.begin(), s1.end(), s2.begin(), not2(ptr_fun(ciCharCompare)));
// s1을 끝까지 비교했는가
if(p.first == s1.end())
{
// s2도 끝까지 비교했다면 같으므로 0 리턴
if(p.second == s2.end())
return 0;
else
return -1;
}
return ciCharCompare(*p.first, *p.second);
}
- not2(ptr_fun(ciCharCompare)
- 이 술어는 두 개의 문자가 일치하면 true를 반환해야 한다.
- 헌데 ciCharCompare은 -1, 0, 1을 반환하는 함수이고, 문자가 같으면 0을 반환한다.
- c++ 컴파일러는 int를 bool로 암시적 변환 할텐데, 0은 false로 변환된다.(true여야 하는데!)
- -1, 1 등은 true로 변환한다.(false여야 하는데!)
- 그래서 not2와 ptr_fun을 붙였다. ptr_fun은..(항목 41 참조)
두 번째 버전
bool ciCharLess(char c1, char c2)
{
return tolower(static_cast<unsigned char>(c1)) < tolower(static_cast<unsigned char>(c2));
}
// operator<처럼 동작한다.
// 즉, s1이 사전상 앞에 있다면 true, 그렇지 않으면 false
bool ciStringCompare(const string& s1, const string& s2)
{
return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), ciCharLess);
}
- lexicographical_compare
- 두 범위의 요소를 사전순(lexicographical)으로 비교한다. 두 범위의 요소를 차례로 비교하며, 첫 번째 범위가 두 번째 범위보다 사전순으로 앞서면 true를 반환하고, 그렇지 않으면 false를 반환한다.
- 즉, strcmp를 일반화한 알고리즘이다.
- strcmp는 문자 배열에 대해서만 동작하는 반면,
- lexicographical_compare에 들어가는 범위의 데이터는 어떤 타입도 될 수 있다.
- strcmp는 두 문자를 코드 값으로 비교하여 같은지 작은지 큰지를 점검하는 반면,
- lexicographical_compare의 두 요소 대소 관계 비교는 사용자가 정의할 수 있다.
- strcmp는 문자 배열에 대해서만 동작하는 반면,
이식성(portability)에 관해..
- 이식성이 정말 별 상관이 없다면, 비표준으로 구현된 함수를 사용하면 된다.
- stricmp나 strcmpi 등이 그것이다.
- 이들은 오로지 문자열 비교만을 하도록 최적화되어 있으므로 월등히 빠르다.
728x90
'개발 > Effective STL' 카테고리의 다른 글
[Effective STL] 37. 범위 요약(summarize) (0) | 2025.01.02 |
---|---|
[Effective STL] 36. copy_if (0) | 2024.12.26 |
[Effective STL] 34. 정렬된 범위에 동작하는 알고리즘 (0) | 2024.12.23 |
[Effective STL] 33. 포인터 요소에 remove 알고리즘 사용 주의하기 (0) | 2024.12.20 |
[Effective STL] 32. remove-erase 관용구 (0) | 2024.12.19 |
Comments