第50回
プログラミング・クイズで腕試し~簡易積算プログラムを作ろう

main関数を作る

まずmain関数から作っていきます。基本的な仕様を定めていく中で、その中から呼び出される下請け関数の仕様も明確になっていきます。

main関数の基本仕様

このプログラムでは、『演算子が変更されるまで、数値の入力が繰り返される』という動作が基本となります。従って、『条件を満たすデータが入力されるまで、入力を待ち続ける』というループ処理が中心となります。

また、数値入力の前にまず演算子を入力しなければなりません。そのため、以下のような2つのループが必要になります。

  1. 演算子と最初の数値を受け取るループ
    起動直後に実行され、ユーザーから演算子の入力を受け付けます。さらに、一番最初の数値もここで受け取ります。
    演算子の入力と数値の入力には、別途関数を用意してそれを呼び出します。
    演算子の入力で'Q'を受け取ったら、プログラムは終了します。
    数値の入力で[Enter]だけ(数値の入力なし)なら、ループの先頭に戻って演算子の再入力となります。
  2. 数値の入力を待つループ
    演算子と最初の数値を受け取ったら、続く数値の入力を受け付けます。
    数値入力のための関数は、上記1.で呼び出すものと同じで構いません。
    数値が入力されれば、先に入力されている演算子に基づいて計算を行います。
    このとき、数値なしで[Enter]だけが押されたら、演算子の入力に移行しなければなりません。従って、以下のような二重ループの構造が必要になります。
ループ1:無条件に繰り返す
  ループ2:数値の入力を受け付け
          → [Enter]のみでなければ
            受け取った数値に基づいて計算し
            処理を繰り返す
          → [Enter]のみなら
            ループ2を抜ける
  ループ2終了
  演算子の入力を受け付ける
   → 演算子なら
     演算子を変更して処理を繰り返す
   → 'Q'なら
      プログラムを終了する
ループ1終了

mainから呼び出される関数の概要

次に、main関数から呼び出される3つの関数について、その概要を決めておきます。

・演算子の入力~getexp
機能 :
演算子またはQの入力だけを受け付ける。
+-*/と'Q'のいずれかが入力されるまで入力を受け付ける。
戻り値 :
入力された演算子を返す。
"Q"が入力されたときは記号定数“ERR”を返す。
“ERR”はshort int型の-1とする。
宣言 :
char getexp(void);
・数値の入力~getnum
機能 :
long型の数値を受け取る。許容範囲以内の数値または[Enter]のみが入力されるまで入力を受け付ける。
戻り値 :
入力された数値を返す。
[Enter]のみの場合は、記号常数“L_ERR”を返す。
“L_ERR”はlong int型の-1とする。
宣言 :
long getnum(void);

・2つの数値を演算~calc
機能 :
数値2つと演算子を受け取って演算子に基づく計算を行い、その結果を表示する。
戻り値 :
計算結果を返す。
宣言 :
long calc(long, long, char);
long型の引数2個は演算の対象となる数値。
char型の引数は演算子。
この関数の戻り値は、main関数のループの中で次の被演算数として保持されます。

---------------------------------------------------------------------

●問題:main関数を作る

これでmain関数が記述できるはずです。

……と、その前にヒントを2つ提示しておきましょう。

  • ヒント1 ~取り込まれるヘッダファイル
    ソースの冒頭で、以下のヘッダファイルを取り込みます。
    stdio.h、stdlib.h、string.h、conio.h
    “conio.h”は、演算子の入力でgetch関数を使うために取り込みます。

  • ヒント2 ~記号定数の定義
    以下のような記号定数を定義します。
    #define  ERR      (-1)   -------- getexp関数から返されるint型のエラー値
    #define  L_ERR    (-1L)  -------- getnum関数から返されるlong型のエラー値
では、解答を見る前にmain関数のソースを考えてみてください。

------------------------ thinking time --------------------------------

●解答

リスト1のようになります。先述したように、この解答とまったく同じ内容である必要はありません。また、コメントの有無やその内容についても書き手の自由です。

リスト1:main関数のソースコード
int  main(void)
{
  char    exp;    /* 演算子 */
  long    n1;     /* 被演算数~累積されていく */
  long    n2;     /* 演算数 */

  /* 以下のループは最初だけ実行される */
  while (1) {
    if ((exp = getexp()) == ERR)
      exit(0);    /* 演算子入力でERRが返れば終了 */
    if ((n1 = getnum()) == L_ERR)
      continue;   /* 数値入力でERRなら演算子入力から */
    else
      break;
  }
  /* 数値が入力されたら
     それ以降は以下のループが実行される */
  while (1) {
    /* L_ERRが返るまで演算を繰り返す */
    while ((n2 = getnum()) != L_ERR)
      /* 演算結果を保存しておく */
      n1 = calc(n1, n2, exp);
    if ((exp = getexp()) == ERR)
      exit(0);   /* 演算子入力でERRが返れば終了 */
  }
}