同じ構造をした「引き出し」変数を構造体変数と呼ぶ

Slides:



Advertisements
Similar presentations
プログラミング入門2 芝浦工業大学情報工学科青木 義満 第11回構造体. プログラミング入門2 2 構造体 5 人分のサッカー選手データ 全てのデータを関数に渡して,処理する場合 char name[5][256]; int assist[5]; int score[5]; void func( char.
Advertisements

C 言語講座第 5 回 構造体. 構造体とは ... 異なる型の値をまとめて新しい型とする 機能がある . つまり , 複数の変数を 1 つのまとまりにできる . 配列と違って同じ型でデータをまとめるのではな く違った型のデータをまとめられる .
プログラミング 関数編 情報科学科. プログラミングにあたって C 言語では、 main 内に処理を記述 1000 行になるような大きなプログラムでは、 プログラム全体が何をしているのかを把握 することが困難になる 他人が見ると非常に理解しにくい 作成者であっても時が経てば内容を忘れて、他 人が見た時と同じ状況になる.
構造体変数 1234 x xyz A 普通の変数 ( ここでは座標値 ) 構造体変数 ( ここでは点を表す ) xyz B 14 y 5 z 点 A の x 座標 プログラム中では A.x 点 B の y 座標 プログラム中では B.y 例えば 「 3 次元空間で2点 A と B の 間に線分を引き・・・」
前回の関数のまとめ (1) プログラムは main() 関数の先頭から実行される 関数は main() 関数または他の関数から呼び出されて実行される. 関数を呼び出す側の実引数の値が関数内の仮引数 ( 変数 ) に コピーされる 関数内で求めた値は return 文によって関数値として呼び出し側に戻され.
復習 配列変数の要素 5は配列の要素数 これらの変数をそれぞれ配列の要素と呼ぶ この数字を配列の添え字,またはインデックスと呼ぶ
復習 配列変数の要素 5は配列の要素数 これらの変数をそれぞれ配列の要素と呼ぶ この数字を配列の添え字,またはインデックスと呼ぶ
次ページに関数の解答例 課題12-1 (問題と解答) 複素数xとして, 実部を入力してください.10 虚部を入力してください.20
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
A B x y z 復習 構造体変数 普通の変数 x y z 構造体変数 x y z 箱のイメージ 引き出しのイメージ
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
第2章 数値の入力と変数 scanfと変数をやります.
第13回構造体.
第12回構造体.
プログラミング入門2 ポインタについて補足 構造体 第11回 芝浦工業大学情報工学科 青木 義満、篠埜 功
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
構造体.
関数 関数とスタック.
構造体 構造体, 構造体とポインタの組み合わせ,.
第10回 プログラミングⅡ 第10回
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
プログラミング応用 printfと変数.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
知能情報工学演習I 第9回( C言語第3回) 課題の回答
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
今までの練習問題の復習.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
知能情報工学演習I 第8回( C言語第2回) 課題の回答
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
第11回 プログラミングⅡ 第11回
C#言語ソースプログラムの原型 C言語 C#言語 Hello World! Hello Students! オマジナイ! 適当なクラス名
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
プログラミング基礎B 文字列の扱い.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
復習 前回の関数のまとめ(1) プログラムはmain()関数の先頭から実行される
C言語 はじめに 2016年 吉田研究室.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング演習I 2003年4月30日(第3回) 木村巌.
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
復習 breakとcontinueの違い int i; for (i = 1; i <= 100; i++) { ・・・処理1・・・・
復習 Cにおけるループからの脱出と制御 break ループを強制終了する.if文と組み合わせて利用するのが一般的. continue
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
第5回 プログラミングⅡ 第5回
復習 breakとcontinueの違い int i; for (i = 1; i <= 100; i++) { ・・・処理1・・・・
標準入出力、変数、演算子、エスケープシーケンス
知能情報工学演習I 第8回(後半第2回) 課題の回答
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
全体の流れ 画像ファイルを開き,画像データをメモリ上にロード メモリ上にロードした画像データに処理を加える
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
モバイルプログラミング第2回 C言語の基礎 (1).
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
printf・scanf・変数・四則演算
第2章 数値の入力と変数 scanfと変数をやります.
知能情報工学演習I 第9回(後半第3回) 課題の回答
復習 いろいろな変数型(2) char 1バイト → 英数字1文字を入れるのにぴったり アスキーコード → 付録 int
C言語講座第5回 2017 構造体.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

同じ構造をした「引き出し」変数を構造体変数と呼ぶ 例えば,課題が 「A君の誕生日をa,B君の誕生日をbとし,どちらが早く生まれたか比べなさい・・・」 日付aや日付bを表す変数があると便利 ⇒実際には日付は複数の変数でできている 復習 構造体変数 箱のイメージ 1999 year 12 month 普通の変数 (ここでは年・月・日) 5 day 構造体変数 (ここでは日付) year month day a 引き出しのイメージ 構造体変数aの中のyear プログラム中では a.year year month day b ピリオド 構造体変数bの中のyear プログラム中では b.year ピリオド 同じ構造をした「引き出し」変数を構造体変数と呼ぶ

復習 a b 構造体のプログラム例(1) ー 日付型 キーワード struct 構造体内の変数をメンバ変数と呼ぶ 2 構造体のプログラム例(1) ー 日付型 キーワード struct 構造体内の変数をメンバ変数と呼ぶ #include <stdio.h> 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); } Date型の構造体の定義 Dateは変数ではなく設計図 year month day a 2015 7 1 year month day b 2015 7 2 1 Date型の構造体変数 aとbの宣言 a.year は構造体変数aのメンバ変数yearを意味する 構造体変数aをbに代入 b.day は構造体変数bのメンバ変数dayを意味する 初めの日付は2015年7月1日,次の日付は2015年7月2日

復習 構造体のプログラム例(4) #include <stdio.h> struct Date { int year; Student型構造体sを仮引数とする関数の定義 引き出しの内容(情報)を丸ごと引数として受け取るイメージ #include <stdio.h> struct Date { int year; int month; int day; }; struct Student int number; //学籍番号 char name[20]; //名前 float height; //身長 float weight; //体重 Date birthday; //誕生日 void printSt(Student s) { printf("%d番%s(%d年%d月%d日生)", s.number, s.name,s.birthday.year, s.birthday.month, s.birthday.day); return; } void main() { Student matsu = {1020, "matsushima", 163.5, 62.0, {1970, 2, 28}}; printSt(matsu); printf("\n"); 1020番matsushima(1970年2月28日生) Student型構造体の変数sの内容を画面表示 代入 (コピー) Student型構造体のメンバとして文字列を指定 注意! s.number ○ number  × Student型構造体変数matsuを実引数とした関数呼び出し Student型構造体のメンバとしてDate型構造体変数を指定

構造体と配列を組み合わせたプログラム例(1/2) 構造体変数の中に配列が含まれている場合(配列を含む構造体) 構造体変数が配列になっている場合(構造体変数の配列) #include <stdio.h> 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; sum = sum + a.money[i]; return sum; 配列を含む構造体の定義 この構造体にバイト一人あたりの情報をすべて詰め込んで管理する この関数を使うと構造体変数baitoの(一人分の)情報を画面表示できる この関数は,構造体変数aの(一人分の)1年間の給料総額を返す 番号 氏名 毎月の給料(単位:千円) 合計 -------------------------------------------------------- 10 Matsushima 10 15 12 10 15 20 20 15 11 15 12 10 : 165 15 Abe 10 15 14 20 15 20 20 16 11 15 42 10 : 208 16 Trump 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 続行するには何かキーを押してください . . .

構造体と配列を組み合わせたプログラム例(2/2) #include <stdio.h> 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, "Abe", {10, 15, 14, 20, 15, 20, 20, 16, 11, 15, 42, 10}}, {16, "Trump", {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])); } ここでは4人分の情報で初期化 番号 氏名 毎月の給料(単位:千円) 合計 -------------------------------------------------------- 10 Matsushima 10 15 12 10 15 20 20 15 11 15 12 10 : 165 15 Abe 10 15 14 20 15 20 20 16 11 15 42 10 : 208 16 Trump 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 続行するには何かキーを押してください . . . list[i]は,i番目の一人分の情報(一つの構造体変数) これは配列引数ではないことに注意!

関数のプロトタイプ宣言(1) 呼出し 定義 呼出し 定義 ソースプログラム上で,関数の定義は関数の呼出しより先に書かれていなければならない #include <stdio.h> 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 <stdio.h> 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; 呼出し 定義 呼出し 定義 ソースプログラム上で,関数の定義は関数の呼出しより先に書かれていなければならない 理由:コンパイラはソースプログラムの先頭から順にソースプログラムを機械語に変換するため,関数の定義より先に関数の呼び出しがあると機械語に変換できない.

関数のプロトタイプ宣言(2) 定義 定義 呼出し 定義 呼出し 呼出し 関数がお互いに呼び出しあうソースプログラムは記述不可能?? #include <stdio.h> float func1(...) //何かの関数1 { ... b = func2(...); return s; } void func2(...) //何かの関数2 c = func1(...); return; int main(void) x = func1(...); y = func2(...); #include <stdio.h> void func2(...) //何かの関数2 { ... c = func1(...); return; } float func1(...) //何かの関数1 b = func2(...); return s; int main(void) x = func1(...); y = func2(...); 定義 定義 呼出し 呼出し 定義 呼出し 関数がお互いに呼び出しあうソースプログラムは記述不可能??

printf()関数やscanf()関数では 不要? 関数のプロトタイプ宣言(3) #include <stdio.h> 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行目 プロトタイプ宣言は関数の使用方法(引数の数と型,戻り値の型)を示している

→ stdio.hという名前のヘッダファイルを読み込む 関数のプロトタイプ宣言を集めてあるファイル → ヘッダファイル (xxxxx.h) ヘッダファイルをソースプログラム内に読み込む命令 → #include #include <stdio.h> → stdio.hという名前のヘッダファイルを読み込む ライブラリ関数 stdio.h あらかじめ用意されている標準入出力関数であるprintf()やscanf()などのプロトタイプ宣言が書かれているヘッダファイル (standard input output) math.h sqrt()などの数値計算関数のヘッダファイル (mathematics) 疑問:ライブラリ関数のプロトタイプ宣言はヘッダファイルに書かれている. では関数本体の定義はどこにある?

実行プログラムができるまで ライブラリ関数 #include コンパイル コンパイル 済みの本体 リンク ソースプログラム ヘッダファイル (source13-1.cpp) 実行プログラム (kadai13-1.exe) コンパイラ 機械語への変換 .exeファイルだけでプログラムが実行できる! プロジェクト名  kadai13-1 ソースプログラム名  source13-1.cpp プロジェクトフォルダ内のDebugまたはReleaseフォルダにできる #include ヘッダファイルの読み込み オブジェクトファイルを結合(リンク) する オブジェクトファイル2 オブジェクトファイル3 オブジェクトファイル4 コンパイラ 参考:複数のソースプログラムがある場合 プリプロセッサ ソースプログラム2 ソースプログラム3 ソースプログラム4 コンパイル 済みの本体 オブジェクトファイル (ライブラリファイル) ヘッダファイル (プロトタイプ宣言) ライブラリ関数 コンパイル リンク コンパイル+リンク=ビルド と呼んでいる プリプロセス(事前処理) されたソースプログラム オブジェクトファイル (source13-1.obj) プリプロセッサ リンカ ヘッダファイルの読み込み等の処理 ライブラリとオブジェクトファイルの結合 オブジェクトファイルは実行プログラムの一歩手前のファイル 複数のオブジェクトファイルの結合 ※ここでのオブジェクトファイルは 構造体で学習した「オブジェクト」とは異なる

プリプロセッサ命令 #include <標準ヘッダファイル名> #include "自作ヘッダファイル名" プリプロセッサ命令は #で始まる #include <標準ヘッダファイル名> #include "自作ヘッダファイル名" #define マクロ名  マクロ文字列 ヘッダファイルを読み込む マクロ名をマクロ文字列で置き換える スペース(空白)またはタブ ソースファイル:kadai12.cpp 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); } 自作ヘッダファイル:rei12.h コンパイル void func1(int a); float func2(int a, char b);

プリプロセッサ命令を用いたプログラムの例(1) 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を計算する #include <stdio.h> #include <math.h> #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)); }

標準ライブラリ関数を用いたプログラムの例(2) 10文字 (= amp) y=0 ⇒ s[10] s[20] ⇑ y=1.0 y=-1.0 ⇓ s[0] 21文字の文字列s[]で1文字だけを'*'にして,グラフとして表現する x y #include <stdio.h> #include <math.h> #include <string.h> #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に置き換えられてからコンパイルされるので,エラーにならない 両側に10文字ずつ変化する 文字列なので最後(S[21])は0にしておく 文字列sを全て特定の文字(ここでは空白文字)で埋めるライブラリ関数 y = sin x y = sin xのy値から求まる特定のインデックスpの1文字を*に変える

どの文字を’*’に変更するのか? (変更する文字の位置の求め方の説明) y = sin x y = -1 y = 0 y = +1 s[22] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21個の要素の いずれかを '*'文字にする p=0 p=10 p=20 double型 int型 p = 10 * y + 10 y : sin(x)の計算結果(double型) p : 文字列sで*印を入れる位置のインデックス(int型)

キャストによる変数型の変換 x1 = 0.00, x2 = 0.00 y1 = 0.33, y2 = 0.67 続行するには何かキー. . . #include <stdio.h> 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); } 整数同士の演算では少数以下は切り捨て 1/3 = 0.333… ⇒ 0 整数変数同士の演算でも少数以下切り捨て 浮動小数点と整数の演算では全て浮動小数点として計算 1.0/3 = 1.0/3.0 ⇒ 0.333… 整数変数同士の演算だが,浮動小数点で計算させたい キャストの書き方 (変数型) 変数 変数を変数型に変換する キャストによる型の変換

キャストを用いた四捨五入 #include <stdio.h> 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 続行するには何かキー. . . warning C4244: '=' : 'double' から 'int' への変換です。データが失われる可能性があります。 キャストを用いているので警告が出ない! キャストを用いた四捨五入 0.5を足して整数型に変換すると小数以下の四捨五入になる 3.4999 + 0.5 = 3.9999 ⇒ 3 3.5000 + 0.5 = 4.0000 ⇒ 4

標準ライブラリ関数を用いたプログラムの例(2) 10文字 (= amp) y=0 ⇒ s[10] s[20] ⇑ y=1.0 y=-1.0 ⇓ s[0] 21文字の文字列s[]で1文字だけを'*'にして,グラフとして表現する x y #include <stdio.h> #include <math.h> #include <string.h> #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); } * 続行するには何かキー. . . p = 10 * y + 10 ↓ p = (int)(10 * y + 10 + 0.5)