C프로그래밍(K&R, Ch1, Word Counting)

Copyright (c) 2015-, All Rights Reserved by Kwanghoon Choi
(아래 강의 노트를 자유롭게 이용하되 다른 웹 사이트 등을 통한 배포를 금합니다.)

The C Programming Language 2nd Ed. by Kerninghan & Ritchie ( Ch.1, Word Counting )

입력 받은 단어의 수를 세는 프로그램을 작성해보자. 단어는 공백(' ', '\t', '\n')으로 구분된 알파벳, 기호, 숫자들이다.

"Yonsei University, Wonju Campus"를 입력하면 단어는 총 4개 "Yonsei", "University,", "Wonju", "Campus"다.

프로그램의 기본 구조는 입력이 끝날 때까지 반복해서 단어를 세는 것이다.

int c;
int nw; 

nw = 0;
c = getchar();
while ( c != EOF ) {
   // 단어 세기
   c = getchar();
} 

printf("# of words : %d \n", nw);

"Hello World" 입력을 받았다고 가정하자. 처음에 아직 문자를 받지 않았을 때 상태를 OUT이라고 하자. 이 상태에서 첫번째 문자 'H' (공백이 아닌 문자)를 입력 받으면 단어가 시작되므로 OUT가 다른 상태 IN이라고 하자.

OUT == c ==> IN     (c가 공백이 아니면)

IN 상태에서 공백이 아닌 문자들('e', 'l', 'l', 'o')를 입력 받는 동안에는 IN 상태로 남는다.

IN == c ==> IN     (c가 공백이 아니면)

그러다 'o' 다음에 공백(' ', '\t', '\n')을 입력 받으면 IN 상태는 OUT 상태로 바뀐다.

IN == ' ' ==> OUT
IN == '\t' ==> OUT
IN == '\n' ==> OUT

여기까지 논의한 바에 의하면 IN 상태에서 입력 받을 수 있는 모든 경우 (공백이거나 공백이 아닌 문자들)에 대해 고려했다. OUT 상태에서 입력 받을 수 있는 경우 중에 공백이 아닌 경우만 생각해보았으므로  공백인 경우도 생각해보자. 단어 바깥에 있는 OUT 상태에서 공백을 입력 받으면 여전히 단어 안으로 들어가지 못하고 바깥 상태에 있어야 한다.

OUT == ' ' ==> OUT
OUT == '\t' ==> OUT
OUT == '\n' ==> OUT

이렇게 모든 경우의 수를 고려해서 정리해보았다. 이제 정리된 것을 C코드로 옮겨보자.

#define IN  1
#define OUT 2

int c;
int nw; 
int state;

state = OUT;
nw = 0;
c = getchar();
while ( c != EOF ) {
   if ( state == OUT ) {
       if ( c != ' ' && c != '\t' && c != '\n' ) {
          state = IN;
       }
       else { // c == ' ' || c == '\t' || c == '\n'
          state = OUT; // 불필요한 코드
       }
   }
   else { // state == IN
       if ( c != ' ' && c != '\t' && c != '\n' ) {
          state = IN; // 불필요한 코드
       }
       else { // c == ' ' || c == '\t' || c == '\n'
          state = OUT;
       }
   }
   c = getchar();
} 

printf("# of words : %d \n", nw);

처음 프로그램을 시작하면 단어 바깥에 있고 (state == OUT) 앞에서 논의한 상태 변화에 따라 C코드를 작성했다. 아직 단어의 수 nw를  변경하지 않았다.

단어가 시작할 때마다 nw를 1 증가시키면 단어의 수가 된다. 이 점을 고려하고, 또한 위의 프로그램에서 불필요한 코드를 삭제하면 아래와 같은 단어 세는 프로그램이 된다.

#define IN 1
#define OUT 2

int c;
int nw;
int state;

state = OUT;
nw = 0;
c = getchar();
while ( c != EOF ) {
   if ( state == OUT ) {
      if ( c != ' ' && c != '\t' && c != '\n' ) {
         state = IN;
         nw = nw + 1;
      }
   }
   else { // state == IN
      if ( c == ' ' || c == '\t' || c == '\n' ) {
         state = OUT;
      }
   }
   c = getchar();
}

printf("# of words : %d \n", nw);

단어 안에 들어갔다가 밖으로 빠져나올때 nw를 1 증가시키는 방법도 생각해볼 수 있다. 다만 입력의 끝(EOF)에 도달하는 경우에 만일 현재 상태가 단어 안의 상태 (IN)라면 추가로 nw를 1 증가시켜야 한다.

[연습문제] K&R 책의 1.5.4절의 단어 세기 프로그램과 위의 프로그램을 비교하시오. 특히 while문 안의 if문 구조가 약간 차이가 있음을 확인하고, 그럼에도 불구하고 두 프로그램들이 동일함을 확인하시오. 또한 문제 풀이 관점에서 if문 구조가 어느 편이 더 자연스러운지 논의하시오.

[끝]

Leave a Reply

Your email address will not be published. Required fields are marked *