yossii@penguin:~/C$  ./magics
魔法陣の次数は?:

実は私,この表示が嫌いなのです…というよりも,scanf( ) で入力を求めること自体が美しくないと感じられてしまうのです
実際に世の中で使われるアプリケーションに,このような表示がなされることは殆どありません
特に windows のアプリケーションならば,textbox などに入力をするのが当たり前になっています

まぁ,それを言ってしまうと,コマンドラインからの入力そのものが今やなかろう,となって墓穴を掘るのですが f^^;
何はともあれ,魔法陣の次数を「magics 5」のように,コマンドの引数としてしまうことにします

と思ってはみたものの・・・どすんだっけ? 状態です

手持ちの本などを調べました

コマンドに引数を渡す

int main(int argc, char *argv[ ]) {
   ・
   ・
   ・
}

argc に引数の個数が渡され,argv[ ] に引数の内容が文字列として渡されます

ホウホウ,簡単なものでした
前回のプログラムを,下のように変えるだけです

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
  int dim = atoi(argv[1]);
  int a[99][99];
  int i = dim - 1;
  int j = (dim - 1) / 2;
  for (int num = 1; num <= dim * dim; num++) {
    a[i][j] = num;
    if (a[(i + 1) % dim][(j + 1) % dim] == 0) {
      i = (i + 1) % dim;
      j = (j + 1) % dim;
    } else {
      i = i - 1;
    }
  for (int i = 0; i <= dim - 1; i++) {
    for (int j = 0; j <= dim - 1; j++) {
      printf("%3d ", a[i][j]);
    }
    printf("\n");
  }
  return 0;
}

数値の文字列を int 型数値に変換

それでは main 関数の一行目をご覧ください
 int dim = atoi(argv[1]);
これにより,コマンドに続けて書いた引数を int 型変数 dim に格納しています
一つ目の引数ですから,当初 argv[0] を渡すものだと考えていたのですが,これでは上手く動いてくれませんでした
そこで試しに,argv[1] とすると魔法陣を表示してくれました(謎vv)
この辺りは,複数の引数を表示するプログラムを書いて,argc と argv[] にはどのような文字列が入るかを確かめる必要があります
書籍などの他人の書いたもので学ぶより,自分で確かめるのが一番です
ただ今回は,引数を一つ渡すことさえできれば宜しいので,これで良しといたします

文字列型を数値型に変換

atoi(str) str 型を int 型に変換する
atol(str) str 型を long 型に変換する
atof(str) str 型を float 型に変換する

argv[1] は文字列型(の先頭アドレス)ですから,この文字列を int 型に変換した上で,変数 dim に格納しなけばなりません
そのために使う関数が atoi( ) です
この関数は,stdlib.h に含まれるので,このヘッダファイルをインクルードしておきます
なお,後に atof( ) 関数も使うので,ここでまとめて挙げておきました

エラートラップ

以上で,コマンドの引数として魔法陣の次数を渡すことができるようになりました
前回からの変更点は極僅かです

ところで,このプログラムは,あくまで奇数次数の魔法陣を表示だけです
やはり,正の奇数以外を引数に書いてしまった場合のことが気になります
今回は,そこの処理も書いておきましょう

#include <stdio.h>
#include <stdlib.h>
int makeSquare(int dim) {
  int a[99][99];
  int i = dim - 1;
  int j = (dim - 1) / 2;
  for (int num = 1; num <= dim * dim; num++) {
    a[i][j] = num;
    if (a[(i + 1) % dim][(j + 1) % dim] == 0) {
      i = (i + 1) % dim;
      j = (j + 1) % dim;
    } else {
      i = i - 1;
    }
  for (int i = 0; i <= dim - 1; i++) {
    for (int j = 0; j <= dim - 1; j++) {
      printf("%3d ", a[i][j]);
    }
    printf("\n");
  }
  return 0;
}
int main(int argc, char *argv[]) {
  int dim = atoi(argv[1]);
  float check = atof(argv[1]) - dim;
  if (dim > 0 && !check && dim % 2) {
    makeSquare(dim);
  } else {
    printf("Sorry!\nI can't make such a magic square.\nPlease let the argument an odd natural number.\n");
  }
  return 0;
}

折角書いたプログラムですから,できるだけ次に生かしましょう
少々の手直しをして,makeSquare( ) 関数として定義しました
そして,main( ) 関数で,奇数以外の引数をとったときには,魔法陣ができない旨のメッセージを表示するようにしました

実行結果を下に示します

yossii@penguin:~/C$  ./magics 5
 11  18  25   2   9
 10  12  19  21   3
  4   6  13  20  22
 23   5   7  14  16
 17  24   1   8  15


yossii@penguin:~/C$  ./magics 4
Sorry!
I can't make such a magic square.
Please let the argument an odd natural number.

最終更新日時: 2022年 03月 16日(水曜日) 06:13