システムプログラミング序論 演習

演習2: コマンドライン引数とファイル入出力

例題1: ファイル中の行数をカウントするプログラム

#include <stdio.h>

int main(int argc, char *argv[])
{
  int ch, count;
  FILE *fp;

  /* コマンドライン引数が1つ指定されているかどうか確認する */
  if (argc != 2) {
    fprintf(stderr, "Missing file argument\n");
    return 1;
  }

  if ((fp = fopen(argv[1], "r")) == NULL) { /* ファイルのオープン */
    fprintf(stderr, "Can't open %s\n", argv[1]);
    return 1;
  }

  count = 0;
  while ((ch = fgetc(fp)) != EOF) { /* 1文字ずつ読み込む */
    if (ch == '\n') { /* 読んだ文字は改行か? */
      count++;
    }
  }

  printf("%d lines\n", count);
  fclose(fp); /* ファイルのクローズ */

  return 0;
}

例題2: ファイルをコピーするプログラム

#include <stdio.h>

int main(int argc, char *argv[])
{
  int ch;
  FILE *sfp, *dfp;

  /* コマンドライン引数が2つ指定されているかどうか確認する */
  if (argc != 3) {
    fprintf(stderr, "Missing file argument\n");
    return 1;
  }

  if ((sfp = fopen(argv[1], "r")) == NULL) { /* コピー元ファイルのオープン */
    fprintf(stderr, "Can't open %s\n", argv[1]);
    return 1;
  }

  if ((dfp = fopen(argv[2], "w")) == NULL) { /* コピー先ファイルのオープン */
    fprintf(stderr, "Can't open %s\n", argv[2]);
    fclose(sfp); /* コピー元ファイルのクローズ */
    return 1;
  }

  while ((ch = fgetc(sfp)) != EOF) {
    fputc(ch, dfp); /* コピー先ファイルにコピー元ファイルの内容を書き込む */
  }

  fclose(dfp); /* コピー先ファイルのクローズ */
  fclose(sfp); /* コピー元ファイルのクローズ */

  return 0;
}

課題1

例題1のプログラムを参考に,コマンドライン引数として1つのファイル名を受け取り,そのファイル中の文字の個数をカウントして表示するプログラム(UNIX の wc コマンドに似たプログラム)を作成しなさい. 空白や改行も1文字とカウントすること.

そのファイルはワイド文字やマルチバイト文字を含まないことを仮定してよい.今後の課題でも同様.

課題2

コマンドライン引数として第1引数に整数 N,第2引数にファイル名を受け取り,そのファイルの最初の N 行のみを標準出力に出力するプログラム(UNIX の head コマンドに似たプログラム)を作成しなさい.N として与えられる数はそのファイルの行数以下であることを仮定してよい.そのファイルのどの行の長さも255文字以下であると仮定してよい.
ヒント: 例題1のように1文字ずつ読むプログラムにすることもできるし,fgets 関数を使って1行ずつ読むプログラムにすることもできる.

課題3

例題2のプログラムを参考に,コマンドライン引数として第1引数にコピー元ファイル名,第2引数にコピー先ファイル名を受け取り,すべての英小文字を英大文字に変換しながらファイルの内容をコピーするプログラムを作成しなさい.

課題4

例題2のプログラムを参考に,ファイルの内容を1行1行読み込み,各行を暗号化したデータを標準出力に出力するプログラムを作りなさい. このプログラムはコマンドラインの第1引数にファイル名,第2引数に整数Nを受け取る. 暗号化は,ファイル内の各アルファベット文字を,N文字後のアルファベット文字で置き換えることによって実現するものとする. Zの次の文字はAとする. アルファベット以外の文字は置き換えない.Nを13としたときの暗号化方式は,ROT13という名前で広く知られている. このプログラムの実行例を以下に示す.

$ cat univ.txt
University of Tsukuba, 1, 2, 3!
College of Information Science \(^o^)/
$ ./ex2_4 univ.txt 2 > cipher.txt
$ cat cipher.txt
Wpkxgtukva qh Vuwmwdc, 1, 2, 3!
Eqnngig qh Kphqtocvkqp Uekgpeg \(^q^)/
$ ./ex2_4 cipher.txt 24
University of Tsukuba, 1, 2, 3!
College of Information Science \(^o^)/
できたプログラムがこのファイルに対して正しく動作することを確認しなさい.具体的には,まず第二引数に13を与えて暗号化データを作り,それを端末に表示させたり,ファイルに保存したりしなさい.次に,その暗号化データが入ったファイルを,再び第二引数に13を与えて暗号化し,元のファイルの内容が表示されることを確認しなさい.レポートに書く実行例には暗号化データ全体を含めるようにしなさい.

補足: Nとしては1以上25以下の整数が与えられると仮定してよい.(2019年10月21日14:35追記)