Download presentation
Presentation is loading. Please wait.
1
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
C言語入門 第4週 プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
2
Visual Studio Code https://code.visualstudio.com/
News Visual Studio Code Microsoft 製プログラミング用テキストエディタ にリリースされたばかりのテキストエディタ。Windows 以外にも Mac, Linux 用もある。
3
条件分岐と繰り返し 制御構造
4
流れ図(フローチャート) プログラムの処理の流れを図示する方法 教科書 pp.112-116. プログラムの開始と終了 画面等への出力
端子 プログラムの開始と終了 表示 画面等への出力 代入や演算等 各ステップにおける処理 処理 手操作入力 キーボード等からの入力 定義済み処理 サブルーチンや関数等 各部品を矢印で繋ぐ事で処理の流れを視覚的に表現する。 各部品の内部にはそれぞれのステップで行う内容に書き換えて使う。 条件分岐 処理の振り分け 結合子 別のフローチャートと結合 追加
5
if 文と switch 文 条件分岐
6
条件分岐 (if 文) 真偽値による場合分け if (条件式1) { // 条件式1が真の場合の処理1 } 教科書 pp.130-133.
7
条件分岐 (if, else 文) 真偽値による場合分け if (条件式1) { // 条件式1が真の場合の処理1 } else {
教科書 pp 条件分岐 (if, else 文) 真偽値による場合分け 条件式1 真 偽 if (条件式1) { // 条件式1が真の場合の処理1 } else { // 条件式1が偽の場合の処理2 } 処理1 処理2 if, else 文を使うと特定の条件下で別の処理を指定出来る。
8
入れ子の条件分岐 (if, else 文) 真偽値による場合分け if (条件式1) { if (条件式2) { // 条件式1が真かつ
教科書 pp 入れ子の条件分岐 (if, else 文) 修正 誤:処理2,3,1 正:処理1,2,3 真偽値による場合分け 条件式1 真 偽 if (条件式1) { if (条件式2) { // 条件式1が真かつ // 条件式2が真の場合の処理1 } else { // 条件式2が偽の場合の処理2 } // 条件式1が偽の場合の処理3 条件式2 真 偽 処理3 処理1 処理2 if, else 文は任意の数入れ子に出来る。 だだし、入れ子が深くなると読み難くなるので注意。
9
入れ子の条件分岐 (if, else 文) 真偽値による場合分け if (条件式1) { // 条件式1が真の場合の処理1 } else {
教科書 pp 入れ子の条件分岐 (if, else 文) 真偽値による場合分け 条件式1 真 偽 if (条件式1) { // 条件式1が真の場合の処理1 } else { if (条件式2) { // 条件式1が偽かつ // 条件式2が真の場合の処理2 // 条件式2が偽の場合の処理3 } 条件式2 処理1 真 偽 処理2 処理3 if, else 文は任意の数入れ子に出来る。 else 側の if は else if で置き換ると入れ子を防げる。
10
複数条件の条件分岐 (if, else if, else 文)
教科書 pp 複数条件の条件分岐 (if, else if, else 文) 真偽値による場合分け 条件式1 真 偽 if (条件式1) { // 条件式1が真の場合の処理1 } else if (条件式2) { // 条件式1が偽かつ // 条件式2が真の場合の処理2 } else { // 条件式2が偽の場合の処理3 } 条件式2 処理1 真 偽 処理2 処理3 else if は任意の数追加出来る。 入れ子を作らずに複数の条件を追加出来る。
11
多分岐判断機構 (switch 文) 値による場合分け switch (式) { case 値1: // 式が値1の場合の処理1
教科書 pp 多分岐判断機構 (switch 文) 値による場合分け 式 switch (式) { case 値1: // 式が値1の場合の処理1 case 値2: // 式が値2の場合の処理2 default: // 他の条件に // 当てはまらない場合の処理N }; 値1 処理1 break 値2 処理2 break default 処理N break break 文を入れておかないと 次の条件の処理を 連続して実行するので注意。
12
条件分岐の例題 平方根の計算
13
sqrt 関数 書式: 引数: 戻り値: #include <math.h> double sqrt(double x);
0≤𝑥 の場合 𝑥 を返す。 0≤𝑥 でない場合は処理系依存? x が負なら、nan (=非数) を返し、グローバル変数 errno に EDOM を代入する(errno は errno.h を include すると参照出来る)。 x が 0 なら 0 を、inf (=∞) なら inf を返す。 x が nan なら nan を返す。
14
平方根の計算 sqrt() 関数は引数が負の場合計算出来ない。 1 2 3 4 5 6 7 8 9 10 11
sqrt_practice_1.c 1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <math.h> void main() { double x; fprintf(stderr, "x = ?\b"); scanf("%lf", &x); printf("x: %f\n", x); printf("sqrt(x): %f\n", sqrt(x)); } mintty+bash+gcc $ gcc sqrt_practice_1.c && ./a x = 2 x: sqrt(x): $ ./a x = -2 x: sqrt(x): nan
15
演習: 平方根の計算(if文) sqrt_practice_1.c を参考に 0≤𝑥 の場合は実数の平方根 𝑥 を、 𝑥<0 の場合は虚数の平方根 −𝑥 𝑖 を if 文で場合分けして表示する sqrt_practice_if.c を完成させよ。虚数は数値の後に i を表示する事で表現すれば良い。 例えば x=-2 の場合は以下のようになる。 mintty+bash+gcc $ gcc sqrt_practice_if.c && ./a x = -2 x: sqrt(x): i
16
演習: 平方根の計算(if文) ヒント sqrt_practice_1.c の 10 行目は 𝑥 を表示している。これを if 文で場合分けしてやれば良い。 sqrt_practice_1.c 𝑥 10 printf("sqrt(x): %f\n", sqrt(x)); sqrt_practice_if.c 条件式 真 偽 10 11 12 13 14 if (条件式) { // 𝑥 を表示 } else { // −𝑥 と 𝑖 を表示 } 𝑥 −𝑥 𝑖
17
条件演算子 三項演算子(?:) 書式: 条件式 ? 式1 : 式2 [1] pp.63-66, 256-257. 1 2 3 4 5 6 7
真 偽 書式: 条件式 ? 式1 : 式2 式1 式2 condexprtest.c mintty+bash+gcc 1 2 3 4 5 6 7 8 9 #include <stdio.h> void main() { int i; fprintf(stderr, "i = ?\b"); scanf("%d", &i); printf("%s\n", i ? "not zero" : "zero"); } $ gcc condexprtest.c && ./a i = 1 not zero $ ./a i = 0 zero
18
演習: 平方根の計算(条件演算子) 先程の負の数の平方根の計算を条件演算子を用いて解決してみよう。
10行目の printf では 2 つ目の引数が %f に 3 つ目の引数が %s へ埋め込まれる。 sqrt_practice_condexpr.c 6 7 8 9 10 double x; fprintf(stderr, "x = ?\b"); scanf("%lf", &x); printf("x: %f\n", x); printf("sqrt(x): %f%s\n", sqrt(/*WYCH*/), /*WYCH*/);
19
追加 条件分岐の例題 奇数と偶数の判定
20
奇数と偶数 整数のうち 2 で割り切れるのが偶数、2 で割り切れないのが奇数 2 で割り切れるとは? 2 で割り切れないとは
整数を 2 で割った余り(剰余)が 0 2 で割り切れないとは 整数を 2 で割った余り(剰余)が 0 以外
21
C言語の剰余 剰余は二項演算子 % 同じかどうか比較するのは二項演算子 == や != i % 2 で 2 で割った余りが求まる
i % 2 == 0 は i を 2 で割った余りが 0 なら真、それ以外は偽 i % 2 != 0 は i を 2 で割った余りが 0 以外なら真、それ以外は偽 i % 2 != 0 は単項演算子 ! を用いて !(i % 2 == 0) としても同じ意味になる
22
演算子の優先度 優先度 高 低 [1] p.65. より 演算子 結合規則 備考 ( ) [ ] -> . 左から右→
( ) [ ] -> . 左から右→ ! ~ * & (type) sizeof 右から左← 単項演算子 * / % 二項演算子 + - << >> bitシフト < <= > >= 関係演算子 == != 等値演算子 & bit毎のAND ^ bit毎のXOR | bit毎のOR && 論理演算子(AND) || 論理演算子(OR) ?: 三項演算子 = += -= *= /= %= &= ^= |= <<= >>= 代入演算子 , 低 [1] p.65. より
23
演習: 偶数かどうか判定する 標準入力から入力された整数値が奇数かどうか判別して、奇数であれば入力された数値に続けて " is even number\n" そうでなければ " is not even number\n" と表示するプログラムを作成せよ。奇数でない場合は何も表示しなくて良い。 if_practice_even.c の /*WYCH*/ の個所を修正すれば良い。
24
演習: 奇数かどうか判定する 標準入力から入力された整数値が奇数かどうか判別して、奇数であれば入力された数値に続けて " is odd number\n" そうでなければ " is not odd number\n" と表示するプログラムを作成せよ。奇数でない場合は何も表示しなくて良い。 if_practice_odd.c の /*WYCH*/ の個所を修正すれば良い。
25
演習: 奇数か偶数か判定する 標準入力から入力された整数値が奇数かどうか判別して、奇数であれば入力された数値に続けて " is odd number\n"、偶数であれば入力された数値に続けて "is even number\n" と表示するプログラムを作成せよ。 if_practice_evenodd.c の /*WYCH*/ の個所を修正すれば良い。
26
入れ子の条件分岐の例題 閏年の判定
27
閏年(leap year)とは 地球の平均回帰年は365日+約1/4日であるため1年を356日にしているとカレンダー上の日付と季節が4年で1日ずつずれてしまう。これを防ぐのが4年に1回設ける2月29日(閏日)。 閏年の求め方 西暦を4で割り切れるなら閏年? 閏年 判定式 真 偽 閏年 平年
28
閏年(leap year)の判定 4で割り切れる(割れる)とは? C言語では0は偽、0以外は真だったから 4で割った余りが0ということ
% : 剰余算演算子 4で割り切れる(割れる)とは? 4で割った余りが0ということ 4で割り切れる : year % 4 == 0 4で割り切れない : year % 4 != 0 C言語では0は偽、0以外は真だったから 以下のようにも書けるが・・・ 4で割り切れる : !(year % 4) 4で割り切れない : (year % 4) 等値演算子 == : 等しい != : 等しくない ! : 論理否定演算子 ぱっと見て意味の分かり易い書き方をしましょう
29
演算子の優先度 優先度 高 低 [1] p.65. より 演算子 結合規則 備考 ( ) [ ] -> . 左から右→
( ) [ ] -> . 左から右→ ! ~ * & (type) sizeof 右から左← 単項演算子 * / % 二項演算子 + - << >> bitシフト < <= > >= 関係演算子 == != 等値演算子 & bit毎のAND ^ bit毎のXOR | bit毎のOR && 論理演算子(AND) || 論理演算子(OR) ?: 三項演算子 = += -= *= /= %= &= ^= |= <<= >>= 代入演算子 , 低 [1] p.65. より
30
演習: 4 で割り切れるか表示する leap_year_practice_1.c の /*WYCH*/ を書き換えて、year が 4 で割り切れる場合 "can be divided by 4."、割り切れない場合 "can not be divided by 4." と表示するプログラムを完成せよ。 修正 誤:dividec 正:divided mintty+bash+gcc $ gcc leap_year_practice_1.c && ./a year = 2015 2015 can not be divided by 4. $ ./a year = 2016 2016 can be divided by 4.
31
閏年(leap year)の定義 グレゴリオ暦における閏年の定義
判定したい年を西暦で表した際 4で割り切れる場合は閏年 (条件1) 但し100で割り切れる場合は平年 (条件2) 但し400で割り切れる場合は閏年 (条件3) 地球の平均回帰年は約 日であるため、上記ルールだと約3320年で1日ずれる程度で済む。
32
閏年(leap year)の判定 4で 割れる 条件1 真 偽 閏年 平年
33
閏年(leap year)の判定 4で 割れる 条件1 +条件2 真 偽 100で 割れる 平年 真 偽 平年 閏年
34
閏年(leap year)の判定 4で 割れる 条件1 +条件2 +条件3 真 偽 100で 割れる 平年 真 偽 完成 400で 割れる
35
演習: 閏年(leap year)の判定 leap_year_practice_2.c の /*WYCH*/ の部分を書き換えて閏年か判定するプログラムを完成せよ。 /*WYCH*/ の部分には year に格納された西暦が閏年であれば変数 leap_year_flag に 1 を閏年でなければ 0 を代入するコード作成すれば良い。これは前のページのフローチャートを参考に if 文を 3 重の入れ子にすれば出来る。 なおここでは紀元前については考慮する必要はない。
36
演習: 閏年(leap year)の判定 ヒント1 前述の条件1~3のフローチャートをif,else文で書くと以下のようになる。 条件1
条件1+条件2 条件1+条件2+条件3 if (/*条件1*/) { /*閏年*/ } else { /*平年*/ } if (/*条件1*/) { if (/*条件2*/) { /*平年*/ } else { /*閏年*/ } if (/*条件1*/) { if (/*条件2*/) { /*条件3のif,else文*/ } else { /*閏年*/ } /*平年*/
37
演習: 閏年(leap year)の判定 ヒント2 閏年なら leap_year_flag に 1 そうでなければ 0 を代入すれば良い。
条件1 if (/*条件1*/) { leap_year_flag = 1; /*閏年*/ } else { /*平年*/ }
38
多分岐の例題 月の名前
39
演習: 月の名前の表示 monthname_practice_1.c の /*WYCH*/ の部分を変更し、入力した月 month に対応する英語の月名(January, February, March, April, June, July, August, September, October, November, December )を表示せよ。 mintty+bash+gcc $ gcc monthname_practice_1.c && ./a month = 1 January
40
for文, while文, do-while 文によるループと continue 文、break 文によるループの再開と脱出
繰り返し(ループ)
41
ループの再開と脱出 continue 文 break 文 while, do while, for 文内で使用可能
以降の処理を中断してループ末尾から再開する for文では後処理(第3パラメータ)も実行する break 文 while, do while, for, switch 文内で使用可能 以降の処理を中断してループを脱出する switch文の場合はswitch文から脱出する
42
後判定ループ (do while 文) 真偽値による繰り返し do { // 条件式 が真の場合の処理 } while (条件式);
教科書 p.123. 後判定ループ (do while 文) 真偽値による繰り返し continue break 処理 do { // 条件式 が真の場合の処理 } while (条件式); 条件式 真 偽 do while 文は、ループ内の処理を 1回以上実行する(=最低1回は実行する)。
43
前判定ループ (while 文) 真偽値による繰り返し while (条件式) { // 条件式が真の場合の処理 }
教科書 pp 前判定ループ (while 文) 修正 誤:式2 正:条件式 真偽値による繰り返し while (条件式) { // 条件式が真の場合の処理 } 条件式 偽 真 continue break 処理 while 文は、ループ内の処理を 0回以上実行する(=実行しない場合もある) 。
44
初期化・更新処理付きループ (for 文) 真偽値による繰り返し for (式1; 式2; 式3) { // 式2が真の場合の処理 };
教科書 pp 初期化・更新処理付きループ (for 文) 真偽値による繰り返し 式1 for (式1; 式2; 式3) { // 式2が真の場合の処理 }; 式2 偽 真 continue break 処理 式3 for 分は前判定ループで 式1による初期化と 式3による更新処理を ひとまとめにしてコンパクトに書ける。
45
for文とwhile文 (前判定ループ) 以下のループは等価 ただしcontinue時の式3の扱いに注意
教科書 pp for文とwhile文 (前判定ループ) 以下のループは等価 ただしcontinue時の式3の扱いに注意 式1 式2 偽 for (式1; 式2; 式3) { // 式2が真の場合の処理 }; 真 break for文の continue 処理 式1; while (式2) { // 式2が真の場合の処理 式3; }; while文の continue 式3
46
for文とwhile文 (前判定ループ) 以下のループは等価 continue時の式3の扱いに注意
教科書 pp for文とwhile文 (前判定ループ) 以下のループは等価 continue時の式3の扱いに注意 i = 0 i < 10 偽 for (i = 0; i < 10; i++) { // ループ内の処理 }; 真 break for文の continue 処理 i = 0; while (i < 10) { // ループ内の処理 i++; }; while文の continue i++
47
後判定ループ (do while 文) continue, break 後の処理(iの値)に注目 教科書 pp.119-122.
looptest_dowhile.c mintty + bash int i = 0, j = 0, n; fprintf(stderr, "n = "); scanf("%d", &n); do { j++; printf("%d, %d: 1st", i, j); if (j == 2) {printf(" continue\n"); continue;} printf(" 2nd"); if (j == 4) {printf(" break\n"); break;} printf(" 3rd\n"); i++; } while (i < n); $ ./looptest_dowhile n = 10 0, 1: 1st 2nd 3rd 1, 2: 1st continue 1, 3: 1st 2nd 3rd 2, 4: 1st 2nd break mintty + bash $ ./looptest_dowhile n = 0 0, 1: 1st 2nd 3rd do while 文は、 ループ内の処理を 最低1回は実行する。
48
前判定ループ (while 文) continue, break 後の処理(iの値)に注目 教科書 p.123.
looptest_while.c mintty + bash int i = 0, j = 0, n; fprintf(stderr, "n = "); scanf("%d", &n); while (i < n) { j++; printf("%d, %d: 1st", i, j); if (j == 2) {printf(" continue\n"); continue;} printf(" 2nd"); if (j == 4) {printf(" break\n"); break;} printf(" 3rd\n"); i++; } $ ./looptest_while n = 10 0, 1: 1st 2nd 3rd 1, 2: 1st continue 1, 3: 1st 2nd 3rd 2, 4: 1st 2nd break mintty + bash $ ./looptest_while n = 0
49
初期化・更新処理付きループ (for 文) continue, break 後の処理(iの値)に注目 教科書 pp.124-129.
looptest_for.c mintty + bash int i = 0, j = 0, n; fprintf(stderr, "n = "); scanf("%d", &n); for (i = 0; i < n; i++) { j++; printf("%d, %d: 1st", i, j); if (j == 2) {printf(" continue\n"); continue;} printf(" 2nd"); if (j == 4) {printf(" break\n"); break;} printf(" 3rd\n"); } $ ./looptest_for n = 10 0, 1: 1st 2nd 3rd 1, 2: 1st continue 2, 3: 1st 2nd 3rd 3, 4: 1st 2nd break mintty + bash $ ./looptest_for n = 0
50
continue 文 以下のループ内に更に小さなループが含まれない場合の continue は goto contin と同義
[1] p.281. continue 文 以下のループ内に更に小さなループが含まれない場合の continue は goto contin と同義 for (...) { // ... contin: ; } do { // ... contin: ; } while (...); while (...) { // ... contin: ; }
51
goto文 指定した名札付き文へ移動(ジャンプ)する 名札(label)は以下のように設定出来る ラベル名: 文 [1] p.281.
余程理由がない限り使わないこと do while 文相当 while 文相当 for 文相当 loop: ; { // something to do contin: ; } if (expr) goto loop; brk: ; loop: ; if (expr) { // something to do contin: ; goto loop; } brk: ; expr1; loop: ; if (expr2) { // something to do contin: ; expr3; goto loop; } brk: ;
52
追加 前判定ループの演習 簡易版 seq コマンドの作成
53
seq コマンド UNIX系のOSに標準で搭載されているコマンド 書式: 機能: seq FIRST LAST
他にも詳細な機能があるが、ここでは省略 JM / seq (1)
54
演習: while 文による簡易 seq コマンド
seq_practice_1_while.c の /*WYCH*/ の部分を修正して以下のプログラムを完成させよ。 標準入力から int 型の変数 first, last に整数値を読み取り、first 以上、last 以下の整数を1刻みで小さい順に表示せよ。 mintty + bash $ gcc seq_practice_1_while.c && ./a first = 5 last = 9 5 6 7 8 9
55
演習: for 文による簡易 seq コマンド seq_practice_1_for.c の /*WYCH*/ の部分を修正して以下のプログラムを完成させよ。 標準入力から int 型の変数 first, last に整数値を読み取り、first 以上、last 以下の整数を1刻みで小さい順に表示せよ。 mintty + bash $ gcc seq_practice_1_for.c && ./a first = 5 last = 9 5 6 7 8 9
56
追加 条件分岐とループの例題 素数判定
57
素数 1と自分以外に正の約数を持たない自然数(正整数)で1でない数
調べたい数をiとすると、2以上i/2以下の整数jの全てについてiが割り切れないことを確認すれば良い。 ※厳密には2以上 𝑖 以下の整数jについて調べれば良いが、平方根の計算は除算に比べかなり遅いのでここではi/2以下について確認する。
58
演習: 素数判定 標準入力から入力された正整数が素数かどうか判定するプログラムを作成せよ。
isprime_practice_1.c の /*WYCH*/ の箇所を修正すれば良い。 mintty + bash $ gcc is_prime_practice_1.c $ ./a i = 1 1 is not prime number i = 2 2 is prime number i = 3 3 is prime number i = 4 4 is not prime number
59
演習: 素数判定(ヒント) 作成すべきプログラムの素数判定部分のフローチャートは以下の通りである 素数判定部分
1 iは2以上 jを2からi/2の範囲で繰り返し 偽 真 素数と仮定 非素数 iがjで 割切れる 真 1 偽 非素数 break j++
60
参考文献 [1] B.W.カーニハン/D.M.リッチー著 石田晴久 訳、プログラミング言語C 第2版 ANSI 規格準拠、共立出版(1989)
Similar presentations
© 2025 slidesplayer.net Inc.
All rights reserved.