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

タブによる字下げの問題点

Cなどのソースでは、字下げにタブを用いるのが一般的です。タブキーを押したときにカーソルが移動する位置をタブストップといい、その幅は一般的に半角8桁です。すると、長いソースでは後端が次行にはみ出す場合があります。

字下げが深いとソースが汚れる

コンソールモードでテキストエディタを使ってソースを書き、コマンドラインでコンパイルする場合、エディタで設定している『タブストップの幅』が気になります。

『タブストップの幅』は標準では半角8桁に設定されており、エディタの1行は通常80桁となっています。すると、5段階目の字下げではソースの先頭が画面の半分の位置(41桁目)から始まることになり、ソースが40文字を超えると行末に達して、画面上では折り返し表示されてしまいます。

Cは簡潔なソースコードを記述できるため、他の言語に比べて1行は短くなりますが、if、for、while、switchなどの制御構造をネスト(入れ子)にすると、字下げによってソースの先頭(書き出し位置)がどんどん右に寄っていきます。

そのため、ネストのレベルが深くなると、図1のような見た目の汚いソースになってしまうことがあります。


タブの代わりに半角2桁のスペース

上述のような事態を避けるため、エディタのタブストップ幅を4桁に設定する人も多いようです。ちなみにVisual Studioのソースエディタでは、標準でタブストップ幅が4桁に設定されています。

僕もエディタのタブストップ幅を4桁に設定していますが、前々回お話ししたように、今ではインデントにタブではなく2桁のスペースを使っています。なぜ4桁ではなく2桁のスペースなのかと言えば、スペースキーを4回打鍵するのが手間であるということと、Cの予約語や標準関数名などが簡潔で短いため、2桁分程度のインデントでも充分に構造が把握できるからです。

ならば、「タブストップ幅を2桁にしてもいいんじゃないの?」と思う人もいるでしょう。もちろんそれでも構わないのですが、これも前々回お話ししたように、雑誌や書籍の原稿としてソースコードを添付する場合に、タブストップ幅が編集部のエディタと異なっていると各行の書き出し位置がずれてしまい、意図した形にならない――という懸念があるためです。

印刷でインデントがズレる

それともうひとつ、僕がソースにタブコードを使わない理由があります。それは、「ソースコードをプリンタで印刷したときのズレ」です。

今ではソースを画面で確認し、プリントアウトすることはほとんどありません。しかし、1画面が80桁×25行のCUIが全盛だった時代には、行数の多い関数全体を画面上で眺めるために上下のスクロールを多用しなければならず、非常に面倒でした。

そのため、当時はひととおり完成したソースはプリントアウトして紙で確認するのが普通だったのです。プリンタはドットインパクト式 ※1 で、ソースは連続紙 ※2 に打ち出しました。

エディタの印刷機能を使えばタブストップ幅を変更できることもありましたが、当時はテキストファイルをリダイレクトでプリンタに送って印刷するのが普通でした。複数のソースファイルをエディタで開くより、catコマンド ※3 でコマンドラインからソースファイルを連続してプリンタに送った方が手っ取り早かったのです。

cat stconv.h stconv.c fileio.h fileio.c > prn

プリンタのタブストップ幅は8桁なので、先に述べたようにエディタ上で4桁となっていたインデントが紙の上では8桁となり、書き出し位置がずれてしまいます。

多数の小さなピンでインクを染み込ませたインクリボンを叩き、紙の上に文字を印字する仕組み。今でも、宅配便の宛名ラベルなど複写式伝票の印字に使われている。印字時に「キーッ」というヒステリックな音がする
切り取り線でつづら折りにたたまれた印刷用紙。両端に等間隔の穴が開けられ、それをプリンタの爪で引っかけて行送りする
複数のファイルを連結して、その内容を標準出力に送るコマンド。MS-DOSではTYPEコマンドで同じことができる

タブをスペースに変換する

そこで、テキストファイル(主にCのソースファイル)を読み込んで、タブコードを4桁のスペースに置き換えるプログラムを作りました。それが、前回コメントのサンプルとして紹介したstconv.cです。

今ではこういった処理はあまり必要とされないかもしれません。が、数の定まらない複数のコマンドラインオプションの処理やタブとスペースの変換処理など、1つのプログラムを実現するための考え方が参考になると思いますので、数回に分けてstconv.cの仕組みを紹介しようと思います。構造体、構造体の配列、ポインタの扱いなども参考になるでしょう。