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문 구조가 어느 편이 더 자연스러운지 논의하시오.
[끝]