第5週 for文を用いたプログラムの流れの繰り返し
INDEX

目標

  • for文を使って、指定回数分の繰り返し処理を実現することができる。
  • for文をネストすることで、2重ループの処理を実現することができる。

予習・復習

 以下のスライドを利用して、予習と復習をしよう。復習では、自分の理解度を確認するために、実際にプログラムを作成し、意図する結果が得られるか確認しよう。
  1. for文

本日の講義・演習予定

  1. インクリメントとデクリメント
  2. for文
  3. 代入演算子
  4. 二重ループ
  5. 演習問題
  6. 提出課題
内 容
  1. インクリメントとデクリメント
  2. for文
  3. 代入演算子
  4. 二重ループ

インクリメントとデクリメント

 変数の値を1、2、3、4、、のようにカウントアップしたり、10、9、8、7、、のようにカウントダウンするときには、それぞれ、
a = a + 1
a = a - 1
と記述しました。
 プログラム中には、このような1増やしたり1減らすという演算がよく登場することから、省略記法として下表の演算子が用意されています。

インクリメント演算子、デクリメント演算子
演算子名称説明記述例説明
++インクリメント演算子変数の値を1増やすa++または++aaの値を1増やす
--デクリメント演算子変数の値を1減らすa--または--aaの値を1減らす

例 incdec.c
#include <stdio.h>

int main(void)
{
    int a = 1;
 
    a++;            // インクリメント a=a+1と同じ
    printf("%d\n",a );
 
    a--;            // デクリメント b=b+1と同じ
    printf("%d\n", a);
     
    return 0;
}

前置インクリメントと後置インクリメント

 インクリメント演算子には、その演算子を変数の前に記述する前置型と後に記述する後置型あります。前置型はその演算子を含むステートメントの処理の前で1加算されます。後置型はその演算子を含むステートメントの後で1加算されます。
prepost.c
#include <stdio.h>

int main(void)
{
	int a, num;

	num = 10;
	printf("num++ => %d\n", num++);			//後置 numの値が表示された後で1加算される
	printf("++num => %d\n", ++num);			//前置 1加算された後、その値が表示される

	num = 10;
	a = num++;
	printf("a = num++ ==> a = %d num =  %d\n", a,num);

	num = 10;
	a = ++num;
	printf("a = ++num ==> a = %d num =  %d\n", a,num);

	return 0;
}
 デクリメント演算子(--)についても前置型と後置型があり、インクリメント演算子と同様に異なるタイミングで処理されます。

for文

繰り返し画面に表示する

 for文を使って、画面にメッセージを10回繰り返して表示するプログラム例for.cです。int型の変数iは、繰り返しの回数を数えあげるためのカウンタ変数です。キーワードforの直後のカッコの中には繰り返しの回数を決めるための3つの式が記述されています。先頭から「カウンタ変数の初期化」、「繰り返し条件」、「カウンタ変数のカウント」です。その後には、繰り返しの対象となる処理を波括弧{}で囲ってコードブロックを構成します。文が一つしかないときには波括弧{}は必ずしも必要ではありません。
例 for.c
#include <stdio.h>

int main(void)
{
	int i;
	
	// 初期値; 条件; カウント
	for (i=1; i<=10; i++) {
		printf("I love C programing.\n");
	}

	return 0;
}
構文:
for (カウンタ変数の初期値; 繰り返し条件; カウンタ変数の増減) {

     繰り返したい処理

}

カウントダウン

 for文では繰り返し処理の回数を制御するために制御変数(例えば、変数i)を使います。先の例ではこのカウンタ変数をカウントアップすることで繰り返し処理を実現しましたが、次の例ではカウンタ変数をカウントダウン、初期値10から1ずつ減ずる(Decrement)ことで繰り返し処理を実現しています。
例 countdown.c
#include <stdio.h>

int main(void)
{
	int i;
	
	//初期値; 条件; デクリメント
	for (i=10; i>=1; i--) {
		printf("%2d\n",i);
	}

	return 0;
}
for文のカッコの中の3つの記述は、先頭から「始めにiの値を10に設定」、「iの値が1以上の間繰り返す」、「毎回iの値を1減ずる」となっています。変数iを減ずるためにデクリメント演算子--が使われています。

代入演算子

1から10までの合計値を求める

 for文を使って、1から10までの合計を求めてみましょう。
例 sum.c
#include <stdio.h>

int main(void)
{
	int i, sum=0;			//カウンタ、合計値
	
	for (i=1; i<=10; i++) {
		sum += i;				//代入演算子 sum = sum + i;
	}

	printf("1から10までの合計 %d\n", sum);
	
	return 0;
}
0からNまでの合計を求めるためには、
0で初期化した変数sumに、1〜Nまでの値を順番に加算していく。
sum += i は、sum = sum + i の省略形で、代入演算子と呼ぶ。

代入演算子

 以下に代入演算子の一覧を示します。 表. 代入演算子
演算子説明記述例説明
+=加算して代入 a += 5; a+5の結果をaに代入する(a = a+5と同じ)
-=減算して代入 a -= 5; a-5の結果をaに代入する(a = a-5と同じ)
*=乗算して代入 a *= 5; a*5の結果をaに代入する(a = a*5と同じ)
/=除算して代入 a /= 5; a/5の結果をaに代入する(a = a/5と同じ)
%=剰余を代入 a %= 5; a%5の結果をaに代入する(a = a%5と同じ)

2重ループ

 繰り返し処理を入れ子構造にする(ネスティング:nesting)することで、2重ループを構成することができます。ネストは1度だけと限らず何度も繰り返すことで多重ループを実現することもできます。
 次の例は、外側のループのカウンタ変数にiを、内側のループのカウンタ変数にjを使って、内側の10回の繰り返し処理を外側の繰り返し処理で5回繰り返しています。
nest.c
#include <stdio.h>

int main(void)
{
	int i,j;
	
	for (i=0; i<5; i++) {
		printf("%2d: ",i);
		for (j=0; j<10; j++) {
			printf("%2d",j);
		}
		printf("\n");
	}

	return 0;
}


expand_lessBack to TOP
内 容
  1. 浮動小数点数をループカウンタに使用しない

浮動小数点数をループカウンタに使用しない

 次のプログラム例は、0.1から1.0まで0.1刻みで10回の繰り返し処理を期待して、for文のカウンタ変数に浮動小数点数型変数を利用した例です。実際にこのプログラムを実行して期待通りの結果が得られるか確認してしてみましょう。
fncounter.c
#include <stdio.h>

int main(void)
{
	float i;
	int count=1;

	for(i=0.1f; i<=1.0f; i+=0.1f){
		printf("%2d: %.10f\n",count++,i);
	}

	return 0;
}
 多くの処理系(x86)では、カウントアップされたカウンタ変数値は期待した値よりも大きくなり、繰り返し処理は9回しか行われなかったでしょう。なぜなら、10進数の0.1は2進数では0.001100110011・・・と、無限小数(循環小数)になるため、正確な値を表現することができないからです。


expand_lessBack to TOP

演習

  1. 次は、画面に「羊が1匹、羊が2匹、・・・」と100匹まで数えるプログラムです。空欄を埋めて完成させなさい。
  2. ex5-1.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i;
    	
    	for ([[空欄ア]]; [[空欄イ]]; [[空欄ウ]]) {
    		printf("羊が%d匹\n", i);
    	}
    	printf("Zzz、Zzz、Zzzzz、....\n");
    
    	return 0;
    }
    

  3. 10人分の得点を入力して、その合計と平均を求めるプログラムex5-2.cを空欄を埋めて作成しなさい。
  4. ex5-2.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i, score, [[空欄ア]];
    
    	for (i=1; [[空欄イ]]; i++) {
    		printf("%d人目の得点>> ", i);
    		scanf("%d",[[空欄ウ]]);
    		[[空欄エ]];
    	}
    
    	printf("合計は%d点、平均は%.1f点です。\n", sum, [[空欄オ]];
    	return 0;
    }
    

  5. 以下は、1から100までの奇数の合計値を求めるプログラムです。空欄を埋めて完成させなさい。
  6. ex5-3.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i, sum=0;
    
    	for ([[空欄ア]]; [[空欄イ]]; [[空欄ウ]]) {
    		sum = sum + i;
    	}
    	printf("1から100までの奇数の合計は、%dです。\n",sum);
    	
    	return 0;
    }
    

  7. 以下は、九九の計算結果を表示するプログラムです。空欄を埋めて完成させなさい。(九九の計算i×jには、i,jのそれぞれの値が1から9までの合計81個の組み合わせがあります。1の段に対して1〜9まで乗数を、2の段に対しても1〜9までの乗数を、のように外側のループで段数を、内側のループで各段に対する1から9までの乗数を表すことで九九の表を実現します。)
  8. ex5-4.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i,j;
    	
    	for (i=1; [[空欄ア]]; [[空欄イ]]) {
    		for (j=1; [[空欄ウ]]; [[空欄エ]]) {
    			printf("%3d", [[空欄オ]]);
    		}
    		printf([[空欄カ]]);
    	}
    	printf("\n");
    	
    	return 0;
    }
    

  9. 100から1までの整数で、3と5の公倍数を表示するプログラムex5-5.c を空欄を埋めて作成しなさい。
  10. ex5-5.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i;
    	for (i=100; [[空欄ア]];[[空欄イ]]) {
    		if ([[空欄ウ]]){
    			printf("%3d",i);
    		}
    	}
    	printf("\n");
    	return 0;
    }
    

  11. 1から10までの整数の総乗(1×2×3×・・・×9×10)を求めたいと思い、以下のプログラムex5-6.cを作成しました。しかし、正しい結果が得られませんでした。間違いを修正して、正しい結果を求めなさい。
  12. ex5-6.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i, prod=0;
    	
    	for (i=1; i<=10; i++) {
    		prod = prod * i;
    	}
    	printf("1から10までの総乗 %d\n", prod);
    	
    	return 0;
    }
    

  13. 以下の実行結果のように、正方形の一辺の長さを入力して、文字*を使って図形を描くプログラムです。空欄を埋めて完成させなさい。
  14. 辺の長さ>> 5 ***** ***** ***** ***** *****
    ex5-7.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i,j, len;
    
    	printf("辺の長さ>> ");
    	scanf("%d", &len);
    
    	for (i=0; [[空欄ア]]; i++) {
    		for (j=0; [[空欄イ]]; j++) {
    			putchar('*');
    		}
    		printf("\n");
    	}
    	
    	return 0;
    }
    

  15. 以下の実行結果のように、長方形の幅と高さを入力して、文字*を使って図形を描くプログラムです。空欄を埋めて完成させなさい。
  16. 幅>> 5 高さ>> 3 ***** ***** *****
    ex5-8.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i,j,width,height;
    
    	printf("幅>> ");
    	scanf("%d", &width);
    	printf("高さ>> ");
    	scanf("%d", &height);
    
    	for(i=0; [[空欄ア]]; i++){
    		for(j=0; [[空欄イ]]; j++){
    			putchar('*');
    		}
    		printf("\n");
    	}
    	return 0;
    }
    

  17. 以下の実行結果のように、段数を入力して、文字*を使って左下直角三角形を描くプログラムです。空欄を埋めて完成させなさい。
  18. 段数>> 5 * ** *** **** *****
    ex5-9.c
    #include <stdio.h>
    
    int main(void)
    {
    	int i,j,step;
    
    	printf("段数>> ");
    	scanf("%d", &step);
    
    	for(i=1; [[空欄ア]]; i++){
    		for(j=1; [[空欄イ]]; j++){		//段数と同じ個数
    			putchar('*');
    		}
    		printf("\n");
    	}
    	return 0;
    }
    

  19. 以下の実行結果のように、段数を入力して、文字*を使って左上直角三角形を描くプログラムex5-10.cを作成しなさい。
  20. 段数>> 5 ***** **** *** ** *

  21. 以下の実行結果のように、段数を入力して、文字*を使って右下直角三角形を描くプログラムex5-11.cを作成しなさい。
  22. ex5-11

  23. 以下の実行結果のように、段数を入力して、文字*を使って右上直角三角形を描くプログラムex5-12.cを作成しなさい。
  24. ex5-12

  25. 以下の実行結果のように、段数を入力して、文字*を使って二等辺三角形を描くプログラムを作成しなさい。
  26. ex5-13

  27. 以下の実行結果のように、段数と個数を入力して、文字*を使って左下直角三角形を個数分縦に並べて描くプログラムを作成しなさい。
  28. 段数>> 5 個数>> 3 * ** *** **** ***** * ** *** **** ***** * ** *** **** *****

  29. 以下の実行結果のように、段数と個数を入力して、文字*を使って右下直角三角形を個数分横に並べて描くプログラムを作成しなさい。
  30. ex5-15

  31. 以下の実行結果のように、幅と高さを入力して、0から9までの数字を使って長方形を描くプログラムex5-16.cを作成しなさい。
  32. 幅>> 7 高さ>> 3 0123456 7890123 4567890

  33. 以下の実行結果のように、正の整数nを入力して、その階乗値(n!)を求めるプログラムex5-17.cを完成させなさい。
  34. 正の整数>> 6 6! = 6 × 5 × 4 × 3 × 2 × 1 = 720

  35. 1から9までのそれぞれの階乗値(1!から9!)を求めるプログラムex5-18.cを作成しなさい。


演習問題解答

OPEN ANSWER
  1. ア. i=1 イ. i<=100 ウ. i++

  2. ア. sum=0 イ. i<=10 ウ. &score  エ. sum += score または sum = sum + score オ. (double)sum/10

  3. ア. i=1 イ. i<=100 ウ. i += 2

  4. ア. i<=9 イ. i++ ウ. j<=9 エ. j++ オ. i*j カ. "\n"

  5. ア. i>0 イ. i-- ウ. i%3==0 && i%5==0

  6. 変数の初期化 prod=0 を、prod=1 に修正する。for文の初期値 i=1をi=2にする。

  7. ア. i<len イ. j<len

  8. ア. i<height イ. j<width

  9. ア. i<=step イ. j<=i

  10. 回答例
  11. code/5/ex5-10.c

  12. 回答例
  13. code/5/ex5-11.c

  14. 回答例
  15. code/5/ex5-12.c

  16. 回答例
  17. code/5/ex5-13.c

  18. 回答例
  19. code/5/ex5-14.c

  20. 回答例
  21. code/5/ex5-15.c

  22. 回答例
  23. code/5/ex5-16.c

  24. 回答例
  25. code/5/ex5-17.c

  26. 回答例
  27. code/5/ex5-18.c

expand_lessBack to TOP

確認テスト1

確認テスト2
次の各式の計算を行うプログラムを作成しなさい。
  1. \[n! = 1 \times 2 \times 3 \times \dots \times n\]
  2. \[S = \sum_{k=1}^{n} \frac{1}{k} = 1 + \frac{1}{2} + \frac{1}{3} + \dots + \frac{1}{n}\]
  3. \[S = \sum_{k=1}^{n} \frac{1}{k} = 1 - \frac{1}{2} + \frac{1}{3} - \frac{1}{4} + \dots + \pm\frac{1}{n}\]
  4. \[S = \sum_{k=1}^{n} \frac{1}{k^2} = \frac{1}{1^2} + \frac{1}{2^2} + \frac{1}{3^2} + \dots + \frac{1}{n^2}\]
  5. \[S = \sum_{k=1}^{n} 2^k = 2^1 + 2^2 + 2^3 + \dots + 2^n\]

本日の提出課題

以下の各プログラムを作成しなさい。ただし、いずれのプログラムもfor文を利用して実現すること。
  • 課題1
  • 2つの正の整数を入力して、その最大公約数を表示するプログラム。

  • 課題2
  • 2進数を入力して10進数に変換した結果を表示するプログラム。ただし、2進数は0と1からなる10進数として扱うものとします。負数についても考慮しなくてよいとします。

  • 課題3
  • 正の整数nを入力して、因数分解するプログラム
      (表示例) 168 = 2 x 2 x 2 x 3 x 7

  • 課題4
  • 正の整数nを入力して、整数の立方根があればその値を表示し、なければ整数の立方根はありませんと表示するプログラム
     (表示例)27の立方根は3です

  • 課題5
  • 段数を入力して、以下のように記号#を使って文字Xを描くプログラム。ただし、段数は3以上を入力するものとする。
    段数5の場合
    #   #
     # # 
      #  
     # # 
    #   #
    				
    段数6の場合
    #    #
     #  # 
      ##  
      ##  
     #  # 
    #    #
    				

    2桁の整数のうち、1桁目の数が5以上となる素数の合計値を表示するプログラムkadai5.cを作成しなさい。

    • [提出方法]
      1. ideone.comを利用して作成した課題プログラムのURLをCoursePowerへ提出のこと。
      2. 適切な実行結果を含むこと
      3. 詳細はスライド「ideoneの使い方」参照のこと。

    • [評価について]
    • プログラムの内容の評価とは別に以下の要件を満たすことを評価の前提とする。
      1. C言語で記述されていること。
      2. ソースコードファイルのコンパイル結果に、ワーニングやエラーが出力されていないこと。
      3. 所定の実行結果が得られるていること。
      4. ソースコードは、インデントや適当な改行が施された見やすい状態であること。

    • [提出期限]
    • 2023年 5月22日(月)までとする。ただし、以降の提出も受け付ける。