4. 合成データ:構造体 プログラミング論I.

Slides:



Advertisements
Similar presentations
構造体 構造体とは? 複数のデータをパックしたもの。 新しい “ 型 “ として使用できる. 構造体 キーワード struct strcut は構造体を宣言する命令。 struct { double x,y; }a,b,c; ↑ ここまでが宣 言 ← この形式で、構造体 a,b,c, を定 義.
Advertisements

C 言語講座第 5 回 構造体. 構造体とは ... 異なる型の値をまとめて新しい型とする 機能がある . つまり , 複数の変数を 1 つのまとまりにできる . 配列と違って同じ型でデータをまとめるのではな く違った型のデータをまとめられる .
プログラミング言語論 第10回(演習) 情報工学科 木村昌臣   篠埜 功.
アルゴリズムとデータ構造 第2回 線形リスト(復習).
プログラミング演習(1組) 第7回
プログラミング言語としてのR 情報知能学科 白井 英俊.
1.1 C/C++言語 Hello.ccを作りコンパイルしてa.outを作り出し実行する
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
第12回新しい型と構造体.
第13回構造体.
解答 1 複素数を構造体として定義し、二つの複素数の積(結果は複素数)を返す 関数 を定義せよ。
第12回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
構造体.
条件式 (Conditional Expressions)
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
構造体 構造体, 構造体とポインタの組み合わせ,.
第16章 構造体 16.1 構造体の定義と構造体変数 16.2 構造体の配列.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
暗黙的に型付けされる構造体の Java言語への導入
プログラミング応用 printfと変数.
第10回関数 Ⅱ (ローカル変数とスコープ).
第11回 宿題 出題日:12月21日 締切日:1月7日(木).
精密工学科プログラミング基礎 第10回資料 (12/18実施)
10.構造体とグラフィックス.
前回の練習問題.
第7回 条件による繰り返し.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
6. リスト処理関数の設計(発展版) プログラミング論 I.
12.数値微分と数値積分.
6.リストの生成.
第11回 プログラミングⅡ 第11回
3.条件式.
4.リスト,シンボル,文字列.
整数データと浮動小数データ.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
11.再帰と繰り返しの回数.
9.構造体.
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
15.cons と種々のデータ構造.
計算機プログラミングI 第3回 プリミティブ値 クラスメソッド クラス変数 式と演算 変数の利用
3. 条件式、 データのバリエーション プログラミング論I.
情報処理Ⅱ 2005年10月28日(金).
1.Scheme の式とプログラム.
5. 任意長の合成データ:リスト プログラミング論I.
cp-15. 疑似乱数とシミュレーション (C プログラミング演習,Visual Studio 2019 対応)
cp-2. 属性,アクセサ (C++ オブジェクト指向プログラミング入門)
cp-1. クラスとメソッド (C++ オブジェクト指向プログラミング入門)
cp-3. 計算 (C プログラミング演習,Visual Studio 2019 対応)
プログラミング 4 文字列.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
PROGRAMMING IN HASKELL
エクセル(3)の目次 参照演算子と演算子 参照セルの表示法 セルの参照方法 エラーについて シグマ(Σ)関数 条件付書式 問題(1)
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
7. 設計の抽象化 プログラミング論 I.
情報処理Ⅱ 2005年11月25日(金).
プログラミング 平成28年10月25日 森田 彦.
プログラミング入門2 第5回 配列 変数宣言、初期化について
第4回 配列.
情報処理Ⅱ 小テスト 2005年2月1日(火).
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
復習 いろいろな変数型(2) char 1バイト → 英数字1文字を入れるのにぴったり アスキーコード → 付録 int
C言語講座第5回 2017 構造体.
第5回 配列.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
高度プログラミング演習 (10).
Presentation transcript:

4. 合成データ:構造体 プログラミング論I

本日の内容 単純データと合成データ 構造体(合成データの一種) 様々なデータとその区別 構造体の定義:構造(構成要素など)の鋳型を準備 構造体の使用 コンストラクタ:構造体の定義にあうデータを生成する セレクタ:構造体の内容を参照する 構造体データを使うプログラムの設計法 様々なデータとその区別

様々なデータ 単純データ 合成データ:複数要素で1つのデータを構成 数値、ブール値、シンボル、文字列、… 構造体 (structure) :固定数の要素で1つのデータ 2次元平面座標(x,y座標)、名簿の一人分の項目数、 … リスト(後日説明):不定数の要素で1つのデータ 窓口の行列の人数、 …

構造体の例 複数の要素から1つのデータを構成する例 x 2次元平面座標 名簿データ y 構造体の名前 要素データ(フィー ルド)の並び 例 名前:山田、年:19、住所:伊都 posn personal_info 構造体の名前 x y name age address 要素データ(フィー ルド)の並び 様々なフィールド(要素データ)を持つ構造データ  → プログラマが定義可能

構造体データを扱う道具立て 様々な構造体を扱う道具立て 例えば二次元平面上の点を扱う場合 各構造体の定義 個々の構造体データの実体を作る コンストラクタ 構造体データから各フィールド値を選ぶ セレクタ 例えば二次元平面上の点を扱う場合 定義:二次元平面上の座標は何で構成される? 座標はx 座標と y 座標で定まる.値は数値. (x, y) コンストラクタ:定義にあう二次元平面上の点を作る 各点の要素の具体的データ(例えば(1, 3) (5, 12) など)を与え構造体データを生成 セレクタ:ある点の座標データの値を調べる どの点のどの要素(x座標か y座標)かを,指定して参照 (1, 3)のx座標の値 1. (1,3)のy座標の値 3 を取り出す.

構造体の定義(一般形) 様々な構造体があり得る→問題に合わせて定義 上記の定義の実行によって 構造体名 フィールド名の並び 固定数のフィールド(属性値)を持つあらゆるオブジェクトを表現 構造体名 フィールド名の並び (define-struct c (s1  …   sn) ) 上記の定義の実行によって 個々の構造体データの実体を作るコンストラクタ: make-c (構造体名の前に make-をつける) 構造体データから各フィールド値を選ぶセレクタ: c-s1 … c-sn (構造体名とフィールド名を - でつなぐ) が使えるようになる

構造体の定義例: posn 型構造体 2次元平面座標 posn は x, y 座標値から構成 上記の定義によって 構造体名 フィールドの並び x y 座標データ フィールド (define-struct posn (x y) ) 上記の定義によって コンストラクタ: make-posn セレクタ: posn-x posn-y が使えるようになる (DrRacketではposn型定義は基本構造体として元から準備済)

例題1. posn構造体 (define-struct posn (x y)) 以下のような点の生成や参照の例 ただし、 y DrRacketでは posn は基本的な組込みの構造体として 最初から定義済なのであらためて定義しなくてよい 4 3 点a (3,4) x y 点 (3,4) を作る 点 (3,4) の x 座標値を選ぶ 点 (3,4) の y 座標値を選ぶ 点 (3,4) を作り a という名前にする 点a の x 座標値を選ぶ 点a の y 座標値を選ぶ

C言語の場合 // (define-struct posn (x y)) typedef struct{ int x; int y; } posn; //(define a (make-posn 3 4)) posn a; // posn型の変数a a.x=3; // a.x == (posn-x a) a.y=4; // a.y == (posn-y a)

C言語の場合 (define-struct personal_info (name age address)) (define a (make-personal_info “Matsuzaka” 33 “Fukuoka”)) (personal_info-name a) => “Matsuzaka” #define _CRT_SECURE_NO_WARNINGS #define <string.h> personal_info a; strcpy(a.name,“Matsuzaka”); a.age=33; strcpy(a.address,“Fukuoka”); typedef struct{ char name[20]; int age; char address[128]; } personal_info;

練習 (define b (make-posn 12 5)) (posn-x b) (posn-y b) (define-struct personal_info (name age address)) (define SBF-1 (make-personal_info “Matsuzaka" 33 “Fukuoka")) (personal_info-name SBF-1) (personal_info-age SBF-1) (personal_info-address SBF-1) 二次元平面上の点b (12,5) について コンストラクタで点bの構造体データを生成せよ セレクタで点bの x座標と y座標を参照せよ 個人情報がname(文字列), age(数字), address(文字列) からなるとき、その構造体を personal_info という名前で定義せよ そのコンストラクタは何か そのセレクタは何か

personal_info 型構造体 名簿データpersonal_info 型構造体を定義 構造体名 フィールド名の並び personal_info は name, age, address から構成 構造体名 フィールド名の並び (define-struct personal_info (name age address)) 上記の定義によって以下が使えるようになる コンストラクタ make-personal_info セレクタ personal_info-name personal_info-age personal_info-address personal_info name age address フィールド

合成データの関数の プログラム設計法

プログラム設計法:合成データの関数 合成データを扱う関数向けに プログラム設計法を拡張 データの解析と定義: 処理対象がN個の特性を持つ → N個のフィールドの構造体を導入 フィールドがどの種のデータを含むか仕様記述するデータ定義 Purpose:プログラムの目的を理解、機能の概要を記述 Contract, Header, Statement: Example:プログラムの振る舞いを「例」で記述. Template:ヘッダと可能な全セレクタ式を列挙した本体を構成 複合データを扱う関数は複合データの構成要素を使い結果を計算 各セレクタ式は適切なセレクタを構造データパラメータに適用 Body Definition:プログラムの定義本体を具体化する Test:検査を通じた誤り(エラー)の発見

例題:原点からの距離 5 出力は数値 入力は点を表すデータ 二次元平面上の点の,原点までの距離を求める関数 distance_to_0 を作る 点 (3, 4) のデータ 5 distance_to_0 入力 出力 入力は点を表すデータ 出力は数値

プログラム設計法:データの解析と定義 処理対象がN個の特性を持つならNフィールドの構造体を導入 → 今回,点は2つの座標値を持つので2つのフィールドの構造体 (define-struct posn (x y)) 可能な限り正確に posn構造体データ定義の仕様を記述: 後にデータ定義に対応した関数テンプレートを作成 フィールドがどのような種類のデータを含むか? posn型の構造体を生成するにはコンストラクタを使う: (make-posn num1 num2) ここで num1 num2は数値 この構造体データの例: (make-posn 3 4) (make-posn 12 5) 注:DrRacket では定義済

プログラム設計法: Contract, Header numberや symbolのような不可分データのクラス名 posn のようなデータ定義で導入した名前 ;; distance_to_0: posn -> number (define (distance_to_0 a_posn) … )

プログラム設計法: テンプレート 本体より先にまずテンプレートを設計 ヘッダと,可能な全セレクタ式を列挙した本体を記述。 各セレクタ式は適切なセレクタを入力の構造体データに適用したもの (関数が入力の構造体データの要素を使う計算をすることを反映) 入力は posn 型構造体のデータ a_posn セレクタは2つ: posn-x posn-y ;; distance_to_0: posn -> number (define (distance_to_0 a_posn) … (posn-x a_posn) … … (posn-y a_posn) … ) セレクタ posn-xでposn 型構造体の入力データ a_posn のx 座標フィールド値の取得、y座標フィールド値も同様

プログラム設計法: Example 二次元平面上の点の,原点までの距離を求める (distance_to_0 (make-posn 3 4)) ;; 期待される値 5 (distance_to_0 (make-posn 12 5)) ;; 期待される値 13

プログラム設計法: 本体定義 基本演算や他の関数を使い答を計算する式を定式化 利用可能なデータは入力、セレクタ式の結果 テンプレート: 本体定義: (define (distance_to_0 a_posn) … (posn-x a_posn) … … (posn-y a_posn) … ) x座標値 y座標値 セレクタで参照した値を二乗して 加算し平方根を求める (define (distance_to_0 a_posn) (sqrt (+ (sqr (posn-x a_posn)) (sqr (posn-y a_posn)))))

distance_to_0 関数 x の2乗と y の2乗を加え平方根を求める ;; distance_to_0: posn -> number ;; compute the distance of a posn to the origin ;; (distance_to_0 (make-posn 3 4)) = 5 (define (distance_to_0 a_posn) (sqrt (+ (sqr (posn-x a_posn)) (sqr (posn-y a_posn))))) セレクタ posn-xでposn 型構造体の入力データ a_posn のx 座標フィールド値を取得、 y 座標フィールド値も同様 x 座標値の2乗と y座標値の2乗を加え平方根を求めている

プログラム全体(例) C言語の場合 (define-struct posn (x y)) (define a-posn (make-posn 3 4)) ;; distance_to_0: posn -> number (define (distance_to_0 a-posn) (sqrt (+ (sqr (posn-x a_posn)) (sqr (posn-y a_posn))))) ;; test > (distance_to_0 a-posn) 5 #include <stdio.h> #include <math.h> typedef struct{ int x; int y; } posn; // sqr: double -> double double sqr(double x){ return x*x; } // distance_to_0: posn -> double double distance_to_0(posn a){ return sqrt(sqr(a.x)+sqr(a.y)); } // test void main(){ posn a; a.x=3; a.y=4; printf(“%f”, distance_to_0(a));

練習 前述の personal_info 構造体について 構造体 personal_info 型のデータ a-person の年齢(age)が20以上ならば true を,20未満なら false を出力する関数 check-age1 を作成せよ。 構造体 personal_info 型のデータ a-person の年齢(age)が20以上ならば「‘Adult」を,20未満なら「’Clild」を出力する関数 check-age2 を作成せよ。

様々なデータとその区別 データの種類として構造体が加わった 様々なデータを処理する関数は などデータを区別する必要がある 数:数値情報の表現; ブール値:真か偽であるか; 記号: 記号情報の表現; 構造体: 合成データの表現 述語(Predicate) :データの特定の形式を判断する演算 number? 値が数なら true 違えば falseを返す boolean? 同様にブール値かどうか symbol? 同様にシンボルかどうか string? 同様に文字列かどうか struct? 同様に構造体かどうか また構造体にもさまざまな定義があるのでその区別も必要 構造体 posn に対する posn? や personal_info の personal_info? 様々なデータを処理する関数は 数と構造体の双方を含む場合、 異なる複数種類の構造体を含む場合、 などデータを区別する必要がある

これまでの Scheme 文法:語彙を用いてプログラム(式と定義)を作る規則 変数:関数と値の名前 キーワード: (変数には使用不可) define define-struct cond else 定数 単純値:数, ブール値, シンボルなど 合成値:構造体(固定要素数) プリミティブ演算: 四則演算子:+ - * / 比較演算子:< <= > >= = データ特性の判定: even? symbol? number? struct? … 論理演算子:and or not 構造体演算(コンストラクタ,セレクタ) その他の演算子: abs remainder quotient max min sqrt expt log sin cos tan asin acos atan など 文法:語彙を用いてプログラム(式と定義)を作る規則 定義 関数定義 (define (関数名 変数並び) 式) 変数定義 (define 変数名 式) 構造体定義 (define-struct 構造体名 (フィールド並び)) 式 変数 定数 プリミティブ演算の適用 定義した関数の適用 条件式

課題

課題1 構造体 posn のデータ a_posn の x 座標の値が 0 と 10 の間にある場合に限り true を返し,範囲外 の場合には false を返すような関数 xwithin を作成せよ。 また点 a (3,4) と点 b (12, 5) に対する実行結果はどうなるか。 但し,x = 0 あるいは x = 10 のときには false を返すこと. ヒント: 次の空欄を埋めなさい (define (xwithin a_posn) (cond [ ] [else ]))

解答例 (define-struct posn (x y)) (define (xwithin a_posn) (cond ;; xwithin: posn -> true or false ;; (xwithin (make-posn 3 4)) => true ;; (xwithin (make-posn 12 5)) => false (define (xwithin a_posn) (cond [(and (< 0 (posn-x a-posn)) (< (posn-x a-posn) 10)) true] [else false])) ;; 以下と同じ (and (< 0 (posn-x a-posn)) (< (posn-x a-posn) 10)))

課題2 構造体 personal_info 型のデータ a-person の年齢(ageフィールド)が20以上ならば名前(name フィールドの文字列) を,20歳未満なら匿名を表す文字列 "anonymous" を出力する関数 check-name1 を作成せよ。 入力は personal_info構造体 出力は文字列(string) check-name1 入力 出力 (make-personal_info "Ken" 18 "Ropponmatsu") ⇒ "anonymous" (make-personal_info "Bill" 20 "Hakozaki") ⇒ "Bill"

解答例 (define-struct personal_info (name age address) (define (check-name1 a-psn) (cond [(<= 20 (personal_info-age a-psn)) (personal_info-name a-psn)] [else “anonymous”])) ;; test (check-name1 (make-personal_info “Matsuzaka” 33 “Fukuoka”)) => “Matsuzaka”

課題3 構造体 personal_info 型のデータ a-person のageフィールドの値が,引数として与えられるある年齢の値と一致するならば,名前(name フィールドの値) を,一致しなければ“failed” を出力する関数 check-name2 を定義せよ。 入力は personal_info構造体 のデータと年齢(数) 出力は文字列(string) check-name2 入力 出力 (make-personal_info "Ken" 18 "Ropponmatsu") と 20 ⇒ "failed" (make-personal_info "Bill" 20 "Hakozaki") と 20 ⇒ "Bill"

解答例 (define-struct personal_info (name age address) (define (check-name2 a-psn an-age) (cond [(= an-age (personal_info-age a-psn)) (personal_info-name a-psn)] [else “failed”])) ;; test (check-name1 (make-personal_info “Matsuzaka” 33 “Fukuoka”) 33) => “Matsuzaka”

課題4. 複素数の計算 Scheme では複素数の計算もできる 足し算 (1+2i) + (3+4i) → 4+6i 課題4. 複素数の計算  Scheme では複素数の計算もできる 足し算 (1+2i) + (3+4i)  → 4+6i 引き算 (5+7i) – (3+4i)  → 2+3i かけ算 (1+2i) ×(3+4i)  → -5+10i 割り算 (-5+10i) / (3+4i) → 1+2i   (分母の通分) (-5+10i)/(3+4i) =(-5+10i)*(3-4i) /((3+4i)*(3-4i)) =(25+50i)/25 =1+2i

課題4. 複素数の計算 複素数データの表現と演算を独自に作ってみる: 実数部を r ,虚数部を i とする複素数データ comp 課題4. 複素数の計算  複素数データの表現と演算を独自に作ってみる: 実数部を r ,虚数部を i とする複素数データ comp 以下の ? を埋めてみる データ定義は (define-?????? comp (? ?)) コンストラクタは ????-comp セレクタは comp-? と, comp-? このcompを使い複素数の加減乗除comp+ comp- comp* comp/ を定義し以下を実行してみる (comp+ (make-comp 1 2) (make-comp 3 4)) (comp- (make-comp 5 7) (make-comp 3 4)) (comp* (make-comp 1 2) (make-comp 3 4)) (comp/ (make-comp -5 10) (make-comp 3 4))

(+ 1+2i 3+4i) →4+6i (- 5+7i 3+4i) →2+3i (* 1+2i 3+4i) →-5+10i (/ -5+10i 3+4i)→ 1+2i  と同等の計算

解答例 (define-struct comp (r i) (define (comp+ c1 c2) (make-comp (+ (comp-r c1) (comp-r c2)) (+ (comp-i c1) (comp-i c2)))) (define (comp- c1 c2) (make-comp (- (comp-r c1) (comp-r c2)) (- (comp-i c1) (comp-i c2)))) (define (comp* c1 c2) (make-comp (+ (* (comp-r c1) (comp-r c2)) (* -1 (comp-i c1) (comp-i c2))) (+ (