★データ構造(配列12)★


以前、おつりの「金種」を求めるプログラムを作りました。

今回は大きくグレードアップしたプログラムを作りましょう。

スーパーのレジなどで、支払った金額が入力されると自動的にお釣りが出てくるのを見たことがありませんか?

ファストフード店で見たことがある人もいるでしょう。

あれはどのような仕組みになっているのでしょうか?

自動的にお釣りが出てこないレジでも「お釣りの計算」はしてくれますので、そこから始めましょう。


まずは簡単に、次の実行結果が表示されるプログラムを考えてください。

<実行結果>

価格を入力してください:2568
支払金額を入力してください:5000
お釣りは2432円です。
続行するには何かキーを押してください・・・

先に、変数名を決めておきましょう。

  価格   price

  支払金額 payment

  お釣り  change

これで、作成してみてください。









































解答例です。


<sample program 072-01>

#include <stdio.h>

int main(void)
{
    int price;   /* 価格 */
    int payment; /* 支払金額 */
    int change;  /* お釣り */

    printf("価格を入力してください:");

    scanf("%d", &price);

    printf("支払金額を入力してください:");

    scanf("%d", &payment);

    change = payment - price;

    printf("お釣りは%d円です。\n", change);

    return 0;
}

<実行結果>

価格を入力してください:1231
支払金額を入力してください:2000
お釣りは769円です。
続行するには何かキーを押してください・・・

ここまでは大丈夫ですよね。

では、↓の実行結果に合うように変更をかけてみてください。

<実行結果>

価格を入力してください:1231
支払金額を入力してください:2000
お釣りは769円です。
続行するには何かキーを押してください・・・

<実行結果>

価格を入力してください:1231
支払金額を入力してください:1000
支払金額が不足しています。
続行するには何かキーを押してください・・・









































解答例です。


<sample program 072-02>

#include <stdio.h>

int main(void)
{
    int price;   /* 価格 */
    int payment; /* 支払金額 */
    int change;  /* お釣り */

    printf("価格を入力してください:");

    scanf("%d", &price);

    printf("支払金額を入力してください:");

    scanf("%d", &payment);

    if (price <= payment) {

        change = payment - price;

        printf("お釣りは%d円です。\n", change);
    }
    else {

        printf("支払金額が不足しています。\n");
    }

    return 0;
}

<実行結果>

価格を入力してください:1231
支払金額を入力してください:2000
お釣りは769円です。
続行するには何かキーを押してください・・・

<実行結果>

価格を入力してください:1231
支払金額を入力してください:1000
支払金額が不足しています。
続行するには何かキーを押してください・・・

さて、ここからが問題です。

お釣りの計算が完了したら、金種を求めなければなりません。

お釣りの可能性のある金種は、以下の通りです。

5,000円
1,000円
  500円
  100円
   50円
   10円
    5円
    1円

今回は配列を作り、それぞれの枚数を保存しておくことを考えてみます。

先ほどのプログラムに配列を追加します。

金種は8種類ですから、defineで8という数値も定義しておきましょう。

<sample program 072-03-1>

#include <stdio.h>

#define KIND 8

int main(void)
{
    /* 数量(枚数) */
    int amount[KIND];

    int price;   /* 価格 */
    int payment; /* 支払金額 */
    int change;  /* お釣り */

    printf("価格を入力してください:");

    scanf("%d", &price);

    printf("支払金額を入力してください:");

    scanf("%d", &payment);

    if (price <= payment) {

        change = payment - price;

        printf("お釣りは%d円です。\n", change);
    }
    else {

        printf("支払金額が不足しています。\n");
    }

    return 0;
}

この配列amountは以下のように考えます。

  amount[0] 5,000円の枚数
  amount[1] 1,000円の枚数
  amount[2]   500円の枚数
  amount[3]   100円の枚数
  amount[4]   50円の枚数
  amount[5]   10円の枚数
  amount[6]    5円の枚数
  amount[7]    1円の枚数

それぞれの金種の枚数を計算する方法は以前のプログラムで同じようなことをやりました。

  お釣り ÷ 5000 = 5,000円の枚数

お釣りが、7,000円であれば、

  7000 ÷ 5000 = 1.4

整数で計算すれば、小数点以下切り捨てですから、「1」枚です。

お釣りが、4,000円であれば

  4000 ÷ 5000 = 0.8

つまり「0」枚です。


↑の計算を商と余りという考え方に当てはめてみるとさらに分かることがあります。

  7000 ÷ 5000 = 1 ... 2000

  4000 ÷ 5000 = 0 ... 4000

割った商が「枚数」、余りが「残りの金額」になっています。

この「残りの金額」を次の計算に使う訳です。

次の計算とは1,000円の枚数を求める計算です。

1,000円の枚数計算も同じように「商」と「余り」を求めます。

商は1,000円の枚数となり、余りは次の計算に使います。

これを1円単位まで行うと完成します。

では、↑に書いたことをそのままプログラムにしてみます。


<sample program 072-03-2>

#include <stdio.h>

#define KIND 8

int main(void)
{
    /* 数量(枚数) */
    int amount[KIND];

    int i;

    int price;   /* 価格 */
    int payment; /* 支払金額 */
    int change;  /* お釣り */

    printf("価格を入力してください:");

    scanf("%d", &price);

    printf("支払金額を入力してください:");

    scanf("%d", &payment);

    if (price <= payment) {

        change = payment - price;
        
        printf("お釣りは%d円です。\n", change);

        /* 5,000円 */

        amount[0] = change / 5000;

        change = change % 5000;

        /* 1,000円 */

        amount[1] = change / 1000;

        change = change % 1000;

        /* 500円 */

        amount[2] = change / 500;

        change = change % 500;

        /* 100円 */

        amount[3] = change / 100;

        change = change % 100;

        /* 50円 */

        amount[4] = change / 50;

        change = change % 50;

        /* 10円 */

        amount[5] = change / 10;

        change = change % 10;

        /* 5円 */

        amount[6] = change / 5;

        change = change % 5;

        /* 1円 */

        amount[7] = change / 1;

        change = change % 1;

        for (i = 0; i < KIND; i++) {
            printf("%d枚\n", amount[i]);
        }
    }
    else {

        printf("支払金額が不足しています。\n");
    }

    return 0;
}

<実行結果>

価格を入力してください:1234
支払金額を入力してください:2000
お釣りは766円です。
0枚
0枚
1枚
2枚
1枚
1枚
1枚
1枚
続行するには何かキーを押してください・・・

完成していますね。

完成していますが、不恰好なプログラムになってしまいました。

似たようなプログラムが並んでいるのであれば、繰り返しを使ったプログラムの方がすっきりします。

しかし、まったく同じプログラムでは無いため、どのように考えれば繰り返し処理が出来るでしょうか。

似たような箇所を抜き出してみます。

amount[0] = change / 5000;

change = change % 5000;

ほぼ、同じプログラムが1円の箇所まで続くのですが、異なる箇所は↓の通りです。

amount[0] = change / 5000;

change = change % 5000;

添え字の部分は「0」から「7」まで変化しています。

これに関してはfor文を使えば何とかなりそうです。

for (i = 0; i < KIND; i++) {
    amount[i] = change / 金種;
    change = change % 金種;
}

金種の部分は、5000→1000→500→100→50→10→5→1と変化するため、法則的なものが見えてきません

ここさえクリアできれば、繰り返し処理に切り替えることが出来そうです・・・


これを解決するため「テーブル」というものを使います。

「テーブル」とは、あらかじめ数値の入った配列と考えてもらえれば良いです。

今回は「金種テーブル」というものを作ってみます。

/* 金種テーブル */
int denomination[KIND] = { 5000, 1000, 500, 100, 50, 10, 5, 1 };

金種の金額は一定の法則に従って計算すると考えると難しそうな数値です。

そこで、配列にあらかじめ数値を入れておきます。

すると、

  5000 は denomination[0]
  1000 は denomination[1]
   500 は denomination[2]
   100 は denomination[3]
    50 は denomination[4]
    10 は denomination[5]
     5 は denomination[6]
     1 は denomination[7]

で指定することが出来ますから、「0」から「7」の数値でそれぞれの金種が使えるようになります。

「0」から「7」の数値はfor文のカウンタとしてすでに存在していますので、

for (i = 0; i < KIND; i++) {
    amount[i] = change / denomination[i];
    change = change % denomination[i];
}

とすれば、繰り返し処理に切り替えることが出来ますね。

それでは作ってみましょう。


<sample program 072-04>

#include <stdio.h>

#define KIND 8

int main(void)
{
    /* 金種テーブル */
    int denomination[KIND] = { 5000, 1000, 500, 100, 50, 10, 5, 1 };

    /* 数量(枚数) */
    int amount[KIND];

    int i;

    int price;   /* 価格 */
    int payment; /* 支払金額 */
    int change;  /* お釣り */

    printf("価格を入力してください:");

    scanf("%d", &price);

    printf("支払金額を入力してください:");

    scanf("%d", &payment);

    if (price <= payment) {

        change = payment - price;

        printf("お釣りは%d円です。\n", change);

        for (i = 0; i < KIND; i++) {
            amount[i] = change / denomination[i];
            change = change % denomination[i];
        }

        for (i = 0; i < KIND; i++) {
            printf("%d枚\n", amount[i]);
        }
    }
    else {

        printf("支払金額が不足しています。\n");
    }

    return 0;
}

<実行結果>

価格を入力してください:1234
支払金額を入力してください:2000
お釣りは766円です。
0枚
0枚
1枚
2枚
1枚
1枚
1枚
1枚
続行するには何かキーを押してください・・・

どの金種の枚数か分かりずらいので、金種テーブルを使って表示を書き換えます。

<sample program 072-05>

#include <stdio.h>

#define KIND 8

int main(void)
{
    /* 金種テーブル */
    int denomination[KIND] = { 5000, 1000, 500, 100, 50, 10, 5, 1 };

    /* 数量(枚数) */
    int amount[KIND];

    int i;

    int price;   /* 価格 */
    int payment; /* 支払金額 */
    int change;  /* お釣り */

    printf("価格を入力してください:");

    scanf("%d", &price);

    printf("支払金額を入力してください:");

    scanf("%d", &payment);

    if (price <= payment) {

        change = payment - price;

        printf("お釣りは%d円です。\n", change);

        for (i = 0; i < KIND; i++) {
            amount[i] = change / denomination[i];
            change = change % denomination[i];
        }

        for (i = 0; i < KIND; i++) {
            printf("%4d円 %d枚\n", denomination[i], amount[i]);
        }
    }
    else {

        printf("支払金額が不足しています。\n");
    }

    return 0;
}

<実行結果>

価格を入力してください:1234
支払金額を入力してください:2000
お釣りは766円です。
5000円 0枚
1000円 0枚
 500円 1枚
 100円 2枚
  50円 1枚
  10円 1枚
   5円 1枚
   1円 1枚
続行するには何かキーを押してください・・・

このように「テーブル」を使えば、不規則な並びの数を一定の法則に従って扱うことが出来ます。

色々と応用出来ますので、必ず覚えておいてください。


次へ

戻る

目次へ