반응형


일반적인 String compare 함수는 정확한 string을 비교해서 처리해야 하는 경우들이 많습니다.


그런데 간혹, 문자열이 엇비슷하면 같다고 처리하고 싶을 때도 있습니다.


예를 들면,  

1. "나 ^^ 이뽀 :)~" 와 "나 ^^;;; 이뽀~~~???" 이런 문자열들을 같은 취급 하고 싶은 경우, 

2. "이 름" 과 "이름" 과 같이 공백을 무시하고 싶은경우,


3. 마지막으로  "오늘 아침 날씨" 와 "오늘 오전 날씨" 와 같이 의미 갖는 단어들을  같은 것으로  취급하고 싶은 경우,


들 일것입니다.


3번은 단순 코드로는 해결하기 힘든 내용일 것입니다. 

'비슷한 문자열'이라는 개념을 정리하는 차원에서 써 놓은 항목입니다.



일단 순수한 코드차원에서 접근하자면, 1,2번의 경우에 대해서는 간단한 해결책이 있습니다.


특수문자나 공백을 제외하고 문자열을 비교하는 코드를 작성하여 이를 사용하면 됩니다.





#include <string>

using namespace std;



bool inline
is_ignorable_ch(unsigned char c)
{
if (c<= 0x2F) return true; // control code
/*
U+0020      20  SPACE
U+0021  !   21  EXCLAMATION MARK
U+0022  "   22  QUOTATION MARK
U+0023  #   23  NUMBER SIGN
U+0024  $   24  DOLLAR SIGN
U+0025  %   25  PERCENT SIGN
U+0026  &   26  AMPERSAND
U+0027  '   27  APOSTROPHE
U+0028  (   28  LEFT PARENTHESIS
U+0029  )   29  RIGHT PARENTHESIS
U+002A  *   2a  ASTERISK
U+002B  +   2b  PLUS SIGN
U+002C  ,   2c  COMMA
U+002D  -   2d  HYPHEN-MINUS
U+002E  .   2e  FULL STOP
U+002F  /   2f  SOLIDUS
*/  
else if(0x3A <= c && c<= 0x40) return true;
/*  
U+003A : 3a  COLON
U+003B  ;   3b  SEMICOLON
U+003C  <   3c  LESS-THAN SIGN
U+003D  =   3d  EQUALS SIGN
U+003E  >   3e  GREATER-THAN SIGN
U+003F  ?   3f  QUESTION MARK
U+0040  @   40  COMMERCIAL AT
*/

else if(0x5B <= c && c<= 0x60) return true;
/*
U+005B  [   5b  LEFT SQUARE BRACKET
U+005C  \   5c  REVERSE SOLIDUS
U+005D  ]   5d  RIGHT SQUARE BRACKET
U+005E  ^   5e  CIRCUMFLEX ACCENT
U+005F  _   5f  LOW LINE
U+0060  `   60  GRAVE ACCENT
*/
else if(0x7B <= c && c<= 0x7E) return true;
/*
U+007B  {   7b  LEFT CURLY BRACKET
U+007C  |   7c  VERTICAL LINE
U+007D  }   7d  RIGHT CURLY BRACKET
U+007E  ~   7e  TILDE
*/
return false;
}

bool
is_similar(const std::string& str1, const std::string& str2)
{
const char* s1 = str1.c_str();
const char* s2 = str2.c_str();
int l1 = str1.size();
int l2 = str2.size();

int i=0,j=0;
for( ;i<l1 && j<l2;)
{
if(is_ignorable_ch(s1[i])){i++; continue;}
if(is_ignorable_ch(s2[j])){j++; continue;}
if(s1[i] != s2[j]) return false;
i++;
j++;
}

for(i ;i<l1;i++)
if(!is_ignorable_ch(s1[i])) return false;

for(j ;j<l2;j++)
if(!is_ignorable_ch(s2[j])) return false;

return true;
}


#define TEST(P1, P2, _EXPECT) do{\
int r = is_similar(P1, P2);\
printf( "%s\t r= %s:\t %s, %s\n"\
,(r == (_EXPECT))?"PASS":"FALSE" \
,(r==true)?"true":"false"\
,#P1 \
,#P2);\
}while(0)

void compare_test()
{

int no = 0;
TEST("","", true);

TEST("", "aaa", false);


TEST("차차차... 해", "", false);

TEST("안녕하세요. ", " 안 녕 하세요, ",true);
TEST("hello... 나는 누구 ?", "hello나는누구",true);
TEST("hello... ", "he ll. o",true);
}



result 


PASS  r= true:  "", ""

PASS  r= false:  "", "aaa"

PASS  r= false:  "차차차... 해", ""

PASS  r= true:  "안녕하세요. ", " 안 녕 하세요, "

PASS  r= true:  "hello... 나는 누구 ?", "hello나는누구"

PASS  r= true:  "hello... ", "he ll. o"



+ Recent posts