340 likes | 508 Views
プログラミング講義資料 ブロック 2:1 回目. 情報科学科. for 文. for 文 for( 初期文 ; 条件 ; 補助文 ) { 手順 1; }. 初期文. 判断の前に 戻って来る. for 文は、 繰り返しに入る前に初期文を実行。 条件を判断してから、 成り立てば手順 1 と補助文を実行し 判断の前に戻る。 不成立なら繰り返しから脱出する. 条件. No. Yes. 手順 1. 補助文. 初期文 ; 条件 ; 補助文 がそろわない 時には while 文を使う方がよい. 初期文. 補助文. 条件. 手順1.
E N D
プログラミング講義資料ブロック2:1回目 情報科学科
for文 • for文for(初期文;条件;補助文) {手順1;} 初期文 判断の前に 戻って来る for文は、繰り返しに入る前に初期文を実行。 条件を判断してから、 成り立てば手順1と補助文を実行し 判断の前に戻る。 不成立なら繰り返しから脱出する 条件 No Yes 手順1 補助文 初期文;条件;補助文がそろわない 時にはwhile文を使う方がよい
初期文 補助文 条件 手順1 コンパイルの前に、MAXPAGEは10に置き換えられるものとする for文の用例 #include <stdio.h> #define MAXPAGE 10 main(void) { int page; /* ページ番号 */ for (page = 1; page <= MAXPAGE; page = page + 1) { printf("- %d -\n", page); printf("\n"); } return 0; } page=1から始め、1ずつ増やしながら、 -(page) - を表示。pageが10の時に最終回の実行。その後、pageが11になって最初に戻ったところでループを抜ける
初期文に相当 条件 補助文に相当 同じ機能のwhile文 #include <stdio.h> #define MAXPAGE 10 int main(void) { int page; /* ページ番号 */ page = 1; while (page <= MAXPAGE) { printf("- %d -\n", page); printf("\n"); page = page + 1; } return 0; }
多重ループ #include <stdio.h>int main(void){int i, j;for (i = 1; i <= 9; i++) {for (j = 1; j <= 9; j++) {printf(“ %2d”, i * j);}printf(“\n”);}return 0;} for文 for文
i=1 初期文: i=1 初期文: j=1 i=<9 No Yes j=<9 for文 No Yes printf("\n"); printf(" %2d", i * j); 補助文: i++ 補助文: j++
i=1 1 2 3 10 j= 初期文: j=1 (1)1*1を印字 (2)1*2を印字 j=<9 No (3)1*3を印字 Yes (4)1*4を印字 (5)1*5を印字 printf(" %2d", i * j); (6)1*6を印字 (7)1*7を印字 補助文: j++ (8)1*8を印字 (9)1*9を印字 5 1 4 2 3 8 9 7 6
i=2 初期文: i=1 初期文: j=1 i=<9 No Yes i=1 j=<9 for文 No Yes printf("\n"); printf(" %2d", i * j); 補助文: i++ 補助文: j++
i=2 1~9 j= 初期文: j=1 (1)2*1を印字 j=<9 (2)2*2を印字 No (3)2*3を印字 Yes (4)2*4を印字 printf(" %2d", i * j); (5)2*5を印字 (6)2*6を印字 補助文: j++ (7)2*7を印字 (8)2*8を印字 (9)2*9を印字 5 1 4 2 3 8 9 7 6 10 2 8 4 6 16 18 14 12
インデント 文の埋め込み構造が基本 main関数は変数宣言文 for文 return文 の3文構成 #include <stdio.h>int main(void){int i, j;for (i = 1; i <= 9; i++) {for (j = 1; j <= 9; j++) {printf(“ %2d”, i * j);}printf(“\n”);}return 0;} for文の中に、for文printf文 が埋め込まれ for文の中に、printf文 が埋め込まれている
1次元配列(1) 4 0 2 3 0 1 0 桜 梅 桃 松 杉 楓 楡 桜の間に4人、桃の間に2人、松の間に3人、 楓の間に1人、梅の間、杉の間、楡の間には0人の 客が泊まっている。全部で何人? 桜+梅+桃+松+杉+楓+楡
1次元配列(2) room 4 0 2 3 0 1 0 0 1 2 3 4 5 6 0号室に4人、2号室に2人、3号室に3人、 5号室に1人、1号室、4号室、6号室には0人の 客が泊まっている。全部で何人? 6 Σroom i i=0
データ 型はint 配列名:配列roomはここから始まります。 添字 1次元配列(3) • 配列は同じ型の要素(データ)が並んでいるもの。 例: int room[7]; room 4 0 2 3 0 1 0 0 1 2 3 4 5 6 配列に含まれる要素(データ)は、配列名と添字で 識別(区別)される。
1次元配列を使ったプログラム例 room[0]からroom[6]までの7部屋 room[7]はない(不正) i は0から1ずつ加算され、 6まで customer=customer+room[i] が実行される。 その後で i が7になって最初に戻ったところでループを抜ける #include <stdio.h> int main(void) { char line[100]; int customer 0; /* 宿泊客数 */ int i, n; /* ループ変数 */ /* 部屋ごとの宿泊者数を入れる配列の宣言 */ int room[7]; /* 各部屋の宿泊者数を読み込む部分は省略 */ /* 各部屋の宿泊者数を足す */ for (i = 0; i < 7; i++) { customer = customer + room[i]; } /* 宿泊者数を表示する部分は省略 */ return 0; }
rank[0] 0点~9点 rank[1] 10点~19点 11個 rank[9] 90点~99点 rank[10] 100点 rank[11] ない(不正) i は0から1ずつ加算され、 10までrank[i]=0が実行 される。 i が11になって 最初に戻ったところで ループを抜ける 学生数を変数 students入力 n は1から1ずつ加算される。studentsと等しい数値の時に最後に実行が行われ、students+1になってループを抜ける #include <stdio.h> int main(void) { char line[100]; int students; /* 学生数 */ int score; /* 得点入力用の変数 */ int i, n; /* ループ変数 */ /* ランクごとの得点者数を入れる配列の宣言 */ int rank[11]; /* 各ランクの人数を 0 人にセット */ for (i = 0; i < 11; i++) { rank[i] = 0; } /* ここからメイン */ printf("何人ですか? "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &students); for (n = 1; n <= students; n++) { printf("%3d人め:\n", n); printf(" 何点ですか? "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &score); rank[score / 10]++; } for (i = 0; i < 11; i++) { printf("%3d点台: %3d人\n", i * 10, rank[i]); } return 0; } 例題: テストの点数を10点単位で分類し、その度数を表示するプログラム scoreがint型なので、score/10はint型で計算され、小数点以下は切り捨てられる。 scoreが5点だとrank[0]、 15点だとrank[1]が1増える
二次元配列 ここは room[1][3] 例: int room[3][7]; 型はint room 4 0 2 3 0 1 0 0段目 0 1 2 3 4 5 6 5 1 3 4 7 2 1 1段目 0 1 2 3 4 5 6 6 2 3 4 2 9 8 2段目 0 1 2 3 4 5 6
2教科分 0:英語、1:数学 #include <stdio.h> #define SUBJECTS 2 #define RANKS 11 int main(void) { char line[100]; int students; /* 学生数 */ int score; /* 得点入力用の変数 */ int i, n; /* ループ変数 */ /* ランクごとの得点者数を入れる配列の宣言 */ int rank[SUBJECTS][RANKS]; /* 各科目,各ランクの人数を 0 人にセット */ for (i = 0; i < RANKS; i++) { rank[0][i] = 0; /* rank[0][??] = 英語 */ rank[1][i] = 0; /* rank[1][??] = 数学 */ } rank[0][0]~rank[0][10] ranl[1][0]~rank[1][10] の初期値を0にする
/* ここからメイン */ printf("何人ですか? "); fgets(line, sizeof(line), stdin); scanf(line, "%d", &students); for (n = 1; n <= students; n++) { printf("%3d人め:\n", n); printf(" [英語] 何点ですか? "); scanf("%d", &score); rank[0][score / 10]++; printf(" [数学] 何点ですか? "); scanf("%d", &score); rank[1][score / 10]++; } printf("[英語]\n"); for (i = 0; i < RANKS; i++) { printf("%3d点台: %3d人\n", i * 10, rank[0][i]); } printf("[数学]\n"); for (i = 0; i < RANKS; i++) { printf("%3d点台: %3d人\n", i * 10, rank[1][i]); } return 0; }
#include <stdio.h> int main(void) { char line[100]; int customer 0; /* 宿泊客数 */ int i, k; /* ループ変数 */ /* 部屋ごとの宿泊者数を入れる配列の宣言 */ int room[3][7]; /* 各部屋の宿泊者数を読み込む部分は省略 */ /* 各部屋の宿泊者数を足す */ for (i = 0; i < 3; i++) { for(k = 0; k<7; k++) { customer = customer + room[i][k]; } } /* 宿泊者数を表示する部分は省略 */ return 0; }
初期文: i=0 初期文: k=0 i<3 No Yes k<7 手順1 No Yes 補助文: i++ c=c+r[i][k] 補助文: k++
データ 型はchar 配列名:配列roomはここから始まります。 添字 文字列=文字の配列 • 配列は同じ型の要素(データ)が並んでいるもの。 例: char str[7]; str p e n 0 1 2 3 4 5 6 配列に含まれる要素(データ)は、配列名と添字で 識別(区別)される。
それでは、”notePC”が保持されている文字列に、 ”pen”を上書きしたら? 例: char str[7]; str n o t e P C 0 1 2 3 4 5 6
それでは、”notePC”が保持されている文字列に、 ”pen”を上書きしたら? 例: char str[7]; str p e n e P C 0 1 2 3 4 5 6 penePC どうしよう!? 文字列の最後に”¥0”という 特殊な文字を付け加える
str[0]=‘n’; str[1]=‘o’; str[2]=‘t’; str[3]=‘e’; str[4]=‘P’; str[5]=‘C’; str[6]=‘\0’; str ← “notePC” 例: char str[7]; str n o t e P C \0 0 1 2 3 4 5 6
str[0]=‘p’; str[1]=‘e’; str[2]=‘n’; str[3]=‘\0’; str ← “pen” 例: char str[7]; str p e n \0 P C \0 0 1 2 3 4 5 6 pen (¥0 の後は無視される) 文字列の最後に”¥0”という 特殊な文字を付け加える
文字 型はchar 配列名: 文字列strはここから始まります。 文字列の最後は必ず'\0' 添字 文字列(まとめ) • 文字列は文字の要素(データ)が並んでいるもの。 例: char str[7]; str 'K' 'A' 'A' 'S' 'A' 'N' '\0' 0 1 2 3 4 5 6 配列に含まれる要素(データ)は、配列名と添字で 識別(区別)される。
文字列の定義と代入 • 宣言と同時に文字列を設定する場合 • ex. 変数宣言の部分でchar str[17]="0123456789ABCEDF";文字型配列 strの0~16番目に 0~F +'\0' (終端記号)が格納される。 • 配列を別の配列に代入することはできない! • だから、str = "abcd"; はできないので注意!! • 繰り返しを使って1文字づつコピーしよう。 • (または、strcpy 教科書p.55)
おまじないは文字列 • ここまで説明すればだいたい察しはついたと思うが… • これまで入力に使っていたおまじないchar line[100]; はlineという文字列変数の宣言である。 • 入力された文字列をfgetsを使ってlineという文字列変数に格納する。
fgetsの動作 • 書式 • fgets( 文字列, サイズ, stdin); • 動作 • (サイズ-1)文字をキーボードから読み取り、文字列に格納する。読み残した部分は次のfgetsで読み取られる。 • 読み込みは、改行が入った後、終る。 • 読み込まれた文字列中の最後には改行'\n'が入る。 • '\0' 文字がバッファの中の最後の文字の後に1文字書き込まれる。 • 文字列+'\n'(改行文字)+'\0'(終端文字) の形でキーボードからの入力が格納される。
‘\n’は入ってる? 文字配列strに’\n’が入っているか知りたい。 printf( “%s”, str ); を記述したプログラム test.cをコンパイル,実行して, $./test $abc$ ← ‘\n’が入ってない $./test $abc ← ‘\n’が入っている $
キーボードから文字列を受け取る1次元配列の場合キーボードから文字列を受け取る1次元配列の場合 char line[100]; char str[100]; /* line => strにコピー */ int i; fgets(line, sizeof(line), stdin); i = 0; while( line[i] != ‘\n’ ) { str[i] = line[i]; i = i + 1; } str[i] = ‘\0’; line[100] a b c \n \0 str[100] a b c \0
キーボードから文字列を受け取る2次元配列の場合キーボードから文字列を受け取る2次元配列の場合 char line[100]; char str[3][100]; /* line => str[1]にコピー */ int i; fgets(line, sizeof(line), stdin); i = 0; while( line[i] != ‘\n’ ) { str[1][i] = line[i]; i = i + 1; } Str[3][i] = ‘\0’; line[100] a b c \n \0 str[3][100] str[0][*] a b c \0 str[1][*] str[2][*]
今日のまとめ • for文 基本的構文は理解できましたか? • 多重ループ 制御の流れを正しく追えますか? • 配列 配列の概念を理解できましたか? • 1次元配列 定義の仕方・利用方法 • 2次元配列 • 文字列 文字列も配列の一種ということが 理解できましたか? • \0 この記号の役割を説明できますか? • fgets fgetsの動作を正確に説明できますか?\n と \0 はどこに入りますか?