[질문] 임의의 문자열을 토큰으로 잘라내는 효율적인 방법
임의의 문자열이 아래와 같이 있고,
string Question = "test|test2|sub_len|sub11$sub12$sub13|sub21$sub22$sub23|sub31$sub32$sub33|";
char *tempP에도 Question의 주소를 넣어놨습니다.(printf("[%s]",tempP)하면 위와 같은 문자열이 찍힙니다.)
토큰은 |,$,^입니다. test와 test2는 임의의 데이터 이고,
sub_len은 뒤에 나올 sub test($를 구분자로 갖는)의 갯수 입니다.
토큰 ^는 sub11,sub12,sub13내부에서 다시 토큰으로 이용됩니다.(복잡해라 ㅠ _ㅠ)
위와 같은 문자열을 먼저 |로 잘라내고 sub_len을 얻은 다음
sub_len을 이용하여 포문등을 돌려서 다시 $를 이용하여 안의 내용을 얻어내야 하는 상황인데
sub11,sub12,sub13등의 sub string에는 |,$,^등의 문자가 올수 있습니다.(모든 문자가 sub string으로 가능합니다.)
따라서 sub11안에 있는 |와 $는 토큰과 구분되어지기위하여 ^|, ^$, ^^으로 변형되어 저장 됩니다.
최종적으로 얻어내야할 내용은 벡터로 구성되어야 하기 때문에 string(C++)으로 각각의 내용을 얻어야 하고,
뭐 중간에는 편의를 위하여 char *tempP등을 선언해서 strncmp등을 이용했습니다.
결과적으로 문자열은 얻었지만... 너무 막 코딩의 느낌을 지울 수가 없어서
위와 같은 상황이라면 고수님들은 어떤식으로 구조를 잡을지 궁금합니다.
저는 대략
먼저 string.find함수로 내용을 test,test2,sublen,substr 크게 네덩이로 나눠서 각각 string 변수에 다시 집어넣고
sublen의 내용을 다시 파싱하기 위하여 sub_len만큼 |로루프를 돌리면서 다시 안의 내용을 $를 이용해서 잘라냈습니다.
이때 첫번째 포문에서 find로 얻어온 position이 구분자가 |이기 때문에 ^|, 또한 find함수에 의하여 잡히기 때문에
일단 find에 의해서 찾아진 값의 검사를 위하여 find함수로 잡아낸 포지션을 strncmp(tempP+포지션-2, "^|", 2) == 0로
검사해서 실제 |(구분자)인지 확인 합니다.
이때, 문제가 sub str의 데이터가 ^^| 이렇게 들어있었다면(실제로 ^가 데이터이고 |가 구분자인 상황)
^|로 strncmp라고 해버리면 문제가 되기 때문에 ^|로 걸리면 다시
strncmp로 앞의 3자리 비교를 합니다.(^^|인지 아닌지)
(char *를 사용한 이유는 c++은 완전 초보인데다 string함수를 처음 써보는 관계로 string함수도 c처럼 직접
char *형 변수+숫자 하여 직접 해당 번지의 내용을 읽어 낼 수 없었기 때문입니다 ㅠ _ㅠ)
위와같이 매우 구차한 방법으로 검사를 하고 있는 상황 입니다.
실제로 포문이 저거말고 ^까지 파싱을위해 하나더 있는상황에서 코드를 보면 스스로 짜놓고도 챙피 합니다.
뭔가 string에 준비된 멋진 함수가 많을 것 같기도 하고 이렇게 구차하게 구현하는것 말고
좀더 아름-_-다운 방법이 있을 것이다라는 생각에 질문을 올려 봅니다.
슈더코드로 제안해주셔도 좋고 직접 내용을 작성해주셔도 좋습니다.
공부하는 입장에서 하나하나 할때마다 뭔가 더 좋은 방법이 있을텐데 라는 생각때문에 하루하루가 매우 힘든 초보 였습니다.
좋은 하루 보내시길 바랍니다.
저는 이번학기
저는 이번학기 컴파일러를 배우면서 문자열에서 토큰 추출하는것에 감동 먹었습니다. 그전까찌는 토큰은 무조건 공백으로 결정하거나 했었는데..
lex를 한번 배워보세요
lex
lex라 일단 검색부터 해봐야겠네요 ^^
일단 이번 문제는 C/C++을 이용해야 하는 상황이라
lex가 뭔지부터 검색해봐야겠네요
감사합니다 ^ _^ //
boost의 정규표현식
boost의 정규표현식 라이브러리를 이용해보면 어떨까요?
다만, boost의 정규표현식의 경우 컴파일해서 써야되고 배포시에 라이브러리도 같이 들어가야되므로 배보다 배꼽이 클지도 모르겠는데,
저런식으로 파싱을 자주해야한다면 유용할수 도 있다고 생각합니다.
(참고로 전 boost의 정규표현식라이브러리는 써본적 없습니다-_-;)
boost 정규 표현식
일단 이번에 할 내용은 일회성 파싱이라
라이브러리까지 이용하기는 좀 그렇고
학습을위하여 꼭 사용해보겠습니다.
요새 코딩에 뭔가 좀 흥미를 느끼고 있어서 유용한 정보 감사합니다 ^^
일단
주어진것은 BNF형식으로 나타내면 그닥 복잡할것 같지는 않네요
생각보다 간단한 문법이 될것 같아요.
TC++PL에 4장인가? 계산기 인터프리터 만드는 부분이 있습니다. 그쪽 참고하시면 도움이 되실듯
넵
좋은 조언 감사드립니다 ^^
참고 해 보도록 하겠습니다. :)
man strtok(3),
man strtok(3), strtok_r(3)
--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
strtok
대신 string의 find를 사용하고 있습니다.
역시 손에익은 strtok가 편하긴한데
string계열 사용하다보니... 엄청 좋네요 : )
댓글 달기