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

タブ←→スペース両方向変換に改造

今回は、タブ←→スペースの両方向変換を実現します。プログラムの仕様を把握しておきましょう。

ファイルごとに変換方向とタブ幅を指定

前回は、複数の入力ファイルを指定し一括して「タブ→スペース」に変換できるように改良しました。今回は、「スペース→タブ」への変換を可能にし、さらに各ファイルごとに
「タブ→スペース」か「スペース→タブ」かを指定できる
ようにしてみます。また
タブストップ幅もファイルごとに指定できる
機能も追加してみます。

構造体の配列を使う

入力ファイルの情報は構造体で管理しました。前回のプログラムでは、入力ファイルの数が不定なので構造体のポインタを使ったリンク構造で対処しました。

しかし、1つのプログラムで何十個ものファイルを指定することは稀(まれ)です。多くても10個程度なので、ここでは構造体の配列を使ってみます。コマンドラインから入力ファイルを見つけ、その都度構造体のメモリを確保するより、最初に配列のメモリを確保しておいた方が幾分か処理が早くなるでしょう(ほんのわずかではありますが)。

コマンドラインの書式

これまでは“tb2sp”というプログラム名でしたが、今回作成するプログラムは「タブ←→スペース」どちらの方向にも変換できるので“tabconv”という名前にしておきます。なお、サンプルのソースファイルは“ex4401.c”という名前です。

このプログラムの書式は以下のようになります。
tabconv <-Sn | -Tn> <ファイル名> <ファイル名> ... <-Sn | -Tn> <ファイル名>...

<-Sn | -Tn>は変換方法を指定するオプションスイッチで、-S(または-s)ならタブをスペースに、-T(または-t)ならスペースをタブに変換します。nはタブストップ幅です。

<-Sn | -Tn>に続けてファイル名を指定します。<-Sn | -Tn>なしにファイル名を指定した場合は、直前に指定していた変換方法とタブストップ幅が受け継がれます。

たとえば、
abc.cとdef.cをタブストップ幅「4」でタブからスペースに
xyz.hをタブストップ幅「8」でスペースからタブに
変換するなら、以下のようなコマンドラインになります。
tabconv -S4 abc.c def.c -T8 xyz.h

関数の追加

今回作るプログラムでは、これまで対応していなかった「スペース→タブ」の変換処理が必要になります。

「タブ→スペース」の変換処理は、これまでと同じ“tb2sp”関数で対応できるので、「スペース→タブ」の変換のために“sp2tb”関数を作ることにします。そして、コマンドラインから“-S”または“-T”の文字列を見つけると、それに応じて“tb2sp”か“sp2tb”のどちらかの関数を呼び出す――ということになります。

そのため、コマンドラインの解析処理にも工夫を凝らさなければなりません。タブストップ幅やファイル名など1件のファイルの処理方法をまとめる構造体にも手を加える必要が生じます。

これらを総合して作り替えたプログラムのソースを、前回と同じく
記号定数の定義
main関数
そこから呼び出される各関数
の順に紹介していきましょう。