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

演習1: 配列と文字列

例題1: 逆行列を求めるプログラム

#include <stdio.h>

#define N 100

int main(void)
{
  double a[N][N], b[N][N], tmp;
  int i, j, k, n;

  scanf("%d", &n);

  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      a[i][j] = 0.0;
      b[i][j] = 0.0;
    }
  }

  for (i = 0; i < n; i++) {
      b[i][i] = 1.0;
  }

  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      scanf("%lf", &a[i][j]);
    }
  }

  for (k = 0; k < n; k++) {
    tmp = a[k][k];
    for (i = 0; i < n; i++) {
      a[k][i] /= tmp;
      b[k][i] /= tmp;
    }
    for (i = 0; i < n; i++) {
      if (i != k) {
        tmp = a[i][k];
        for (j = 0; j < n; j++) {
          a[i][j] -= a[k][j] * tmp;
          b[i][j] -= b[k][j] * tmp;
        }
      }
    }
  }

  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      printf("%f ", b[i][j]);
    }
    printf("\n");
  }

  return 0;
}

例題2: 正の整数値を読み込んで桁数を表示するプログラム

#include <stdio.h>

int main(void)
{
  int n, tmp;
  int digit;

  scanf("%d", &n);

  tmp = n;
  digit = 0;

  do {
    tmp /= 10;
    digit++;
  } while (tmp > 0);

  printf("%d\n", digit);

  return 0;
}

例題3: 入力された文字列から全ての数字文字を削除して表示するプログラム

#include <stdio.h>

int main(void)
{
  char str1[100], str2[100];
  int i, j;

  scanf("%s", str1);

  i = 0;
  j = 0;
  while (str1[i] != '\0') {
    if (str1[i] < '0' || str1[i] > '9') {
      str2[j] = str1[i];
      j++;
    }
    i++;
  }
  str2[j] = '\0';

  printf("%s\n", str2);

  return 0;
}

課題1

行列の積を求めるプログラムを作成しなさい. そのプログラムは,正方行列2つを標準入力から読み,それらの積の行列を標準出力に出力するものとする. 入力の書式は以下の通りである.
  • 入力には,まず1つ目の行列の情報が,次に2つ目の行列の情報が書かれている.
  • 行列の情報の最初の行には,行列のサイズn (n ≤ 100) を表す整数が書かれている.
  • 入力の1行が行列の1行に対応し,行列の要素と要素は1個以上の空白で区切られている.
  • 各行の最初の要素の前および最後の要素の後に1個以上の空白が入っていることがある.
  • 行列の要素は全て実数(浮動小数)である.
行列の出力においては,入力と同様の行列の書式を用いるものとする. そのプログラムは例えばこの入力を与えると,この出力を出力し, この入力を与えると,この出力を出力する. この入力ファイルを用いた計算結果をレポートに記載しなさい. 余裕があれば,他の入力ファイルを用いた場合についても記載しなさい. 小数点以下の部分の表示は適当な桁数,たとえば最大6桁までで打ち切りなさい(printf で桁数を指定しなければそうなる). 縦に並ぶ複数の行列要素は桁を揃えて表示してもよいし,揃えずに表示してもよい(行内の要素と要素の間の空白の個数は1個でも複数個でもよい).

課題2

例題3のプログラムを参考に,正の整数を読み込んで,その数を逆順に表示するプログラムを作成しなさい. 例えば12345を入力すると54321と表示される.読み込んだ整数の最下位の桁に0が並んでいる場合には,逆順に表示される数の先頭に0が並んでいてもよい.

読み込む整数は1000000以下であると仮定してよい(2019年10月18日14:50追記).

課題3

例題2のプログラムを参考にして,標準入力から1行読んでそれを文字列 str1 とし,さらに1行読んでそれを文字列 str2 とし,str2 に含まれる文字のみを str1 から 抽出して表示するプログラムを作成しなさい. 例えば,str1 が "tsukubadai" で str2 が "mountain" ならば,"tuuaai" と表示される. str1 を "college-of-information-science!!" として,str2 を "coins!" とした場合の結果をレポートに記載すること. 読む文字列は NUL 文字も含めて100文字以下であると仮定してよい.

読む文字列の中には空白や,改行以外の制御文字は含まれないと仮定してよい(2019年10月18日14:50追記).

課題4

発展課題: 単位取得のためには提出は必須ではないが,提出すれば加点する.
ライフゲームの盤面を計算するプログラムを作成しなさい. そのプログラムは,盤面の縦の長さ,横の長さ,初期盤面(1世代目の盤面),整数N(N > 1)を受け取り,1世代目からN世代目の盤面を順に出力する. 入力の書式は以下の通りである.
  • 最初の行には盤面の縦の長さが書かれており,次の行には盤面の横の長さが書かれている.縦の長さも横の長さも100以下である.
  • 以降の行には初期盤面の情報が以下の書式で書かれている.
    • 入力の1行が盤面の1行に対応する.
    • 生きているセルはO(英大文字のオー)で表されており,死んでいるセルは.(ピリオド)で表されている.
    • 入力中のセルを表す文字間は1個以上の空白で区切られている.
    • 各行の最初のセルの前および最後のセルの後に1個以上の空白が入っていることがある.
  • その次の行にはNが書かれている.
出力の書式は以下の通りである.
  • G世代目の盤面を出力する前に,Gth generationという行を出力する.Gの部分は世代を表す整数で置き換える.
  • 以降の行にはG世代目の盤面の情報を入力の盤面とほぼ同じ書式で出力するが,出力を見やすくするために,空白文字は出力しない.
  • 出力を見やすくするために,各盤面の下に1行の空行を入れる.
初期盤面には生きているセルが1つ以上あることを仮定してよい. 盤面の外には死んでいるセルが常に並んでいるとみなす. そのプログラムは例えば この入力を与えると,この出力を出力し, この入力を与えると,この出力を出力する. この入力ファイルを用いた計算結果をレポートに記載しなさい. 余裕があれば,他の入力ファイルを用いた場合についても記載しなさい. Nが10以上の場合には,計算結果が大きくなるので,最初と最後の世代だけをレポートに記載しなさい.