Prog0:Users

From Prog0

Jump to: navigation, search

演習第 4 回

Contents

主な内容

  • インデント・フローチャート・ループ・while・見張り方式
  • インクリメント演算子・デクリメント演算子・前置・後置
  • 代入演算子・無限ループ


A問題

A-1 複雑なif文

ファイル名:ex04a1.txt

日付を入力して、それが月の最後の日か判断するプログラムlec04-1.clec04-2.cは講義で取り上げた通り、正しく動作しない。

正しいプログラムはlec04-3a.cおよびlec04-3b.cにあるが、両者のプログラムの内容と、実際にコンパイル、実行した際の結果をよく見て、どのような場合に正しく動作しないのかを説明せよ。

入力した日付によって正しく動作するように見える場合と、明らかにおかしい動作を行う場合があるので、それぞれ具体的な入力例とその結果を示した上、正しく動作しない理由を記述すること。

A-2 whileループ

ファイル名:ex04a2.c

変数 a にある初期値(正の整数とする)を代入してから、最初は1を引き、次は2を引き、と順に1づつ大きい数を引いていく。計算の途中経過を表示するとともに、結果が0以下となったところで計算を停めるとする。

このプログラムは変数 a の値を監視し,a が 0 以下となるまでループを継続する、while文を用いた見張り方式で実現できる。

以下のプログラムの下線部を埋めて完成させなさい。

Image:Ex04a1.png

[実行例]

% ./a.out
初期値を入力して下さい。
100
ループ1回目 a = 99 
ループ2回目 a = 97 
ループ3回目 a = 94 
ループ4回目 a = 90 
ループ5回目 a = 85 
ループ6回目 a = 79 
ループ7回目 a = 72 
ループ8回目 a = 64 
ループ9回目 a = 55 
ループ10回目 a = 45 
ループ11回目 a = 34 
ループ12回目 a = 22 
ループ13回目 a = 9 
ループ14回目 a = -5 
14回目のループで 0 以下になりました

A-3 インクリメント・デクリメント・代入演算子

ファイル名:ex04a3.c

A-2で作成したプログラムの中で,インクリメント・デクリメント・代入演算子を使って書き換えることのできる部分がある.この部分を書き直したプログラムを作成しなさい

A-4 無限ループ

ファイル名:ex04a4.c

以下のプログラムでは,キーボードから繰り返し整数を入力させ,正の値が合計3回入力されたら終了する動作を無限ループを利用して行う.下線部を補ってプログラムを完成させなさい.

なお,二つの変数inputとcountはそれぞれ以下のような意味を持つ.

input
キーボードから入力した整数値
count
正の値が入力された回数
#include <stdio.h>

main () {

int   input;
int   count = 0;

 while( _______ ){

   printf("正の値は%d回入力されています.整数を入力して下さい.\n", count);

   scanf("%f", &input );
   if( _______ ){
     _______;
   }

   if( _______ ) _______;

 }

 printf("3回正の値が入力されました.プログラムを終了します.\n");

}


[実行例]

 % ./a.out    
正の値は0回入力されています.整数を入力して下さい.
2   
正の値は1回入力されています.整数を入力して下さい.
-1   
正の値は1回入力されています.整数を入力して下さい.
0   
正の値は1回入力されています.整数を入力して下さい.
1   
正の値は2回入力されています.整数を入力して下さい.
2   
3回正の値が入力されました.プログラムを終了します.

B問題

B-1 if・switch-caseの復習

ファイル名:ex04b1.c

以下は,ハンドアウトLec04-6にあるif文を用いた月末日判定のプログラムをもとに,switch-case文を用いて同じ機能を実現したものである.以下の指示に従って足りない部分を補い,プログラムを完成させよ.なお,うるう年は考慮しなくてよい.

  • 下線部________の中を補う
  • /* ここに必要なプログラムを書く */ と書かれている部分を補う
  • break文が必要な箇所を探して補う

注意:プログラムが正しく動作するか確かめる際には,上記の実行例で示されている月日の入力以外の場合でも試してみる必要がある.どんな条件で試すべきか,よく考えること

 #include <stdio.h>
main()
{
  int m,d;
  
  printf("月と日を空白で区切って入力してください : ");
  scanf("%d %d",&m, &d);
  
  switch (________) {

     /* ここに必要なプログラムを書く */

     switch (________) {
       ________:
         printf("%d月%d日は月の最後の日\n",m,d);
       ________:
         printf("%d月%d日は月の最後の日ではない\n",m,d);
       }

     /* ここに必要なプログラムを書く */

     switch (_____) {
       ________:
         printf("%d月%d日は月の最後の日\n",m,d);
       ________:
         printf("%d月%d日は月の最後の日ではない\n",m,d);
       }

     /* ここに必要なプログラムを書く */

     switch (_____) {
       ________:
         printf("%d月%d日は月の最後の日\n",m,d);
       ________:
         printf("%d月%d日は月の最後の日ではない\n",m,d);
       }
 }
}

[実行例]

% ./a.out
月と日を空白で区切って入力してください : 1 1
1月1日は月の最後の日ではない

% ./a.out
月と日を空白で区切って入力してください : 1 31
1月31日は月の最後の日

B-2 コラッツの問題

ファイル名:ex04b2.c

ドイツの数学者コラッツは任意の0でない自然数 n に対して、

  • n が偶数の場合、n を 2 で割る
  • n が奇数の場合、n に 3 をかけて 1 を足す

という操作を繰り返すと、最終的に n は 1 になる、と予想した。これを コラッツの問題 と呼ぶ。

この問題はまだ証明はされていないものの、実際に任意の自然数 n に対してこの通りとなるか、コンピュータのプログラムで確かめることができる。

以下に示すフローチャートを参考にし、下線部および指示された部分を補ってプログラムを完成させよ。ただし、フローチャートには一部の画面表示の処理などは記入されていない。これらの処理についてはプログラム内で適切な場所を自分で考え、printf文などを入れること。

#include <stdio.h>
main()
{
  int n;
  
  printf("0でない自然数nを入力\n");
  scanf("%d", &n);
  
  while ( _______ ) {

/* この部分に必要なプログラムを補う */    
   
 }
 printf("終了します\n");
  
}

[実行例]

% ./a.out
0でない自然数nを入力
3
n = 10
n = 5
n = 16
n = 8
n = 4
n = 2
n = 1
終了します

B-3 コラッツの問題プログラムの改良

ファイル名:ex04b3.c

#B-2 コラッツの問題で作成したプログラムに改良を加えて、以下のように計算の途中経過や計算回数がわかるようにしたい。

[実行例]

% ./a.out
0でない自然数nを入力
3
1回目
3は奇数
次の n = 10

2回目
10は偶数
次の n = 5

3回目
5は奇数
次の n = 16

4回目
16は偶数
次の n = 8

5回目
8は偶数
次の n = 4

6回目
4は偶数
次の n = 2

7回目
2は偶数
次の n = 1

7回目でn = 1 になりました

このプログラムを実現するためには、

  • 計算回数を記録する変数の追加
  • 毎回の n の状態(偶数か奇数か)を表示する機能の追加
  • 次の n を表示する機能の追加
  • 何回目で n=1 となったかを表示する機能の追加

が必要である。これらの機能追加を行い、プログラムを完成させよ。

ポイント
機能追加をプログラム内のどこで行うか(ループの前,ループの中,ループの後)についてよく考えること
また,whileループの中およびループの終了後に変数の値がどうなっているのかをよく確認すること


C問題

C-1 whileループとswitch-caseの組合せ

ファイル名:ex04c1.c

前回の演習問題 Ex03 A-3 で,switch-case文を利用した班分けのプログラムを制作した.このプログラムを,班分けの処理を繰り返しを行えるように改造したい.以下の方針に基づいてプログラムを作成せよ.

  • 学生の人数は一定しないため,見張り方式のループで処理を繰り返す.
  • 終了する場合は,学籍番号の代わりに0 を入力する.

[実行例]

% ./a.out 
学籍番号の下三桁を入力してください(例: 400)> 003
この人は第3班です
学籍番号の下三桁を入力してください(例: 400)> 102
この人は第2班です
学籍番号の下三桁を入力してください(例: 400)> 65
この人は第1班です
学籍番号の下三桁を入力してください(例: 400)> 230
この人は第2班です
学籍番号の下三桁を入力してください(例: 400)> 0
プログラムを終了します


C-2 ループを利用した平均点の算出

ファイル名:ex04c2.c

ある授業における試験の得点を入力して,試験を受けた学生の人数と得点の平均点,最高点と最低点を算出したい.プログラムの仕様は以下の通りとする.実行例も参考にしてプログラムを作成せよ.

  • 得点は整数とし,満点は100点とする
  • 平均点は浮動小数点型の実数とする
  • 得点を順番に入力する
  • 得点の代わりに負の数を入力することで入力を終了し,平均点の算出と学生の人数・平均点の出力を行う

[実行例]

% ./a.out    
得点を入力して下さい: 80
得点を入力して下さい: 23
得点を入力して下さい: 50
得点を入力して下さい: 60
得点を入力して下さい: -1
受験者数は 4 人で,平均点は 53.250000 点です
最高点は 80 点,最低点は 23 点です


C-3 借金の返済管理

ファイル名:ex04c3.c

ある人が友人に1万円の借金をします.毎月すこしづつ返済しますが,未返済の残額には一ヶ月ごとに5%の利子がつくことになっています. 以下のように毎月の返済額と利子適用後の残額を記録・表示して,返済が終了するまで動くプログラムを作成しなさい.

なお,

  • 最初の月には利子はつかないものとします
  • 残額以上に返済しても,返済終了と見なします
  • 1円以下の端数は無視します(プログラム上の取り扱い方法は各自で考えなさい)

としてよい.

[実行例]

% ./a.out
1ヶ月目
利子適用後の借金の残額は10000円です
今月の返済金額を入力して下さい
5000
借金の残額は5000円になりました

2ヶ月目
利子適用後の借金の残額は5250円です
今月の返済金額を入力して下さい
5000
借金の残額は250円になりました

3ヶ月目
利子適用後の借金の残額は262円です
今月の返済金額を入力して下さい
262
借金の残額は0円になりました

返済が終了しました


課題提出上の注意事項

解答ファイルはmenuコマンドを使って提出してください。以下のようにmenuコマンドを実行し、表示されるメッセージに沿って操作すること。

% ~prog0/bin/menu

menuコマンドは、解答ファイルが ~/Prog0/Ex## のディレクトリに指定されたファイル名で置かれているものとして処理します。正常に提出された場合は ○ が、何らかのエラーが生じた場合は × が表示されます。

解答の提出期間は以下のとおりです。

問題提出受付開始提出〆切
A問題 演習日の6日前の午後9時演習終了時刻
B, Extra問題 演習日の6日前の午後9時演習日の6日後の午後9時

提出は〆切前であれば何度でもやり直すことができます。再提出すると、前に提出したファイルは新しい内容で上書きされます。

Personal tools