![]() |
|
||||||||
경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지 |
|
저도 명쾌하게 이해가 안되어서 자세히 쓰지 않은 건데..
어리버리한 넘 잔머리의 바닥까지 들여다보시려고... ㅎㅎㅎ _wcsicmp의 문제니까 제 머리의 동작 방식으로는 자연스럽게 _wcsicmp의 소스를 들여다보려고 했었죠. 근데 _wcsicmp 함수 자체의 소스는 없고, t로 시작하는 tchar 버전의 함수로 define이 되어 있더군요. 그리고 C++빌더에 포함된 소스들을 뒤져보니 그 함수의 소스가 있어서 들여다보니, locale.IsCLocale이던가 하는 구조체 멤버를 참조해서 그에 따라 if 문 분기를 하도록 되어 있더군요. 이 IsCLocale 멤버로 검색을 해보니 별다른 정보는 안나오고, 다만 일본의 C++빌더 개발자가 다른 함수 하나에서 비슷한 문제를 겪은 기록도 나오고요. IsCLocale은 BOOL 타입으로 TRUE FALSE 값을 가질 수 있죠. TRUE이면 위에서 박우성님이 말씀하신 결과가 나오니까 FALSE로 설정되게 하면 되겠지요. 그래서 이 IsCLocale 멤버를 강제로 설정해보니 잘 되긴 했습니다. (IsCLocale이라는 이름 자체가 "로케일이 C이냐"라는 의미겠지요?) 그런데 그 정도로 마무리하려다 보니, 이 IsCLocale이 포함되어 있는 헤더파일 locale.h가 include 아래가 아닌 source/cpprtl/rtlinc 아래에 있어서 좀 불편하게 되어 있더군요. 물론 include가 아닌 다른 디렉토리에 있으면 #include <../source/cpprtl/rtlinc/locale.h> 이렇게 해버리면 되긴 하지만, 이건 좀 아니다 싶어서 다른 방법을 찾기 시작했습니다. 그래서 찾은 넘이 setlocale() 함수였습니다. 이넘을 찾게 된 것은, 앞서 말한 locale.h 헤더가 표준 헤더 디렉토리인 include 디렉토리가 아닌 다른 디렉토리에 있으므로 include에 뭔가 비슷한 역할로 사용할 수 있는 넘이 있을 거라고 추론을 한 거였구요. 그래서 찾은 것이 setlocale()이었죠. 이놈의 값을 위 댓글처럼 설정해보니 IsCLocale을 설정한 것과 똑같이 동작했습니다. 즉 IsCLocale의 값이 따라서 바뀌더군요. 제가 가장 이해가 안되었던 것은, 로케일에 왜 "C"라는 값이 디폴트인지였습니다. 검색을 해보니 이건 C++빌더 이외의 다른 컴파일러에서도 당연한 듯 한데요. 왜인지는 몰라도 어쨌든 당연한 것 같기는 합니다. 이제 아시겠지만 저도 별 대단할 게 없는 평범한 개발자입니다. 저도 궁금해서 아침부터 일도 접어두고 거의 두시간 정도 이래저래 뒤져보고 알아낸 거였네요. 임프님 분석을 보고 매뉴얼을 찾아봤는데, C++빌더 메뉴얼에는 locale관련 내용이 없는데, MSDN에는 샘플소스까지 있습니다.
// crt_stricmp_locale.c #include <string.h> #include <stdio.h> #include <locale.h> int main() { setlocale(LC_ALL,"C"); // in effect by default printf("\n%d",_wcsicmp(L"ä", L"Ä")); // compare fails setlocale(LC_ALL,""); printf("\n%d",_wcsicmp(L"ä", L"Ä")); // compare succeeds } locale 설정이 잘못되면 비교실패가 되네요. 근데, 공교롭게도 비교실패의 결과로 C++빌더에서는 그냥 0을 리턴에 버립니다. 결과값만 보고 비교실패인지 알 방법이 없죠. C++빌더를 주로 사용하다 보니까, 당연히 매뉴얼도 C++빌더에 있는 것을 참조하게 되는데, 앞으로는 MSDN 매뉴얼을 참조해야 할 것 같습니다. 엠바카데로에서 매뉴얼좀 잘 만들어 주면 좋겠네요. 관련 글 리스트
|
Copyright © 1999-2015, borlandforum.com. All right reserved. |
결론부터 말하자면, 프로그램 초기화시에 다음과 같이 한 줄을 추가해주면 _wcsicmp()에서 제대로 된 결과를 리턴할 겁니다.
setlocale(LC_CTYPE, "");
저도 아리까리합니다만, 어쨌든 C++빌더에서 _wcsicmp() 구현이 C 로케일의 영향을 받게 되어 있나봅니다.
그런데 C++빌더에서 이 로케일의 기본값이 시스템 디폴트 값이 아니라, "C"로 되어 있습니다.
이렇게 로케일 값이 "C"인 경우, _wcsicmp() 함수가 좀 다르게 동작하더군요.
setlocale() 함수는 여러가지 로케일 값들을 설정하는 함수인데, 첫번째로 넘겨줬던 LC_CTYPE은 설정할 로케일의 종류중 하나로서 문자의 취급에 대한 분류이고요, 두번째로 넘겨준 ""는 시스템 디폴트 로케일로 설정하라는 의미입니다.
그래서, 지금까지 작업하셨던 모든 소스에서 다 수정하기보다는, 모든 프로젝트의 초기화 부분에서 setlocale() 함수를 한번씩만 호출하기만 하면 될 것 같네요.