C言語勉強中 - detab関数

会社の人からC言語の本を借りました。

プログラミング言語C 第2版 ANSI規格準拠

プログラミング言語C 第2版 ANSI規格準拠

第一章まで読んだので章の終わりにあった練習問題をやってみよう。

問題

P42 演習1-20

入力されたタブを、次のタブ・ストップまでのスペースをうめる適当な数のブランク(空白)で置き換えるプログラムdetabを書け。タブ・ストップの位置は、例えばn文字というように固定して考えよ。nは変数にすべきか、記号パラメータにすべきか?

やってみた

難しそうなので、とりあえずタブは4文字と固定して考えよう。
えーっと、、タブの幅っていうのは、行の先頭から何文字目にタブ文字が登場したかで決まりそうな気がする。
タブ幅を4文字に設定した秀丸でやってみた。


表にするとこんな感じだ

タブ文字の位置 長さ
0 4
1 3
2 2
3 1
4 4
5 3
6 2
7 1
8 4

関数にできた

長さ = 4 - ( タブ文字の位置 % 4 )

( タブ文字の位置 % 4 )っていうのは「タブ文字の位置を4で割った余り」っていう意味ね。

関数にできたので関数を作ってみよう

int tab_width( int pos ) {
  return 4 - ( pos % 4 )
}

できた。


この関数が戻した数だけ半角スペースを出力してやればいいわけだ。
これも関数にしよう。

int print_tab( int pos ) {
  int i = 0;
  int width = tab_width( pos );
  
  for( i=0; i<width; i++ ) {
    putchar( ' ' );
  }
  return width;
}

できた。


これらを使ってプログラムを書けばいいわけだ。

/* detab.c */
#include <stdio.h>

int print_tab( int pos );
int tab_width( int pos );


int main() {
  int pos = 0;
  int width = 0;
  char c = '\0';

  while( ( c = getchar() ) != EOF ) {
    if( c == '\t' ) {
      width = print_tab( pos );
      pos += width;
      continue;
    }

    if( c == '\n' ) {
      pos = 0;
    } else {
      pos++;
    }
    putchar( c );
  }

  return 0;
}



int print_tab( int pos ) {
  int i = 0;
  int width = tab_width( pos );

  for( i=0; i<width; i++ ) {
    putchar( ' ' );
  }
  return width;
}



int tab_width( int pos ) {
  return 4 - ( pos % 4 );
}

できた。

感想

なんだか無理やりな感じがする。そもそも問題にある「detab関数」も作ってないし。
うーん。
・・・
明日またがんばろう。