프로그램을 하다보면 문자열 처리시 문자열에 포함된 특정 문자를 제거해야하는 경우가 종종있습니다.
예를들어, 어떤 명칭을 입력받으면서 공백없이 입력해달라고 했는데 사용자의 실수로 공백이 같이 입력되면
처리하는쪽에서 문자열에 공백이 있는지 여부를 체크하고 공백이 있다면 해당 공백을 제거해야합니다.
MFC를 사용하다보면 문자열 처리시에 CString 클래스를 많이 사용하는데, CString 클래스의 멤버함수중에
Remove 라는 함수가 있고 이 함수가 CString이 관리하는 문자열에서 특정 문자를 제거하는 기능입니다.
예를들면, 아래와 같습니다.
CString str = "Hello World!!";
str.Remove(' ');
AfxMessageBox(str);
이렇게 하면 결과가 아래와 같이 문자열에 공백이 제거된 상태로 메시지박스에 출력됩니다.
HelloWorld
하지만, 여기에 문제가 있습니다. 이 CString 클래스자체가 한글을 기준으로 제작된 클래스가 아니라서
한글이 포함된 문자열인 경우 Remove 함수를 사용하면 원하지 않는 결과가 발생합니다.
한글코드가 "한글여부(1bit) + 초성(5bit) + 중성(5bit) + 종성(5bit) = 총 2바이트(16비트)"로 구성되기
때문에 영문기준으로 1바이트씩 문자열을 비교하다보면 "디", "바"와 같이 종성이 없거나 종과 같이 종성이
존재하는 경우라도 한글문자가 공백다음에 놓이면 문자열값이 변형되는 문제가 발생합니다.
변경전 CString::Remove(' ')를 이용하여 변경한 후...
"다 다" --> "다도"
"다 바" --> "다뭐"
"다 종" --> "다좋"
결국 조금 불편하더라도 한글이 포함된 문자열에서 특정 문자를 제거하는 경우에는 한글을 고려해서
문자열 처리가 될수 있도록 아래와 같이 함수를 구성해서 사용하는것이 좋습니다.
void www_tipssoft_com_RemoveCharFromString(CString &parm_string, char parm_remove_char)
{
int count = parm_string.GetLength(), index = 0;
if(count > 0){
// 문자열 제거에 사용할 버퍼를 생성한다. 이 버퍼는 기준 문자열보다 클 필요가 없다.
char *p_data = new char[count + 1];
for(int i = 0; i < count; i++){
if(parm_string[i] & 0x80){
// 한글인 경우는 2바이트로 구성되기 때문에 1바이트 정보인 parm_remove_char와 비교할
// 필요가 없다. 따라서 그냥 2바이트 정보를 모두 복사해주면 된다.
p_data[index++] = parm_string[i++];
p_data[index++] = parm_string[i];
} else {
// 한글이 아닌 경우는 정보가 1바이트씩 구성되기 때문에 parm_remove_char에 지정된
// 문자와 비교하여 다른 경우에만 복사한다.
if(parm_remove_char != parm_string[i]) p_data[index++] = parm_string[i];
}
}
// parm_remove_char를 뺀 나머지 문자가 복사된 문자열의 끝에 '\0'을 추가한다.
p_data[index] = 0;
// parm_remove_char가 제거된 문자열을 원본 문자열에 저장한다.
parm_string = p_data;
// 문자열 제거에 사용한 버퍼를 제거한다.
delete[] p_data;
}
}
사용방법 :
CString str = "이동 디스크";
www_tipssoft_com_RemoveCharFromString(str, ' ');
AfxMessageBox(str);
이렇게 하면 결과가 아래와 같이 문자열에 공백이 제거된 상태로 메시지박스에 출력됩니다.
( CString::Remove 함수를 사용하면 "이동도슬탤" 라고 출력됩니다. )
이동디스크
출처 : 팁스 소프트
http://www.tipssoft.com/bulletin/tb.php/FAQ/253