Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "4. 合成データ:構造体 プログラミング論I."— Presentation transcript:

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

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

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

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

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

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

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

8 例題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 座標値を選ぶ

9 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)

10 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;

11 練習 (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 という名前で定義せよ そのコンストラクタは何か そのセレクタは何か

12 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 フィールド

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

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

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

16 プログラム設計法:データの解析と定義 処理対象が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 では定義済

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

18 プログラム設計法: テンプレート 本体より先にまずテンプレートを設計 ヘッダと,可能な全セレクタ式を列挙した本体を記述。
各セレクタ式は適切なセレクタを入力の構造体データに適用したもの (関数が入力の構造体データの要素を使う計算をすることを反映) 入力は 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座標フィールド値も同様

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

20 プログラム設計法: 本体定義 基本演算や他の関数を使い答を計算する式を定式化 利用可能なデータは入力、セレクタ式の結果 テンプレート:
本体定義: (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)))))

21 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乗を加え平方根を求めている

22 プログラム全体(例) 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));

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

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

25 これまでの 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 構造体名 (フィールド並び)) 変数 定数 プリミティブ演算の適用 定義した関数の適用 条件式

26 課題

27 課題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 ]))

28 解答例 (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)))

29 課題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"

30 解答例 (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”

31 課題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"

32 解答例 (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”

33 課題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

34 課題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))

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

36 解答例 (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))) (+ (


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

Similar presentations


Ads by Google