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

条件判断と分岐を書き換える

オプション・スイッチを調べる処理でifを使いましたが、1つの文字を順に調べていく場合にはswitch caseの方が合理的です。リスト1を書き換えてみましょう。

switch caseで書き換える

リスト1では、forループの中でpがパラメータ文字列の先頭アドレスを受け取って、その先頭が'-'であった場合、続く1文字をifで調べていきました。調べる対象が同じなら、switch caseの方が効率的であることは既に説明したとおりです。

そこで、forループの中の最初のif文で先頭文字が'-'であった場合、続く1文字がc、n、f、wのいずれかなら対応する処理を実行する部分をswitch caseを使って書き換えたのがリスト2です。

処理結果はまったく変わりませんが、どの変数を何と比べてどのように処理するのか──という処理構造は、こちらの方が分かりやすくなります。

リスト2:リスト1と同じ処理をswitch case文で書き直した(ex2902.c, ex2902.exe)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define bool int        /* 論理型を定義 */
#define _FALSE 0        /* 偽 */
#define _TRUE  !_FALSE  /* 真 */

int main(int argc, char * argv[])
{
  int i;                   /* ループカウンタ */
  char *p;                 /* 各パラメータ(argv[])の受け皿 */

  /* 各パラメータを保持する変数 */
  char *filename;
  char *word;
  bool sw_capt = _FALSE;
  int maxnum = 0;

  for (i=1; i<argc; i++) {
    p = argv[i];

    if (p[0] == '-') {
      p++;
      /* '-'記号の次の1文字で分岐 */
      switch (p[0]) {
        case 'c' : {
          sw_capt = _TRUE;
        }
        case 'n' : {
          maxnum = atoi(++p);
        }
        case 'f' : {
          filename = ++p;
        }
        case 'w' : {
          word = ++p;
        }
        default : {
          /* 先頭が'-'でなければ何もしない */
        }
      }
    }
  }
  /* パラメータの示す内容を表示 */
  printf("Caps : %s, MaxNumber : %d, File name : %s, Word : %s\n", 
          sw_capt ? "TRUE" : "FALSE", maxnum, filename, word);
}

forの代わりにwhileも使える

main関数の第1引数argcがパラメータの数を保持しているため、リスト1もリスト2も繰り返し処理には以下のようにforループを使っています。
for (i=1; i<argc; i++) {

配列argvの最後はNULLポインタとなっているため、whileループで『argv[ ]がNULLでない間』という条件を指定しても同じことになります。
i = 1;
while (p = argv[i++]) {
    :
}