第29回
データ構造(8)~コマンドライン・パラメータの切り出し

コマンドラインの分解処理を考える

ユーザーがコマンドラインに入力したパラメータを受け取ってそれを分解し、処理の中で利用する方法を紹介してきました。では、OSから渡されたコマンドライン・パラメータは、どのようにしてmain関数の引数であるchar型ポインタの配列argvに格納されるのか、考えてみましょう。

スペース区切りの文字列を分解する

コマンドラインを分解して配列に収める処理は、プログラマーが書いたmain関数から始まるソースをコンパイルしたオブジェクトファイルにリンクされる、Cのスタートアップ・ルーチンで行われます。具体的なメカニズムを説明すると複雑になるので、ここでは
複数の単語がスペースで区切られた文字列を分解し
各単語をchar型の二次元配列に格納する
という処理を紹介しておきます。

例えば"hello C Programming world!"という4つの単語がスペースで区切られた文字列を、char型の二次元配列(=ポインタの配列)*str[ ]に順次格納して、以下のような結果を得る──という形です。
str[0] : "hello"
str[1] : "C"
str[2] : "Programming"
str[3] : "world!"

切り出した単語を配列に収める

上述のような処理を実現するためには、以下のような手順が必要となります。

(1)文字列の先頭から1文字ずつ読み取る
(2)受け側のchar型配列に1文字ずつコピーする
(3)空白(スペース)が現れたら処理を終える
(4)受け側の終端にNULL(\0)を配置する

これで、1つの単語が格納されます。この処理を、スペースで区切られた単語の数だけ繰り返さなければなりません。

リスト3は、ユーザーの入力した文字列を要素数4行×256バイトの二次元配列に格納し、その結果を表示するプログラムです。簡略化するため、単語は4個までしか対応していません。

実行結果は以下のようになります。

C:\CLANG>exe\ex2903
input : hello C Programming world! -------- ユーザーの入力
buf = hello C Programming world! ---------- 入力内容を表示
str[0] : hello
str[1] : C
str[2] : Programming
str[3] : world!

リスト3:入力された文字列から単語を切り出して二次元配列に格納するプログラム(ex2903.c, ex2903.exe)
#include <stdio.h>
# define _SPACE 0x20

int main(void)
{

int i;
char buf[1024 + 1];
char str[4][256 + 1];
char *s, *d;

  /* 文字列(スペース区切り)を入力 */
  printf("input : ");
  (void)gets(buf);
  /* 入力内容を表示 */
  printf("buf = %s\n", buf);

  s = buf;    /* 送り側のポインタをセット */
  for (i=0; i<4; i++) {  /* 配列の数だけ繰り返す */
    d = str[i];          /* 受け側のポインタをセット */
    while ((*d++ = *s++) != _SPACE) {
      /* スペースが出るまでコピー */
    }
    *d = '\0';    /* 終端のNULLをセット */
  }

  /* 配列の内容を表示 */
  for (i=0; i<4; i++) {
    printf("str[%d] : %s\n", i, str[i]);
  }
}

forループとwhileループの二重構造

外側のforループで一次元目(0~3)を順次処理し、内側のwhileループで各単語を切り出しています。whileループではポインタを使い、strcpy関数と同じような文字列のコピー処理を条件文の中で1行で記述しています。

s = buf;               /* 送り側のポインタをセット */
for (i=0; i<4; i++) {  /* 配列の数だけ繰り返す */
  d = str[i];          /* 受け側のポインタをセット */
  while ((*d++ = *s++) != _SPACE) {
   /* スペースが出るまでコピー */
  }
  *d = '\0';    /* 終端のNULLをセット */
}

あとがき

hiropから新年のご挨拶♪

本年もご愛読、よろしくお願いいたしますm(_ _)m

ということで、お年賀を用意しました♪

↓以下のURL↓にアクセスしてください。

●Flash Playerプラグインをお持ちの方
http://www.eonet.ne.jp/~hirop/nenga/09nenga.html

●Flash Playerをお持ちでない方
(または、新年早々アニメーションなんて観たくないよ~という方)
http://www.eonet.ne.jp/~hirop/nenga/09nenga_s.html