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

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

例題 2

64 文字未満の文字列(途中に空白を含む.最後に改行を含む.)を読み込み, 空白を区切り文字として入力文字列を複数の部分文字列へ分解しなさい.
ただし,空白文字は部分文字列に含めないものとする.

コーディング例

     1	/*
     2	 * プログラミング演習 第 11 回
     3	 * [例題 2]
     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[64];
    11	  char word[64];
    12	  char buf[2];
    13	  int i;
    14	
    15	  /* 文字列を読み込み, 改行文字を空白に置き換えておく */
    16	  fgets(str, 64, stdin);
    17	  i = strlen(str);
    18	  str[i-1] = ' ';
    19	
    20	  /* 文字列 word を空文字列として用意 */
    21	  strcpy(word,"");
    22	
    23	  /* 長さ 1 の文字列を格納するための配列 buf を用意 */
    24	  buf[1] = '\0';
    25	
    26	  /* 読み込んだ文字列 str を 1 文字ずつ調べていく */
    27	  for ( i = 0; i < strlen(str); i++ ){
    28	    if ( str[i] != ' ' ){ /* 空白文字でない場合 */
    29	      buf[0] = str[i];
    30	      strcat(word, buf); /* word の後ろに buf を連結する */
    31	    }
    32	    else{ /* 空白文字に遭遇した場合 */
    33	      printf("[%s]\n", word);
    34	      strcpy(word, "");
    35	    }
    36	  }
    37	
    38	  return 0;
    39	}
     
※左端の数字は行番号であり,ソースコードには含まれない点に注意!

コンパイル & 実行例

     $ gcc example11_2.c [Enter]
     $ ./a.out [Enter]
     $ This is a test data[Enter]
     [This]
     [is]
     [a]
     [test]
     [data]
     

解説

基本的な考え方は,str の内容を順番に 1 文字ずつ調べ,それが
  • 空白文字以外ならば,部分文字列として word に追加していき,
  • 空白文字ならば,それまで作っていた word を出力して次に備える( word を空文字列にリセット)
というものである.

この考え方を上のプログラムコードに対応付けると,
str の内容を順番に 1 文字ずつ調べるというのが 27 〜 36 行目の

     27	  for ( i = 0; i < strlen(str); i++ ){
     ・
     ・
     ・
     36	  }
という for 文のループで str[i] を見ていくことに対応する.

そして,空白文字以外ならば,部分文字列として word に追加 というのが 28 〜 31 行目

     28	    if ( str[i] != ' ' ){ /* 空白文字でない場合 */
     29	      buf[0] = str[i];
     30	      strcat(word, buf); /* word の後ろに buf を連結する */
     31	    }
に対応する.
ここで,できることなら strcat(word, str[i]); とやりたいところであるが,残念ながらそれだとエラーになる.
なぜなら,str[i] は 1 文字であって文字列(文字配列)ではない. そこで,いったん長さ 1 の文字列に変換する. それが 29 行目の
     29	      buf[0] = str[i];
である. これに先だって,24 行目で
     24	  buf[1] = '\0';
としてあるので, buf は長さ 1 の文字列として成立する.
これを word に連結してやればよい(30 行目):
     30	      strcat(word, buf); /* word の後ろに buf を連結する */

一方,空白文字ならば,それまで作っていた word を出力して次に備える というのが 32 〜 35 行目

     32	    else{ /* 空白文字に遭遇した場合 */
     33	      printf("[%s]\n", word);
     34	      strcpy(word, "");
     35	    }
に対応する.
ここでは, 次の部分文字列の格納に備えるため, word に再び空文字列 "" をコピー(上書き) している.

なお,この例題では空白文字への遭遇が単語の区切りを意味するので, 改行文字については空白文字へ置き換えておくことで事足りる:

     16	  fgets(str, 64, stdin);
     17	  i = strlen(str);
     18	  str[i-1] = ' ';