みなためラボ

【C言語課題解説】品物の重さなどを配列に入れ、重さの合計を表示するプログラム

文字サイズ

はじめに

どうも! 高杉 皆為(@MinatameT)です。

この記事では、無限ループとbreak文や、ポインター変数とmalloc関数などを使うプログラムの課題の解答例を紹介しています。

正直なところ、今回の内容はけっこう難しいと思いますので、C言語に苦手意識のある初学者は近寄るべからずです(苦笑)。

それでは、問題文と解答例を確認していきましょう。

問題文

品物がn個あり、i番目の品物の重さが1次配列weight[i]に、i番めの品物の系統(文字列)が2次配列c[i][0]に格納されるとします。これらの入力の後、品物の重さの合計を出力してください。

ただし、nの上限は10とします。nに不正な値が入力されたら、入力をやりなおしさせてください。この入力処理では、無限ループを使いましょう。

品物の重さを格納する配列の領域は、malloc関数でn個確保してください。そのため、weightはポインター変数として宣言します。

品物の系統の入力は、EOF(配列の終端)を使ってループを終了判定させてください。

最後に、品物の重さの合計を出力するときは、小数第1位までの表示としましょう。

解答例

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
  int n; //品物の数
  int i; //品物の番号
  char c[10][100]; //最大10個の品物の系統(1つにつき最大半角100文字まで。)
  double *weight; //品物の重さ(後で配列化する。)
  double sum; //品物の重さの合計値

  sum = (double)0; //合計値の初期値はdouble型の0にしておく。

  for(; ; ) //無限ループ
  {
    printf("品物の数を入力してください。>");
    scanf("%d",&n); //品物の数の入力処理
    if(n<1 || n>10) //品物の数が1未満か10超過(不適切)なら
    {
      printf("品物の数は1個以上10個未満です。\n");
    }
    else //品物の数が1以上10以下(適切)なら
    {
      break; //for文(無限ループ)から抜け出す。
    }
  }

  weight = (double*)malloc(sizeof(double)*n); //double型のスペースをn個だけ確保する。

  for(i=0; i<n; i=i+1) //品物の数だけループする。
  {
    printf("%d個めの品物の重さ (kg) を入力してください。>",i+1);
    scanf("%lf",&weight[i]); //品物の重さを入力し、配列に代入する。
    sum = sum + weight[i]; //入力した値を、品物の重さの合計値に加える。
  }

  weight[i] = EOF; //ファイル(配列)の終端を決める。

  for(i=0; weight[i]!=EOF; i=i+1) //配列の終端ではなければループする。配列の終端ならループ終了。
  {
    printf("%d個めの品物の系統を入力してください。>",i+1);
    scanf(" %s",&c[i][0]); //品物の系統の入力
  }

  printf("品物の重さの合計は、%0.1f (kg) です。\n",sum); //%0.1fで、小数第1位まで表示。

  return(0);
}

詳しく説明すると非常に長くなり、逆に混乱してしまうと思いますので、簡単に説明します。各行の説明については、各行のコメント文(//以降)に書いてあるとおりです。

weightはポインター変数にすることで、領域情報を覚えられるようになります。ポインター変数については、次の記事でわかりやすく説明してあります。

malloc関数についてですが、これはメインメモリーの領域をプログラム実行中に確保するためのものです。

ポインター変数とmalloc関数を使うことで、配列の要素数を「プログラム実行中に入力した値」にすることができます。便利ですね。これを「領域の動的確保」といいます。

  weight = (double*)malloc(sizeof(double)*n); //double型のスペースをn個だけ確保する。

※普通は、プログラムの実行前に、配列の要素数を決める必要があります。これを「領域の静的確保」といいます。例えば、int a[5]、double x[2]などですね。

入力処理についてですが、for(; ; )で無限ループを実現できます。正しく入力されるまで脱出できない……といった仕組みが作れますね。

ここで、無限ループからの脱出方法も用意しておく必要があります。その方法は、脱出条件を設定したif文(else if文やelse文でも可。)を用意し、その中にbreak文を記述するだけです。

  for(; ; ) //無限ループ
  {
    printf("品物の数を入力してください。>");
    scanf("%d",&n); //品物の数の入力処理
    if(n<1 || n>10) //品物の数が1未満か10超過(不適切)なら
    {
      printf("品物の数は1個以上10個未満です。\n");
    }
    else //品物の数が1以上10以下(適切)なら
    {
      break; //for文(無限ループ)から抜け出す。
    }
  }

このプログラムでは、EOFを配列weight[i]に直接代入しています。

nが5の場合は、weight[0]からweight[4]までに、品物の重さが格納されていますよね。品物の重さを入力するfor文を抜けた後のiの値は「5」です。このとき、次のコードが実行されると、weight[5]にEOFが入ります。

  weight[i] = EOF; //ファイル(配列)の終端を決める。

そして、次の品物の系統入力のfor文では、weight[i]がEOF以外なら、ループを継続する条件にしています。weight[i]がEOFになれば、ループを終了します。

  for(i=0; weight[i]!=EOF; i=i+1) //配列の終端ではなければループする。配列の終端ならループ終了。
  {
    printf("%d個めの品物の系統を入力してください。>",i+1);
    scanf(" %s",&c[i][0]); //品物の系統の入力
  }

あとの出力の部分は、コメント文を読むだけで大丈夫だと思います。

  printf("品物の重さの合計は、%0.1f (kg) です。\n",sum); //%0.1fで、小数第1位まで表示。

%0.1fなら小数第1位まで、%0.3なら小数第3位までの表示です。簡単ですね。

それでは最後に、このプログラムの実行例を見ていきましょう。

品物の数を入力してください。>0
品物の数は1個以上10個未満です。
品物の数を入力してください。>100
品物の数は1個以上10個未満です。
品物の数を入力してください。>3
1個めの品物の重さ (kg) を入力してください。>5.0
2個めの品物の重さ (kg) を入力してください。>22.4
3個めの品物の重さ (kg) を入力してください。>0.7
1個めの品物の系統を入力してください。>food
2個めの品物の系統を入力してください。>machine
3個めの品物の系統を入力してください。>tool
品物の重さの合計は、28.1 (kg) です。

nに不正な値が入力されると、再入力になります。

重さの合計値を出すだけなら、系統を入力する意味はないのですが、重さと系統を入力させていきます。

そして、最後に5.0 + 22.4 + 0.7 = 28.1 と、正しい合計が表示されました!

今回はここまでです。今回の内容はけっこう難しかったと思います。皆さん、お疲れさまでした。


 

みなためじゃんけん

このコーナーは、私と擬似的にじゃんけんできるコーナーです。

みなためじゃんけん、じゃんけんぽん!

私が出したのは……





チョキ

チョキでした! グーの勝利です!



この記事をSNSでシェアする

プログラミングカテゴリーの最新記事(5件)

最新記事(10件)

管理人のTwitter

内部リンク集