第44回
仕様設計からコーディングまで~タブ/スペース変換プログラムを作る(4)

main関数

今回は、入力ファイルの情報を保存する構造体を配列として扱います。そのため、main関数も大幅に書き換えることになります。

構造体を配列で扱う

main関数では、まず構造体STCONV型の配列“dat”と作業用のポインタpを宣言しています。

STCONV  dat[ARGMAX], *p;

配列の要素数は記号定数ARGMAXで示し、その値は8としています。コマンドライン・パラメータの上限数であって、入力ファイルの上限数ではありません。

コマンドラインでは“-T4”など変換方向とタブストップ幅も指定されるため、実際には入力ファイル数はARGMAX未満となります。従って、この配列には「使用されない余り」が出ることもあります。その場合はメモリの無駄遣いとなりますが、この程度なら許される範囲でしょう。

全体の処理手順

main関数では、以下の1~5の順に関数を呼び出していきます。1~5の説明とリスト4の()内の番号と照らし合わせて、動作を確認してください。
  1. コマンドライン・パラメータの数が足りなければ、putusage関数を呼び出して使い方を表示し、プログラムを終了する。
  2. forループ内でconvinit関数を呼び出し、構造体の配列を初期化する。
  3. chk_opt関数でコマンドラインを解析し、構造体の配列“dat”へオプションとファイル名へのポインタをセットする。
    chk_opt関数は有効な構造体の数を返すので、その値が0の場合は有効な入力ファイルがないとみなしてエラーメッセージを表示し、プログラムを終了する。
  4. forループでchk_opt関数の戻り値(有効な入力ファイルの数)だけsetdata関数を繰り返し呼び出す。
    setdata関数はタブストップ幅などの値を適正値にし、入力ファイルをオープンして、それぞれの値を構造体のメンバにセットする(前回の動作と同じ)。
  5. setdata関数はファイルが正しくオープンできなければFALSEを返すので、その場合は次の配列に移動する。ファイルが正しくオープンできればTRUEを返すので、その場合は実際に変換処理を行うstconv関数を呼び出す。
    stconv関数は、構造体のメンバswの値に基づいて「タブ→スペース」または「スペース→タブ」いずれかの変換処理を実行する。
リスト4:main関数
void    main(int argc, char *argv[])
{
  int     i, count;
  STCONV  dat[ARGMAX], *p;
           ↑構造体の配列を宣言
  if (argc < ARGMIN) {
    putusage(); -------- パラメータ不足なら使い方を表示 (1)
    exit(1);
  }
  p = dat;
  for (i = 0; i < ARGMAX; i++)
    convinit(p); ------- 構造体の初期化 (2)

  if ((count = chk_opt(p, argv)) == 0) { ---- 構造体の配列に値をセット (3)
    fprintf(stderr,"出力するファイルがありませんでした.¥n");
    exit(1);
  }
  for (i = 0; i < count; i++, p++) { ---- 構造体の配列を順次処理していく (4)
    if (setdata(p) == FALSE)
        continue;
    stconv(p); ------------------------ 変換処理を実行 (5)
    putchar(_FF); ---- プリンタ出力のためにページ送りする
  }
}