C++에서 regex 쓸 때 주의점
08 Jan 2018C++11 이후 버전에서 공식적으로 정규표현식을 사용하게 되면서 C++에서 문자열을 파싱하기가 한결 수월해졌다. 하지만 오늘 업무 중에 regex 의 동작 방법을 잘 몰라서 고생할 뻔했기에 기록을 남겨둔다.
아래의 코드는 regex를 사용하는 기본 코드이다.
#include <iostream>
#include <regex>
using namespace std;
int main() {
regex rPattern("(\\w+)_(\\d+)");
smatch mResult;
string sInput = "abc_123";
if (regex_match(sInput, mResult, rPattern))
cout << mResult[1] << " " << mResult[2] << endl;
return 0;
}
위의 코드를 실행하면 다음과 같은 결과를 얻는다.
abc 123
그런데, regex에 사용되는 input string의 scope를 조금 다르게 하면 예상치 못한 결과가 나온다.
#include <iostream>
#include <regex>
using namespace std;
int main() {
regex rPattern("(\\w+)_(\\d+)");
smatch mResult;
{
// if문이라던지.. for 안에서 input을 받아서 밖으로 넘기고 싶다....
string sInput = "abc_123";
if (regex_match(sInput, mResult, rPattern))
cout << mResult[1] << " " << mResult[2] << endl;
}
cout << mResult[1] << " " << mResult[2] << endl;
return 0;
}
위의 코드를 작성하면서 다음과 같은 결과를 원했다.
abc 123
abc 123
하지만 실제로 코드를 실행해보면 다음과 같이 나온다.
abc 123
bc 123 // 꼭 이렇게 나오지는 않을 수 있다.
실제로 smatch는 match_results<string::const_iterator> 의 typedef 형인데, 해당 템플릿 타입의 멤버변수 _Org 을 갖는다. regex_match를 수행하는 과정에 레퍼런스로 넘어간 smatch 변수가 채워지게 되고, 이때 _Org이 input string을 가르키는 iterator가 된다. 따라서 input string의 scope 밖으로 넘어가면 smatch 객체 내부가 깨지게 되는 것으로 보인다.
한 이틀 고생할 만한 것이었는데 다행히 15분만에 찾고 넘겨서 다행이다.
regex를 쓸 때에는 input string의 scope 내에서 사용하도록 하자.