Download presentation
Presentation is loading. Please wait.
Published byちとら かがんじ Modified 約 8 年前
1
構造体変数 1234 x xyz A 普通の変数 ( ここでは座標値 ) 構造体変数 ( ここでは点を表す ) xyz B 14 y 5 z 点 A の x 座標 プログラム中では A.x 点 B の y 座標 プログラム中では B.y 例えば 「 3 次元空間で2点 A と B の 間に線分を引き・・・」 実際には点 A や点 B は座標で 表すので,複数の変数が必 要 例えば 「 3 次元空間で2点 A と B の 間に線分を引き・・・」 実際には点 A や点 B は座標で 表すので,複数の変数が必 要 箱のイメージ 引き出しのイメージ 復習
2
構造体のプログラム例 (1) ー 日付型 #include struct Date { int year; int month; int day; }; void main() { Date a, b; a.year = 2015; a.month = 7; a.day = 1; b = a; b.day = 2; printf(" 初めの日付は %d 年 %d 月 %d 日, ", a.year, a.month, a.day); printf(" 次の日付は %d 年 %d 月 %d 日 \n", b.year, b.month, b.day); } a.year は構造体変数 a のメ ンバ変数 year を意味する 構造体内の変数をメンバ変数と呼ぶ 初めの日付は 2015 年 7 月 1 日,次の日付は 2015 年 7 月 2 日 Date 型の構造体の定義 キーワード struct b.day は構造体変数 b の メンバ変数 day を意味す る 構造体 変数 a を b に代入 Date 型の構造体変数 a と b の宣言 yearmonthday b yearmonthday a 201571 71 2 Date は変数ではなく設計図 復習
3
構造体と配列を組み合わせたプログラム例 (1/2) #include struct BaitoKanri // バイト管理構造体 { int id; // バイトの個人番号 char name[20]; // バイトの氏名 ( 文字列 ) int money[12]; //1 ~ 12 月に支払ったバイト料 (1000 円単位 ) }; // バイト一人分の番号,氏名,支払額の表示する関数 void PrintPerson(BaitoKanri baito) { int i; printf("%2d %-10s", baito.id, baito.name); for (i = 0; i < 12; i++) { printf(" %2d", baito.money[i]); } // バイト一人分の 1 年間の支払額を計算する関数 int Sum(BaitoKanri a) { int i, sum = 0; for (i = 0; i < 12; i++) { sum = sum + a.money[i]; } return sum; } 番号 氏名 毎月の給料 ( 単位 : 千円 ) 合計 -------------------------------------------------------- 10 Matsushima 10 15 12 10 15 20 20 15 11 15 12 10 : 165 15 Noda 10 15 14 20 15 20 20 16 11 15 42 10 : 208 16 Obama 20 15 13 15 15 30 20 15 11 25 12 10 : 201 20 Putin 12 15 12 20 15 20 10 17 11 15 12 10 : 169 続行するには何かキーを押してください... 構造体変数の中に配列が含まれ ている場合 ( 配列を含む構造体 ) 構造体変数が配列になっている 場合 ( 構造体変数の配列 ) 構造体変数の中に配列が含まれ ている場合 ( 配列を含む構造体 ) 構造体変数が配列になっている 場合 ( 構造体変数の配列 ) 配列を含む構造体の定義 この構造体にバイト一人あたりの 情報をすべて詰め込んで管理する この関数を使うと構造体 変数 baito の ( 一人分の ) 情 報を画面表示できる この関数は,構造体変数 a の ( 一人分の )1 年間の給 料総額を返す 復習
4
構造体と配列を組み合わせたプログラム例 (2/2) #include struct BaitoKanri // バイト管理構造体 { int id; // バイトの個人番号 char name[20]; // バイトの氏名 ( 文字列 ) int money[12]; //1 ~ 12 月に支払ったバイト料 ( 単位 1000 円 ) }; int main(void) { BaitoKanri list[4] = { {10, "Matsushima", {10, 15, 12, 10, 15, 20, 20, 15, 11, 15, 12, 10}}, {15, "Noda", {10, 15, 14, 20, 15, 20, 20, 16, 11, 15, 42, 10}}, {16, "Obama", {20, 15, 13, 15, 15, 30, 20, 15, 11, 25, 12, 10}}, {20, "Putin", {12, 15, 12, 20, 15, 20, 10, 17, 11, 15, 12, 10}}, }; printf(" 番号 氏名 毎月の給料 ( 単位 : 千円 ) 合計 \n"); printf("---------------------------------------------------------\n"); int i; for (i = 0; i < 4; i++) { PrintPerson(list[i]); printf(" :%4d\n", Sum(list[i])); } 番号 氏名 毎月の給料 ( 単位 : 千円 ) 合計 -------------------------------------------------------- 10 Matsushima 10 15 12 10 15 20 20 15 11 15 12 10 : 165 15 Noda 10 15 14 20 15 20 20 16 11 15 42 10 : 208 16 Obama 20 15 13 15 15 30 20 15 11 25 12 10 : 201 20 Putin 12 15 12 20 15 20 10 17 11 15 12 10 : 169 続行するには何かキーを押してください... 構造体変数の配列宣言 一人分の情報 ここでは 4 人分の情 報で初期化 list[i] は, i 番目の一人分の 情報 ( 一つの構造体変数 ) これは配列引数ではないこ とに注意 ! 復習
5
関数のプロトタイプ宣言 (1) #include float menseki(float a, float b) { float s; s = a * b / 2; return s; } int main(void) { float kekka; kekka = menseki(3, 4); printf("s=%f\n", kekka); } #include int main(void) { float kekka; kekka = menseki(3, 4); printf("s=%f\n", kekka); } float menseki(float a, float b) { float s; s = a * b / 2; return s; } 理由:コンパイラはソースプログラムの先頭から順にソースプログラムを機械語に 変換するため,関数の定義より先に関数の呼び出しがあると機械語に変換できない. ソースプログラム上で,関数の定義は関数の呼出しより 先に書かれていなければならない 定義 呼出し 定義 呼出し
6
関数のプロトタイプ宣言 (2) #include float func1(...) // 何かの関数 1 {... b = func2(...); return s; } void func2(...) // 何かの関数 2 {... c = func1(...); return; } int main(void) {... x = func1(...); y = func2(...); } #include void func2(...) // 何かの関数 2 {... c = func1(...); return; } float func1(...) // 何かの関数 1 {... b = func2(...); return s; } int main(void) {... x = func1(...); y = func2(...); } 関数がお互いに呼び出しあうソースプログラムは記述不可能?? 呼出し 定義 呼出し 定義 呼出し
7
関数のプロトタイプ宣言 (3) #include float menseki(float a, float b); int main(void) { float kekka; kekka = menseki(3, 4); printf("s=%f\n", kekka); } float menseki(float a, float b) { float s; s = a * b / 2; return s; } 関数のプロトタイプ宣 言 ソースプログラム上で,関数 の呼び出し前に,関数の定義 か,プロトタイプ宣言のどち らかが絶対必要 printf() 関数や scanf() 関数では 不要? No! 絶対必要 printf() や scanf() のプロトタイプ 宣言は stdio.h ファイルに定義さ れている. プロトタイプ宣言 = 関数定義の1行目 プロトタイプ宣言は関数の使用方法 ( 引数の数と型,戻り値の型 ) を示して いる 定義 呼出し プロトタイプ宣 言は関数定義の 予告編
8
ヘッダファイル 関数のプロトタイプ宣言を集めてあるファイル → ヘッダファイル (xxxxx.h) ヘッダファイルをソースプログラム内に読み込む命令 → #include stdio.h あらかじめ用意されている標準入出力関数である printf() や scanf() などのプロトタイプ宣言が書かれているヘッダ ファイル (standard input output) math.h sqrt() などの数値計算関数のヘッダファイル (mathematics) ライブラリ関数 #include → stdio.h という名前のヘッダファイルを読み込む 疑問:ライブラリ関数のプロトタイプ宣言はヘッダファイルに書かれている. では関数本体の定義はどこにある?
9
ソースプログラム (source13-1.cpp) 実行プログラム (kadai13-1.exe) コンパイラ 機械語への変換.exe ファイルだけでプロ グラムが実行できる! プロジェクト名 kadai13-1 ソースプログラム名 source13-1.cpp プロジェクト名 kadai13-1 ソースプログラム名 source13-1.cpp プロジェクトフォルダ内の Debug または Release フォル ダにできる 実行プログラムができるまで プリプロセス ( 事前処理 ) されたソースプログラム オブジェクトファイル (source13-1.obj) プリプロセッ サ リンカ ヘッダファイルの 読み込み等の処理 ライブラリとオブ ジェクトファイル の結合 コンパイル リンク コンパイル+リンク=ビルド と呼んでいる コンパイル 済みの本体 オブジェクトファイル ( ライブラリファイル ) ヘッダファイル (プロトタイプ宣言) ライブラリ関数 ソースプログラム 2 ソースプログラム 3 ソースプログラム 4 オブジェクトファイル 2 オブジェクトファイル 3 オブジェクトファイル 4 コンパイラ 参考:複数のソース プログラムがある場 合 #include ヘッダファイ ルの読み込み オブジェク トファイル を結合 ( リ ンク ) する ※ここでのオブジェクトファイルは 構造体で学習した「オブジェクト」とは異なる ※ここでのオブジェクトファイルは 構造体で学習した「オブジェクト」とは異なる 複数のオブジェク トファイルの結合
10
void func1(int a); float func2(int a, float b); int main(void) { int x,y; x = 35 + 22 + 'B'+15; func1(x); y = func2(35, 'B'+15); } プリプロセッサの処理後 プリプロセス プリプロセッサ命令 #include "rei12.h" #define teisu 35 #define moji 'B'+15 int main(void) { int x,y; x = teisu + 22 + moji; func1(x); y = func2(teisu, moji); } void func1(int a); float func2(int a, char b); ソースファイル: kadai12.cpp 自作ヘッダファイル: rei12.h #include #include " 自作ヘッダファイル名 " #define マクロ名 マクロ文 字列 ヘッダファイルを読み込む マクロ名をマクロ文字列で置き換える スペース ( 空白 ) またはタブ プリプロセッサ命令 は # で始まる コンパイル
11
プリプロセッサ命令を用いたプログラムの例 (1) #include #define PI 3.1415 int main(void) { double x; for (x = 0; x <= 2*PI; x = x + PI/10) { printf("x = %5.3f, sin x = %6.3f\n", x, sin(x)); } x = 0.000, sin x = 0.000 x = 0.314, sin x = 0.309 x = 0.628, sin x = 0.588 x = 0.942, sin x = 0.809 x = 1.257, sin x = 0.951 x = 1.571, sin x = 1.000 x = 1.885, sin x = 0.951 x = 2.199, sin x = 0.809 x = 2.513, sin x = 0.588 x = 2.827, sin x = 0.309 x = 3.142, sin x = 0.000 x = 3.456, sin x = -0.309 x = 3.770, sin x = -0.588 x = 4.084, sin x = -0.809 x = 4.398, sin x = -0.951 x = 4.712, sin x = -1.000 x = 5.026, sin x = -0.951 x = 5.341, sin x = -0.809 x = 5.655, sin x = -0.588 x = 5.969, sin x = -0.309 x = 6.283, sin x = -0.000 続行するには何かキー... x=0 から 2 まで /10 毎に sin x を計 算する
12
標準ライブラリ関数を用いたプログラムの例 (2) #include #define PI 3.1415 #define amp 10 int main(void) { double x, y; int p; char s[2*amp + 2]; s[2*amp + 1] = 0; for (x = 0; x <= 2*PI; x = x + PI/10) { _strset(s, ' '); y = sin(x); p = (int)(amp * y + amp + 0.5); s[p] = '*'; printf("%s\n", s); } * 続行するには何かキー... 要素数 22 の配列宣言 注 ) amp が 10 に置き換えられて からコンパイルされるので,エ ラーにならない 文字列なので最後 (S[21]) は0にして おく 文字列 s を全て特定の文字 ( ここ では空白文字 ) で埋めるライブ ラリ関数 21 文字の文字列 s[] で 1 文字だけを '*' にして, グラフとして表現す る 10 文字 (= amp) 10 文字 (= amp) y=0 ⇒ s[10] s[20] ⇑ y=1.0 y=-1.0 ⇓ s[0] y = sin x の y 値から どの文字を * に変 えるかを計算 x y
13
どの文字を ’*’ に変更するのか? ( 変更する文字の位置の求め方の説明 ) 01234567891011121314151617181920 y = 0y = -1y = +1 p=10p=0p=20 s[22] p = 10 * y + 10 21 個の要素の いずれかを '*' 文字にする y = sin x double 型 int 型 y : sin(x) の計算結果 (double 型 ) p : 文字列 s で * 印を入れる位置のインデックス (int 型 )
14
キャストによる変数型の変換 #include int main(void) { int a = 2, b = 3; double x1, x2, y1, y2; x1 = 1 / 3; x2 = a / b; printf("x1 =%5.2f, x2 =%5.2f\n", x1, x2); y1 = 1.0 / 3; y2 = (double) a / b; printf("y1 =%5.2f, y2 =%5.2f\n", y1, y2); } x1 = 0.00, x2 = 0.00 y1 = 0.33, y2 = 0.67 続行するには何かキー... x1 = 0.00, x2 = 0.00 y1 = 0.33, y2 = 0.67 続行するには何かキー... 整数同士の演算では少数以下は切り捨て 1/3 = 0.333… ⇒ 0 浮動小数点と整数の演算では全て 浮動小数点として計算 1.0/3 = 1.0/3.0 ⇒ 0.333… キャストによる型の変 換 キャストの書き方 ( 変数型 ) 変数 変数を変数型に変換する 整数変数同士の演算でも少数以下切り捨て 整数変数同士の演算だが, 浮動小数点で計算させたい
15
キャストを用いた四捨五入 #include int main(void) { int c0, c1, c2, c3, c4; double x1, x2; x1 = 3.4999; c0 = x1; c1 = (int) x1; x2 = 3.5000; c2 = (int) x2; printf("c1 = %d, c2 = %d\n", c1, c2); c3 = (int) (x1 + 0.5); c4 = (int) (x2 + 0.5); printf("c3 = %d, c4 = %d\n", c3, c4); } c1 = 3, c2 = 3 c3 = 3, c4 = 4 続行するには何かキー... c1 = 3, c2 = 3 c3 = 3, c4 = 4 続行するには何かキー... warning C4244: '=' : 'double' から 'int' への変 換です。データが失われる可能性があります。 キャストを用いているので警 告が出ない! キャストを用いた四捨五入 0.5 を足して整数型に変換する と小数以下の四捨五入になる 3.4999 + 0.5 = 3.9999 ⇒ 3 3.5000 + 0.5 = 4.0000 ⇒ 4
16
標準ライブラリ関数を用いたプログラムの例 (2) #include #define PI 3.1415 #define amp 10 int main(void) { double x, y; int p; char s[2*amp + 2]; s[2*amp + 1] = 0; for (x = 0; x <= 2*PI; x = x + PI/10) { _strset(s, ' '); y = sin(x); p = (int)(amp * y + amp + 0.5); s[p] = '*'; printf("%s\n", s); } * 続行するには何かキー... 21 文字の文字列 s[] で 1 文字だけを '*' にして, グラフとして表現す る 10 文字 (= amp) 10 文字 (= amp) y=0 ⇒ s[10] s[20] ⇑ y=1.0 y=-1.0 ⇓ s[0] x y p = 10 * y + 10 ↓ p = (int)(10 * y + 10 + 0.5)
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.