Ex05

From Prog0

Jump to: navigation, search

演習第5回

Contents

演習問題

主な内容

  • while文
  • 代入演算子
  • インクリメント・デクリメント
  • 無限ループ

以下の問題を解いて期限内に解答を提出してください。

出席確認

演習時間中に出席確認をLMS上の「演習出欠」で行ってください。出席確認用のパスワードは演習時間のどこかのタイミングで提示されます。


A問題

A-1 whileループ

ファイル名: ex05a1.c

以下のような動作をするプログラムを作成したい。

(1) まず変数 n に正の整数を入力する。
(2) n を2で割って、商と余りを求め、それぞれ n と r に代入する。
(3) 計算の途中経過を表示する(実行例参照)
(4) (2)-(3) の処理を繰り返す。
(5) n の値が0になったらプログラムを終了する。

このプログラムは、変数 n の値を監視し、n が0より大きい間はループを継続するので、whileを用いた見張り方式で実現するのに適している。 以下の下線部の空欄を埋めてプログラムを完成させなさい。

#include <stdio.h>

int main() {

  int n, r, count=0;

  printf("初期値の入力 : ");
  scanf("%d", &n);
  while( _____ ) {
    count = count + 1 ;
    __ = _____ ;
    __ = _____ ;
    printf("%d回目ループ 商 %d  余り %d\n", _________ );
  }

  return 0;
}

[実行例1]

% ./a.out
初期値の入力 : 10
1回目ループ 商 5  余り 0
2回目ループ 商 2  余り 1
3回目ループ 商 1  余り 0
4回目ループ 商 0  余り 1

[実行例2]

% ./a.out
初期値の入力 : 50
1回目ループ 商 25  余り 0
2回目ループ 商 12  余り 1
3回目ループ 商 6  余り 0
4回目ループ 商 3  余り 0
5回目ループ 商 1  余り 1
6回目ループ 商 0  余り 1

ちなみに、計算された余りを下から順に取り出して、左から並べると、元の初期値を2進数であらわしたものになっている。(例えば10進数の50 = 2進数の110010)

A-2 whileループとインクリメント・デクリメント・代入演算子

ファイル名: ex05a2.c

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

A-3 無限ループによる書き換え

ファイル名: ex05a3.c

A-2で作成したプログラムはさらに、無限ループ(while(1))を使って書き換えることができる。このように書き直したプログラムを作成しなさい。

(A-2で作成したインクリメントや代入演算子部分はそのまま残すこと)

B問題

B-1 コラッツの問題

ファイル名: ex05b1.c

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

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

という操作を繰り返すと、最終的に n は 1 になる、と予想した。これを コラッツの問題 と呼ぶ。 この問題はまだ証明はされていないものの、実際に任意の自然数 n に対してこの通りとなるか、コンピュータのプログラムで確かめることができる。

以下に示すフローチャートを参考にし、下線部および補うよう指示された部分を補ってプログラムを完成させなさい。

ただし、フローチャートには一部の画面表示の処理などは記入されていない。これらの処理についてはプログラム内で適切な場所を自分で考え、printf文などを入れること。

#include <stdio.h>

int main()
{
  int n;
  
  printf("0でない自然数nを入力して下さい ");
  scanf("%d", &n);
  
  while ( _______ ) {


  /* この部分に必要なプログラムを補う */    

   
  }

  printf("終了\n");
  return 0;   
}

[実行例]

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

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

ファイル名: ex05b2.c

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

[実行例]

% ./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 となったかを表示する機能の追加

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

B-3 ユークリッドの互除法

ファイル名: ex05b3.c

ユークリッドの互除法は、2 つの自然数(0を含むとする)の最大公約数を求める手法の一つである。アルゴリズム(手順)を以下に示す。

この方法を用いて、入力された二つの数値の最大公約数を求めるプログラムを作成しなさい。

ただし、実行例のように途中経過を表示すること。 入力値に対するエラー処理は含めなくてもよい。

 アルゴリズム

   1. 入力を m, n (m ≧ n) とする。
   2. n = 0 なら、 m を最大公約数として出力し、プログラムを終了する。
   3. m を n で割った余りを新たに n とし、
      元のnを新たにm として、
      2. に戻る。

[実行例]

% ./a.out
m nを入力して下さい:21 14
21 % 14 = 7
14 % 7 = 0
最大公約数は 7 です
% ./a.out
m nを入力して下さい:32 18
32 % 18 = 14
18 % 14 = 4
14 % 4 = 2
4 % 2 = 0
最大公約数は 2 です
% ./a.out
m nを入力して下さい:78 48
78 % 48 = 30
48 % 30 = 18
30 % 18 = 12
18 % 12 = 6
12 % 6 = 0
最大公約数は 6 です
%

B-4 インクリメント・デクリメント

ファイル名: ex05b4.txt

次のプログラムを作成し、実行せよ。

#include <stdio.h>

int main() {

    int i = 0;

    i++;
    printf("%d\n", i);
    ++i;
    printf("%d\n", i);
    printf("-------------\n");

    printf("%d\n", ++i);
    printf("%d\n", i++);
    printf("%d\n", --i);
    printf("%d\n", i--);

    return 0;
}

このプログラムの出力は以下の実行例のようになる。

[実行例]

% ./a.out    
1
2
-------------
3
3
3
3
%

"3"が連続して4回出力される理由を、 ex05b4.txt に簡潔に説明して提出してください。

説明の仕方は、下記にならってください。

最初の"3"は、前置インクリメントによって出力よりも前にiに1が足されるため、3が出力される。出力後のiの値は3である。
2番目の"3"は、・・・・・

Extra問題

E-1 曜日の計算

ファイル名: ex05e1.c

閏年でないある年の1月1日は日曜日であった。その年の月日を入力したら、その日付が1月1日から何日目であるかと何曜日であるかを計算して表示するプログラムを作成せよ。ただし、while文とswitch-case文を利用した以下の仕様に従うものとする。

  • 1月1日から入力された月日までの日数(積算日数)を、while文を用いて各月の日数(下記参照)をもとに計算する。
  • 計算した積算日数から曜日を求める。この時のみswitch-case文を用いる。
  • 誤った日付やあり得ない日付が入力された場合のエラー処理は考慮しなくてよい。

各月の日数

31日:1, 3, 5, 7, 8, 10, 12月
30日:4, 6, 9, 11月
28日:2月

[実行例]

% ./a.out
月と日を空白で区切って入力してください:1 1
2023年1月1日は1日目で日曜日です
% ./a.out
月と日を空白で区切って入力してください:4 10
2023年4月10日は100日目で月曜日です
% ./a.out
月と日を空白で区切って入力してください:6 23
2023年6月23日は174日目で金曜日です
%

課題提出上の注意事項

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

% ~prog0/bin/menu

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

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

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

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

Personal tools