프로그래밍 2014. 5. 21. 18:25
728x90

 

 

C++ 문자열 테이블 만들기 ( C++ make string table ), 문자열 파싱

 

 

txt 파일이 있고,

 

< id='1' color='255|10|0' text='나공간' >
< id='2' color='255|255|255' text='1476년\n고려왕조가 멸망하고, 조선왕조가 건국된지 수십년의 세월이 흘렀다.\n새 왕조는 기세를 확장하여
점차 기반을 다져가고 있었다. 그러나 백성들의 곤궁한 삶은 별로 나아진 것이 없었다.' >

....

....

 

이런 식으로 문자열 테이블을 관리하고 싶을 때

 

사용할 수 있는

 

간단한 문자열 파싱 소스입니다.

 

예제는

id, color(r,g,b), text 등을 문자열마다 지정해 두고 사용할 수 있습니다.

 

 

#define MAX_SCRIPT_LINESIZE  255
#define SCRIPTTEXT_HEADER  0xf7063dd1


#define SCRIPT_BIG_SEP   "<>" //제일큰 구분자
#define SCRIPT_SMALL_SEP  "=()'<>{}[]|" //.은 소수점 표현에 사용된다
                                                          //,은 텍스트에서 쉼표로 사용

 

#define SCRIPT_CMD( string, var ) (strstr(string,var) ? 1 : 0) //string안에 var가 있는지 찾는다

 


void FileLoad( const char *_pszFile )
{

 

 //파일 열기
 FILE *fp=NULL;
 fopen_s( &fp, _pszFile, "rt" );
 if( !fp )
 {
  char szMessage[200];
  sprintf_s( szMessage, "CScript_Text> %s file is invalid!", _pszFile );
  MessageBoxA( NULL, szMessage, "FILE LOAD", MB_OK );
  return;
 }

 

 char szLine[MAX_SCRIPT_LINESIZE];

 std::string STR;
 STR.reserve( 1500 ); //문자열을 저장할 버퍼, 크기는 용도만큼 잡아서 사용
 
 BYTE nType = 0;

 

 //한 라인씩 읽어 들이면서, 각각의 문자열을 구성해 줍니다.

 //테이블의 문자열 하나가 여러 라인을 사용하고 있을때는

 //큰 구분자 끝이 나올때까지 문자열을 합칩니다

 while( fgets(szLine, MAX_SCRIPT_LINESIZE, fp) )
 {

 

  //큰 구분자가 있는지 검색하여, 두개다 있으면 라인 하나 짜리
  if( strchr( szLine, '<' ) && strchr( szLine, '>' ) )

  {
   nType = 0;
  }

  //문자열 테이블 시작
  else if( strchr( szLine, '<' ) )
  {
   nType = 1;
  }

  //문자열 테이블 끝
  else if( strchr( szLine, '>' ) )
  {
   nType = 2;
  }

  //큰 구분자가 없으면, 문자열 중간이 되겠지요
  else
  {
   nType = 3;
  }

 

  switch( nType )
  {
  //한라인짜리
  case 0:
   {
    STR = "";
    STR = szLine;

    

    //테이블 문자열 하나의 구성이 완료되었다면, 파싱해 줍니다.

    Parse( (char*)STR.c_str(), pS );
   }
   break;
  
  //라인연결
  case 1:
   {
    STR = "";
    STR += szLine;
   }
   break;

 

  //라인연결끝
  case 2:
   {
    STR += szLine;

   

    //테이블 문자열 하나의 구성이 완료되었다면, 파싱해 줍니다.

    Parse( (char*)STR.c_str(), pS );
   }
   break;

 

  //라인연결중
  case 3:
   {
    STR += szLine;
   }
   break;


 }

 

 fclose( fp );
}

 

//통짜스트링을 각각의 변수들로 파싱한다

void Parse( char* _pszBuffer, SScriptText* _pS )
{
 char* pszValText = NULL;

 

 //strtok 사용시 처음 호출때는 버퍼를 함수 인자로 넘기고,

 pszValText = strtok( (char*)_pszBuffer, SCRIPT_SMALL_SEP );
 while( pszValText != NULL )
 {
  ParseValue( pszValText, _pS );

 

  //문자열 안을 계속 파싱할 때는 NULL 을 대입해 줍니다

  pszValText = strtok( NULL, SCRIPT_SMALL_SEP );
 }
}

 

//분리된 변수들에게서 값을 읽어 들인다

void ParseValue( char* _pszValText, SScriptText* _pS )
{
 if( SCRIPT_CMD(_pszValText, "id") )
 {
  _pszValText = strtok( NULL, SCRIPT_SMALL_SEP );
  int id = atoi(_pszValText);

 }
 else if( SCRIPT_CMD(_pszValText, "color") )
 {
  BYTE r,g,b;

  _pszValText = strtok( NULL, SCRIPT_SMALL_SEP );
  r = atoi(_pszValText);

  _pszValText = strtok( NULL, SCRIPT_SMALL_SEP );
  g = atoi(_pszValText);

  _pszValText = strtok( NULL, SCRIPT_SMALL_SEP );
  b = atoi(_pszValText); 

}

else if( SCRIPT_CMD(_pszValText, "text") )
{
  _pszValText = strtok( NULL, SCRIPT_SMALL_SEP );
}

 

}

 

strtok 를 사용하면 구분자를 넣어서,

구분자를 제외한 사이 사이의 문자열들을 추려낼 수 있습니다.

 

 

바이너리 파일로도 사용가능 하겠지요.

 

저장 할때는

txt 의 라인을 fwrite 를 사용해서 쭉 저장해 두고,

(단, 저장 & 읽어들일 라인의 크기는 정해두어야 합니다. )

 

읽을 때는

fread 를 이용해서 읽어들이면 됩니다.

 

파싱 부분은 어차피 char 데이타를 파싱하는 것이라,

동일하게 사용할 수 있습니다.

 

 

 

728x90

'프로그래밍' 카테고리의 다른 글

로그 log  (0) 2014.06.25
범프매핑 노말매핑 법선매핑  (0) 2014.06.10
셰이더 - 퍼 픽셀 라이팅 ( per pixel lighting )  (0) 2014.05.12
BSP 트리 ( bsp tree ) - 06  (0) 2014.04.21
BSP 트리 ( bsp tree ) - 05  (0) 2014.04.21
posted by BK dddDang
: