2011년6월16일_문장을 어휘단위로 분해하기(문자열을 token단위로 잘라내기)

 

 

 

image

상기의 그림과 같이 포인터변수 Text에 “This is a ATmega”라는 문자열이 저장되어 있다.
이 문자열을 어휘(이하 token)단위로 구분하는데 공백문자를 사용한다. (↔ 공백문자가 없다면 하나의 단어가 될 것이다.)

   1:   const char *Text = "This is a ATmega";
   2:   const char *p;
   3:   char T[4][7];
   4:   
   5:  // Code
   6:  printf("T[0] = [%s]\n", T[0]);

 

문자열을 담을 포인터변수 Text와,
그 문자열을 가리킬 포인터변수 p와,
잘라낸 token을 담을 2차원 배열 T를 선언하고,

하기와 같이 문자열을 잘라내는 처리를 하는 함수를 사용하여 2차원 배열에 저장하고 출력할 것.

 

image

 

<소스코드>

   1:  // 문자열에서 token단위로 잘라 배열에 저장.
   2:   
   3:  #include <stdio.h>
   4:   
   5:  int main()
   6:  {
   7:      const char *Text = "This is a ATmega";
   8:      const char *p;
   9:      char T[4][7];
  10:      
  11:      // Code
  12:      p = Text;                    //문자열이 저장된 *Text의 시작주소를 가리킴.
  13:   
  14:      strncpy(T[0], p, 4);        //T배열의 1행으로 "This" 복사(Text를 참조)
  15:      T[0][4] = 0;                //T배열의 1행 5열에 NULL문자 넣기.
  16:   
  17:      p = p + 5;                    //*Text의 6행을 가리킴.
  18:   
  19:      strncpy(T[1], p, 2);        //T배열의 2행으로 "is" 복사(Text를 참조)
  20:      T[1][2] = 0;                //T배열의 2행 3열에 NULL문자 넣기.
  21:   
  22:      p = p + 3;                    //*Text의 9행을 가리킴.
  23:      
  24:      strncpy(T[2], p, 1);        //T배열의 3행으로 'a' 복사(Text를 참조)
  25:      T[2][1] = 0;                //T배열의 3행 2열에 NULL문자 넣기.
  26:   
  27:      p = p + 2;                    //*Text의 11행을 가리킴.
  28:      
  29:      strncpy(T[3], p, 6);        //T배열의 4행으로 "ATmega"복사(Text를 참조)
  30:      T[3][6] = 0;                //T배열의 4행 7열에 NULL문자 넣기.
  31:      
  32:   
  33:      printf("T[0] = [%s]\n", T[0]);        //"This" 출력
  34:      printf("T[1] = [%s]\n", T[1]);        //"is" 출력
  35:      printf("T[2] = [%s]\n", T[2]);        //"a" 출력
  36:      printf("T[3] = [%s]\n", T[3]);        //"ATmega128" 출력
  37:      
  38:      
  39:      return 0;
  40:  }

<실행결과>

image

 

 

<다른 해법>

① 문자열을 담은 포인터변수 Text을 검사하여 공백문자를 NULL문자로 대치한 다음에,
    그 문자열을 가리키는 포인터변수 p을 %s형식지정자로 출력하면 첫 token이 출력될 것이다. 다음에,
    p에 5를 더하여 다시 p를 %s형식지정자로 출력하면 두 번째 token이 출력될 것이다.
    이렇게 반복하면 될 듯 한데…
    p에 더 할 값을 찾는 법은,
    문자열을 탐색하여 NULL문자가 나오면 그 다음 주소를 가리키도록 p값을 조정하면 되지 않을까?
    마지막 NULL문자가 나오면 처리를 달리 해야 함. (미리 조사할 때 마지막NULL문자까지 몇 개의 token이 있나 확인해야 할 것.)

② 문자열을 공백문자를 경계로 잘라내는 함수를 만들고, 그 함수의 내용은,
    잘라낼 문자열의 시작주소와 저장될 문자열의 시작주소와 token의 순번을 인자로 받아,
    순번이 0이면 첫 문자열,
    순번이 1이면 두 번째 문자열,
    순번이 2이면 세 번째 문자열,
    순번이 3이면 네 번째 문자열을 잘라내 저장될 문자열에 복사하고 마지막에 NULL문자도 추가한다.

1번의 장점은 따로 token을 담을 배열을 선언하지 않아도 된다는 것이고,
       단점은 원본이 훼손된다는 것이다.
2번의 장점은 원본이 훼손되지 않는 다는 것이고,
       단점은 사본을 담을 배열을 선언해야 되는데 만약 문자열을 입력 받는다면 크기를 알 수 없다.