main関数
今回は、入力ファイルの情報を保存する構造体を配列として扱います。そのため、main関数も大幅に書き換えることになります。
構造体を配列で扱う
main関数では、まず構造体STCONV型の配列“dat”と作業用のポインタpを宣言しています。
STCONV dat[ARGMAX], *p;
配列の要素数は記号定数ARGMAXで示し、その値は8としています。コマンドライン・パラメータの上限数であって、入力ファイルの上限数ではありません。
コマンドラインでは“-T4”など変換方向とタブストップ幅も指定されるため、実際には入力ファイル数はARGMAX未満となります。従って、この配列には「使用されない余り」が出ることもあります。その場合はメモリの無駄遣いとなりますが、この程度なら許される範囲でしょう。
全体の処理手順
main関数では、以下の1~5の順に関数を呼び出していきます。1~5の説明とリスト4の()内の番号と照らし合わせて、動作を確認してください。
- コマンドライン・パラメータの数が足りなければ、putusage関数を呼び出して使い方を表示し、プログラムを終了する。
- forループ内でconvinit関数を呼び出し、構造体の配列を初期化する。
- chk_opt関数でコマンドラインを解析し、構造体の配列“dat”へオプションとファイル名へのポインタをセットする。
chk_opt関数は有効な構造体の数を返すので、その値が0の場合は有効な入力ファイルがないとみなしてエラーメッセージを表示し、プログラムを終了する。
- forループでchk_opt関数の戻り値(有効な入力ファイルの数)だけsetdata関数を繰り返し呼び出す。
setdata関数はタブストップ幅などの値を適正値にし、入力ファイルをオープンして、それぞれの値を構造体のメンバにセットする(前回の動作と同じ)。
- 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); ---- プリンタ出力のためにページ送りする
}
}
|
|
|