第 11 回 - 文字列操作(2)

[6/3, 2006 H.Aman]
67x27(1669bytes)   67x27(1669bytes) 【課題 3】

例題 3

複数行の英文(1 行は改行も含めて 256 文字未満)を読み込み, その中で "software" という単語の登場回数を答えなさい.

コーディング例

     1	/*
     2	 * プログラミング演習 第 11 回
     3	 * [例題 3]
     4	 * (C) 2006 Hirohisa AMAN <aman@cs.ehime-u.ac.jp, aman@computer.org>
     5	 */
     6	#include <stdio.h>
     7	#include <string.h>
     8		
     9	int main(void){
    10	  char str[256];
    11	  char word[256];
    12	  char buf[2];
    13	  int i, count;
    14	
    15	  buf[1] = '\0';
    16	  strcpy(word, "");
    17	
    18	  count = 0;
    19	  while ( fgets(str, 256, stdin) != NULL ){
    20	    i = strlen(str); /* 改行文字を空白で上書き */
    21	    str[i-1] = ' ';
    22	    
    23	    for ( i = 0; i < strlen(str); i++ ){
    24	      if ( str[i] != ' ' ){ /* 空白文字でない場合 */
    25		buf[0] = str[i];    /* 部分文字列として格納していく */
    26		strcat(word, buf);
    27	      }
    28	      else{ /* 空白文字に遭遇した場合 */
    29		if ( strcmp(word,"software") == 0 ){ /* 比較 */
    30		  count++;
    31		}
    32		strcpy(word, "");
    33	      }
    34	    }
    35	  }
    36	
    37	  printf("software の登場回数 : %d 回\n", count);
    38	
    39	  return 0;
    40	}
     
※左端の数字は行番号であり,ソースコードには含まれない点に注意!

コンパイル & 実行例

     $ gcc example11_3.c [Enter]
     $ ./a.out [Enter]
     In software development, comprehensive software reviews and [Enter]
     testings are important activities to preserve high quality [Enter]
     and to control maintenance cost. [Enter]
     However it would be actually difficult to perform comprehensive [Enter]
     software reviews and testings because of a lot of components, [Enter]
     a lack of manpower and other realistic restrictions. [Enter]
     [Ctrl]+[d]

     software の登場回数 : 3 回
     

解説

基本的な考え方は,次の操作を繰り返すというものである:
  • 文字列を 1 行読み込んで,その中を単語に分解する.
  • 得られた単語が "software" に等しいかどうかチェックし, 等しかった回数をカウントしておく.

まず,1 行読み込む という操作は,これまでも何度も登場してきた fgets を使えばよい.
ただし,今回はこれを複数回(入力が終了するまで) 繰り返す必要があるので,while 文によるループにしている (19 〜 35 行目のループ):

     19	  while ( fgets(str, 256, stdin) != NULL ){
     ・
     ・
     ・
     35	  }
なお, 入力文字列をすべて読み終えると fgets の戻り値が NULL となるので,上のループによって全文字列の読込みが可能である.

while ループの中身は, ほとんどが 例題2 と同じである.
唯一の違いといえるのが,部分文字列を表示するのではなく, それが "software" という文字列であるのか をチェックしているところである.

2 つの文字列が等しいかどうかを確認するには 1 文字ずつ地道に照合することになる. しかし,そのような作業は定型的(ワンパターン)なものであり, 既に strcmp という関数でライブラリ化されている.
使い方はシンプルで
 strcmp(str1, str2); 
とすると,str1 と str2 を比較し, その比較結果が関数の戻り値として得られる. 戻り値は整数値になっていて,

  • 02 つは同じ文字列
  • 負数 : str1 と str2 を辞書に載せるとしたら str1 の方が先に登場する(辞書式順で str1 の方が小さい)
  • 正数 : (同様に辞書式順で) str2 の方が先に登場する
という仕組みになっている.
つまり,29 行目
     29		if ( strcmp(word,"software") == 0 ){
は,word が "software" という文字列であるかどうかをチェックしている.