Ex05Ans
From Prog0
演習第5回
Contents |
解答例
A問題
A-1 while文
ファイル名: ex05a1.c
#include <stdio.h> int main() { int sum = 0; int i = 1; while (i <= 100) { sum += i; i++; } printf("sum = %d\n", sum); return 0; }
A-2 インクリメント・デクリメント
ファイル名: ex05a2.txt
最初の"3"は、前置インクリメントによって出力よりも前にiに1が足されるため、3が出力される。 2番目の"3"は、後置インクリメントによって出力の後にiに1が足されるため、3が出力される。出力後のiの値は4である。 3番目の"3"は、前置デクリメントによって出力よりも前にiから1が引かれるため、3が出力される。 最後の"3"は、後置デクリメントによって出力の後にiから1が引かれるため、3が出力される。出力後のiの値は2である。
A-3 複雑なif文
ファイル名: ex05a3.txt
lec05-1.c(間違いのプログラム)では、if-elseの対応が合っていない。 どのように合っていないかというと… 1,3,5,7,8,10,12月の場合、月の最後の日でない日付が入力された際に、 さらに「4,6,9,11月ならば」というif文の処理に移るのみであり、これだと月の条件が矛盾するため、 何の出力処理も行わないままプログラムを終了してしまう。 (1,3,5,7,8,10,12月で、各月最後の日でない日付が入力された際に該当する分岐処理が用意されていない。) また、他の月(2,4,6,9,11月)の日付が入力された場合も同様に、該当する分岐が存在せず、 何の出力処理も行わずにプログラムを終了してしまう。 結局このプログラムは、1,3,5,7,8,10,12月の31日だけしか正しく判定しない。 <参考> 正しく動作しないのはどんな場合か: 1,3,5,7,8,10,12月で、月末(31日)以外の日付が入力された場合と、 2,4,6,9,11月の日付(月末でもそれ以外の日でも)が入力された場合 上記の入力例の場合、プログラム中の16-17行目の条件分岐以降、どの行に実行が移っていくか (いずれか一つ答えればよい) 小の月(4/30等)の場合:16-17行目のif文が偽となるので、24行目に飛んで終了。 大の月で月末以外(5/30等)の場合:16-17行目のif文が真となるので18行目に進み、 そのif文は偽となるので19行目に進み、そのif文も偽と判定されて、24行目に飛んで終了。 同じ入力例で、修正後のプログラムの場合は16-17行目の条件分岐以降、どの行に実行が移っていくか (いずれか一つ答えればよい) 小の月で月末(4/30等)の場合:16-17行目のif文は偽となるので19行目に進み、そのelse-if文で真となるため、 20行目のprintfで「月の最後の日」と表示され、25行目に飛んで終了。 大の月で月末以外(5/30等)の場合:16-17行目のif文は偽となり、19行目のelse-if文に進むがここも偽なので21行目に進み、 そこのelse-if文も偽となるので、23行目のprintfで「月の最後の日ではない」と表示され、25行目で終了。 小の月で月末以外(4/1等)の場合:5/30等と同じ それぞれに対応するフローチャートは以下のようになります (作成: 松川さん)
B問題
B-1 無限ループ
ファイル名: ex05b1.c
#include <stdio.h> int main() { int input; int count = 0; while(1) { printf("偶数は%d回入力されています。正の整数を入力して下さい ", count); scanf("%d", &input); if(input%2 == 0){ count++; } if(count == 2) break; } printf("偶数が2回入力されました。プログラムを終了します\n"); return 0; }
B-2 温度計の目盛り
ファイル名: ex05b2.c
#include <stdio.h> int main() { int min, max, deg; printf("最低温度? "); scanf("%d", &min); printf("最高温度? "); scanf("%d", &max); /* 数字を表示 */ deg = min; while (deg <= max) { printf("%3d ", deg); // 空白を加えて4文字幅で表示 deg += 10; } printf("\n"); /* 線を表示 */ deg = min; while (deg <= max) { printf("--+-"); // 数字に合わせて4文字 deg += 10; } printf("\n"); return 0; }
B-3 試験結果の集計
ファイル名: ex05b3.c
#include <stdio.h> int main() { int student = 0; // 受験者数 int pass = 0, fail = 0; // pass:合格者数、fail:不合格者数 int score, total_score = 0; // score:得点、total_score:得点の合計 double average; while(1) { printf("得点を入力して下さい: "); scanf("%d", &score); if (score < 0) break; student++; total_score += score; if (score >= 50 ) pass++; else fail++; } average = (double) total_score / student; printf("受験者数 %d 名,平均点は %f 点\n", student, average); printf("合格者数 %d 名,不合格者数 %d 名\n", pass, fail); return 0; }
B-4 曜日の計算
ファイル名: ex05b4.c
#include <stdio.h> int main() { int i; int m, d; int days; printf("月と日を空白で区切って入力してください:"); scanf("%d %d", &m, &d); days = d; i = 1; while (i < m) { if (i == 2) { days += 28; } else if ((i == 1) || (i == 3) || (i == 5) || (i == 7) || (i == 8) || (i == 10) || (i == 12)) { days += 31; } else { days += 30; } i++; } printf("2023年%d月%d日は%d日目で", m, d, days); switch (days % 7) { case 0: printf("土"); break; case 1: printf("日"); break; case 2: printf("月"); break; case 3: printf("火"); break; case 4: printf("水"); break; case 5: printf("木"); break; case 6: printf("金"); break; } printf("曜日です\n"); return 0; }
Extra問題
E-1 ユークリッドの互除法
ファイル名: ex05e1.c
#include <stdio.h> int main() { int m, n, new_n; printf("m nを入力して下さい:"); scanf("%d%d", &m, &n); while(n != 0) { new_n = m%n; printf("%d %% %d = %d\n", m, n, new_n); m = n; n = new_n; } printf("最大公約数は %d です\n", m); return 0; }