• 検索結果がありません。

Microsoft PowerPoint pptx[読み取り専用]

N/A
N/A
Protected

Academic year: 2021

シェア "Microsoft PowerPoint pptx[読み取り専用]"

Copied!
40
0
0

読み込み中.... (全文を見る)

全文

(1)

情報処理Ⅱ

情報処理Ⅱ

第8回

2009年12月7日(月)

2009年12月7日(月)

(2)

本日学ぶこと

本日学ぶこと

関数と変数

目的

目的

 関数を自分で定義し,変数の利用方法・範囲を明示的に制限 することで 適切な機能分割(モジュール化 再利用)を図る することで,適切な機能分割(モジュ ル化,再利用)を図る. 

してはいけないこと

i 関数のみで100行以上のプログラム プログラムを 読みやすくする  main関数のみで100行以上のプログラム  グローバル変数を駆使するプログラム

問題

読みやすくする ⇒ 保守性保守性向上 

問題

 多項式関数 f(x) = c0 + c1x + c2x2 + … + cnxn 実数 が与 れた き f を計算 きる と実数aが与えられたときに,f(a)を計算できる? • 次数nの異なる様々な関数に対して,求められる? 2 入p.109

(3)

関数

(F

ti )

関数

(Function)

関数の分類

 自作関数: 自分で定義する ⇒ 本日のテーマ  自作関数: 自分で定義する.⇒ 本日のテ マ  ライブラリ関数: 出来合いのもの.printfなど. 

なぜ関数を定義するのか?

なぜ関数を定義するのか?

 処理を共通化(一般化)する プ グラムの見通しをよくする  プログラムの見通しをよくする  main関数がないとプログラムは動かない 3 入pp.274-275 リp.346

(4)

関数定義の方法

関数定義の方法

構文

:

型名

型名 関数名

関数名

(

(引数並び

引数並び

) {

) {文

...}

...}

 型名は 関数の戻り値の型 値を返さないときは voidvoidと書く  型名は,関数の戻り値の型.値を返さないときは,voidvoidと書く.  引数並びは,「型名 変数名」をカンマで区切ったもの. 引数がないときは voidvoidと書く 引数がないときは,voidvoidと書く.

 例: double double myatofmyatof(const char *str0) {…}(const char *str0) {…}  例: void procedure(void procedure(intint xx intint y) { }y) { }

 例: void procedure(void procedure(intint x, x, intint y) {…}y) {…}

一括の変数宣言と異なり括の変数宣言と異なり, このintは省略できない.

4

(5)

id型

void型

 

void

void

は「何もない」や「無効な値」を表す型名

  ×× void x;void x;   ×× void x;void x;   ○○ void *x;void *x; 

用途

用途

 関数が引数や戻り値を持たないことを明示するとき id ii (i )

• void exitexit(int status);

• void procedure(void);void procedure(void); プログラムを終了するライブラリ関数.通常,exit(0);exit(0); もしくは exit(1);exit(1); のいず  任意のポインタ型を表現するとき • • void *p;void *p; もしくは exit(1);exit(1); のいず れかで呼び出す.

• void *mallocmalloc(size_t size);

5

(6)

関数の呼び出し

関数の呼び出し

関数定義の例:

double f(double x) {return x+1;}

double f(double x) {return x+1;}

double f(double x) {return x+1;}

double f(double x) {return x+1;}

関数呼び出しの例:

b=f(a);

b=f(a);

 x を関数 f の仮引数仮引数(parameter) 変数aの値を引数として, 関数fを呼び出し,その戻  x を関数 f の仮引数仮引数(parameter), a を関数 f の実引数実引数(argument) という.これらを区別する必要のないときは,ともに引数引数という. 関数 を呼び出し,その戻 り値を,変数bに代入する. という.これらを区別する必要のないときは,ともに引数引数という. • 仮引数の宣言には型名も書く.実引数には書かない.  x = a; の代入を行ってから 関数本文の処理に入る 関数  x = a; の代入を行ってから,関数本文の処理に入る.関数 の処理が終われば,変数 x (のオブジェクト)は消滅する.  x = f(x); と書いてもよい このとき 仮引数の x と 実  x = f(x); と書いてもよい.このとき,仮引数の x と,実 引数の x (あらかじめ定義しておく)は,別のオブジェクトであ る. 6 入pp.277-278 リpp.347-348

(7)

t

return

関数処理中に

return

return 値

;

;

があれば,そこで関数の処理

を終え,値を

戻り値

戻り値

(return value)とする.

を終え,値を

戻り値

戻り値

(return value)とする.

 値の前後にカッコは不要.

 戻り値の型がvoidなら return;return; と書ける  戻り値の型がvoidなら, return;return; と書ける.

 戻り値の型がvoid以外なら,必ずreturn 値;で処理を終え

るように書く るように書く.

7

(8)

引数の授受

引数の授受

Cの関数呼び出しでは必ず

値渡し

値渡し

(call by value)にな

る.

る.

 値渡し: 実引数のコピーコピーが仮引数に格納される.その後,仮 引数の値を変更しても,実引数の値には影響しない. 引数の値を変更しても,実引数の値には影響しない.  

参照渡し

参照渡し

(call by reference)をしたければ,ポインタ

値を引数とすればよい

値を引数とすればよい.

 参照渡し: 仮引数の値を変更すれば,実引数の値もそれに変 わる Cではこの意味での参照渡しをすることができないが ポ わる.Cではこの意味での参照渡しをすることができないが,ポ インタ値を渡すことで,その参照先の値を変える参照先の値を変えることができる. アドレス渡しともいう. 8 入p.277, p.285 リpp.347-348

(9)

二つの値を交換する関数

二つの値を交換する関数

値渡し ⇒ 失敗

 引数は関数内の仮引数にコピーされる  引数は関数内の仮引数にコピ される.  関数内の仮引数の中で,値を交換しても,関数の外のオブジェ クトは変更されない クトは変更されない. 

参照渡し ⇒ 成功

関数の仮引数は 指し示す先を持つ  関数の仮引数は,指し示す先を持つ.  「*ポインタ変数 = 値」とすることで,ポインタ変数が指し示す (関数の外の)オブジェクトに値を代入する (関数の外の)オブジェクトに値を代入する. 9 swapint.c

(10)

値渡しで失敗する理由(1)

値渡しで失敗する理由(1)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ x = y; x = y; y = y = tmptmp;; } } } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 10 main 入p.230

(11)

値渡しで失敗する理由(2)

値渡しで失敗する理由(2)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ y = -1 x = 1 x = y; x = y; y = y = tmptmp;; } } } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 11 main 入p.230

(12)

値渡しで失敗する理由(3)

値渡しで失敗する理由(3)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ y = -1 x = 1 x = y; x = y; y = y = tmptmp;; } } tmp } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 12 main 入p.230

(13)

値渡しで失敗する理由(4)

値渡しで失敗する理由(4)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ y = -1 x = 1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 13 main 入p.230

(14)

値渡しで失敗する理由(5)

値渡しで失敗する理由(5)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ y = -1 x = 1 x = -1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 14 main 入p.230

(15)

値渡しで失敗する理由(6)

値渡しで失敗する理由(6)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ y = -1 x = 1 x = -1 y = 1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 15 main 入p.230

(16)

値渡しで失敗する理由(7)

値渡しで失敗する理由(7)

コード(抜粋)

 voidvoid swapint badswapint bad((intint xx intint y)y) 

 void void swapint_badswapint_bad((intint x, x, intint y) y)

{ {

int

int tmptmp;pp;;; swapint bad

tmp tmp = x;= x; p _ y = -1 x = 1 x = -1 y = 1 x = y; x = y; y = y = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint bad

swapint bad(x(x y);y); x = 1 y = -1

swapint_bad

swapint_bad(x, y);(x, y);

main y 1 x 1 16 main 入p.230

(17)

参照渡しで成功する理由(1)

参照渡しで成功する理由(1)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 17 main リp.356

(18)

参照渡しで成功する理由(2)

参照渡しで成功する理由(2)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 18 main リp.356

(19)

参照渡しで成功する理由(3)

参照渡しで成功する理由(3)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 19 main リp.356

(20)

参照渡しで成功する理由(4)

参照渡しで成功する理由(4)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = 1 y = -1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 20 main リp.356

(21)

参照渡しで成功する理由(5)

参照渡しで成功する理由(5)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = -1x = 1 y = -1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 x 1 21 main リp.356

(22)

参照渡しで成功する理由(6)

参照渡しで成功する理由(6)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = -1x = 1 y = -1y = 1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 x 1 y 1 22 main リp.356

(23)

参照渡しで成功する理由(7)

参照渡しで成功する理由(7)

コード(抜粋)

 voidvoid swapint goodswapint good((intint **pxpx intint **pypy)) 

 void void swapint_goodswapint_good((intint pxpx, , intint pypy) )

{ {

int

int tmptmp;pp;;; swapint good

tmp tmp = *= *pxpx;; swapint_good py px * *pxpx = *= *pypy;; * *pypy = = tmptmp;; } } tmp=1tmp } }   x x = 1, y = = 1, y = --1;1; swapint good

swapint good(&x(&x &y);&y); x = -1x = 1 y = -1y = 1 swapint_good

swapint_good(&x, &y);(&x, &y);

main y 1 x 1 x 1 y 1 23 main リp.356

(24)

i 関数の型

main関数の型

main関数の(戻り値の)型は,int とする.

 void main とする本も多いが 規格上適切ではない  void main とする本も多いが,規格上適切ではない. 

正常終了は

return 0;

return 0;

と書き,

異常終了は

return 1;

return 1;

と書くのが一般的

異常終了は

return 1;

return 1;

と書くのが一般的.

main関数が返す値,およびexit関数の引数は,

終了ステ タス

(exit status)と呼ばれる

終了ステータス

(exit status)と呼ばれる.

 Linuxなら,コマンド実行後,「echo $?」を実行することで その値を確認できる その値を確認できる.  「コンパイルが成功したときに限り,ファイルを実行する」が 一つのコマンドで書ける 一つのコマンドで書ける 24 リpp.359-362

(25)

関数定義の順番

関数定義の順番

呼び出す関数は,呼び出す前に(プログラムファイルの上の

ほうで)宣言されていなければならない.

ほうで)宣言されていなければならない.

 宣言や定義がない場合は,intint 関数名関数名();(); とみなして呼び 出しを試みる. 出しを試みる. 

対策

 呼び出す順序に注意して関数を並べる  呼び出す順序に注意して関数を並べる.  関数プロトタイプを使用する. 25

(26)

関数プロトタイプ

「関数原型」

関数

トタイ

(Function prototype)

「関数原型」 ともいう 

構文

:

型名

型名 関数名

関数名

(

(引数の型の並び

引数の型の並び

);

);

 「引数の型の並び」は 「引数(型と変数)の並び」でもよい こ セミコロンを忘れずに  「引数の型の並び」は,「引数(型と変数)の並び」でもよい.こ のとき変数名は無視される.  一般に 各関数の定義より前(上)に記述する  般に,各関数の定義より前(上)に記述する.  例: intint swapint_goodswapint_good((intint **, , intint *);*);

関数プロトタイプを用いることで

関数プロトタイプを用いることで,

 関数定義の順番を気にすることなく順番を気にすることなくプログラムを記述できる. 関数の入出力が明確になる  関数の入出力が明確になる. 26 入pp.278-279 リpp.350-351

(27)

変数

(V i bl ) 識別子 オブジ クト

変数

(Variable)・識別子・オブジェクト

識別子

(Identifier): 変数名,関数名,型定義名など

の「名前」

の 名前」

識別子とオブジェクト

(Object)の違い

 識別子は プログラムファイル(静的)で記述される「ラベル」  識別子は,プログラムファイル(静的)で記述される「ラベル」  オブジェクトは,プログラム実行中(動的)に生成される「実体」 同 の識別子に対して複数のオブジ クトが生成されることも  同一の識別子に対して複数のオブジェクトが生成されることも ある.

宣言

宣言

により 変数ならそのオブジ クト 関数ならその実行

 

宣言

宣言

により,変数ならそのオブジェクト,関数ならその実行

コードが,記憶域(メモリ)上に割り当てられるとき,

その宣言を特に

定義

定義

という

その宣言を特に

定義

定義

という.

 関数プロトタイプや,externを用いた変数や関数の宣言, 構造体などの独自型定義は この意味で定義ではない 27 構造体などの独自型定義は,この意味で定義ではない. 入p.223 リp.37, pp.102-103

(28)

変数を宣言 定義する際の注意点

変数を宣言・定義する際の注意点

型は何か?

グローバルかローカルか?

グローバルかローカルか?

auto(自動)かstatic(静的)かextern(外部)か?

28 リpp.104-106

(29)

グロ バル変数とロ カル変数

グローバル変数とローカル変数

各変数は,定義された位置によって,有効範囲

(scope)を

持つ.

持つ.

 グローバル変数 • あらゆるブロックの外で定義された変数 • あらゆるブロックの外で定義された変数. • 有効範囲はファイル末尾まで.  ロ カル変数 「ブロックの中」とは, { と }で  ローカル変数 • ブロックの中で定義された変数. 有効範囲はブロ ク終了まで { と }で 挟まれた領域のこと • 有効範囲はブロック終了まで. グ バ l b l 大域的 あらゆるブ クの外 関数の仮引数も ローカル変数  グローバル - global - 大域的 - あらゆるブロックの外  ローカル - local - 局所的 - あるブロックの中 29 入pp.280-281 リpp.111-114

(30)

識別子の宣言に関するル ル

識別子の宣言に関するルール

グローバルに同一の識別子を複数宣言できない.

一つのブロック内に 同一の識別子を複数宣言できない

つのブロック内に,同

の識別子を複数宣言できない.

関数はブロック内で定義できない.必ずグローバル区間での

定義となる

定義となる.

 GCC(演習室のコンパイラ)では,関数の中に関数を定義できる が 使用しないこと! が,使用しないこと! 

ブロック内に変数を定義するときは,それより外にある同一

の識別子と重複してもよい

の識別子と重複してもよい.

 ただし,外にある同一の識別子は参照できない. ジ 化 関 有 な  モジュール化に関して有用なルール. 30 リp.114, p.225

(31)

型の属性

型の属性

記憶域クラス

 extern static auto register  extern, static, auto, register

型修飾子

const volatile

 const, volatile

:

extern void function1(const char *);

extern void function1(const char *);

i t

(

id) { t ti

i t

0

}

i t

(

id) { t ti

i t

0

}

int x(void) {static int c=0; ...}

int x(void) {static int c=0; ...}

31

(32)

記憶域クラス(1)

記憶域クラス(1)

 

auto

auto

: そのオブジェクトの生存期間は自動記憶域期間で

ある.

ある.

 積極的にautoを書くことはない.  

static

static

: そのオブジェクトの生存期間は静的記憶域期間

 

static

static

: そのオブジェクトの生存期間は静的記憶域期間

である.

 必要なときに使う  必要なときに使う.  

extern

extern

: 他の場所で宣言された識別子を使用する.

分割 パイ 不可欠 プログラムが複数のソースファイルで 構成されることがある.大規模プログ ラミングでは当たり前だが,本授業で  分割コンパイルで不可欠.  externとstaticは,関数に 対しても指定できる ラミングでは当たり前だが,本授業では実例を出さない. 対しても指定できる. 32 リp.107

(33)

記憶域クラス(2)

記憶域クラス(2)

静的記憶域期間 (

静的変数

静的変数

static変数)

 staticを指定した変数と グローバル変数が該当する  staticを指定した変数と,グロ バル変数が該当する.  プログラムの実行に先立ち,オブジェクトが生成され,初期値が設定 される.プログラム終了まで破棄されない.  初期値を指定しないオブジェクトには 0 が代入される.  初期値は,コンパイル時に計算可能な定数式でなければならない. 

自動記憶域期間 (

自動変数

自動変数

auto変数)

 autoを指定した変数,staticやexternの指定なくブロック内で定 義した変数と,関数の仮引数が該当する.  宣言文を実行するたびに,オブジェクトが生成され,初期値があれば 毎回初期化される ブ クを終えると 破棄される 毎回初期化される.ブロックを終えると,破棄される.  初期値を指定しないオブジェクトの初期値は不定. 初期値は任意の計算式でよい 33  初期値は任意の計算式でよい. 入pp.226-227 リp.110, pp.115-120

(34)

有効範囲?記憶域クラス?

有効範囲?記憶域クラス?

ここで問題

(小テストではありません)  グローバルな静的変数は 定義《 できる ∥ できない 》  グロ バルな静的変数は,定義《 できる ∥ できない 》.  グローバルな自動変数は,定義《 できる ∥ できない 》.  ロ カルな静的変数は 定義《 できる ∥ できない 》  ローカルな静的変数は,定義《 できる ∥ できない 》.  ローカルな自動変数は,定義《 できる ∥ できない 》. 

ローカルな静的変数の用途

 ブロック内で情報を保存しておき,あとで利用する.  動的に確保することなく,配列領域を戻り値とする.  自動変数では扱いきれない大容量オブジェクト(100万個の int配列など)を取り扱う. 34 リpp.118-119

(35)

配列の自動変数(1)

配列の自動変数(1)

関数の中で配列変数を定義すれば,関数処理の中で確保さ

れ,関数処理が終わると破棄されるような配列が作られる.

れ,関数処理が終わると破棄されるような配列が作られる.

void print_message(void) void print_message(void) { { { {

char message[] = "Wakayama"; char message[] = "Wakayama"; printf("%s

printf("%s¥¥n"n" message);message); printf( %s

printf( %s¥¥n , message);n , message); }

}

print_message

message

'W'

'a'

'k'

'a'

'y'

'a'

'm' 'a'

'¥0'

(36)

配列の自動変数(2)

配列の自動変数(2)

関数の仮引数に配列変数を書けば,その配列と型が適合す

るポインタ変数になる.

るポインタ変数になる.

void

void print_messageprint_message(char message[])(char message[]) {

{ 宣言の形は不完全型

printf

printf("%s("%s¥¥n", message);n", message); } } 宣言の形は不完全型 実体はポインタ変数  要素数(多次元配列の場合は左端のみ)は無視される. 要素数なし・初期化なし(不完全型)でもよい. print_message

message

'W'

'a'

'k'

'a'

'y'

'a'

'm' 'a'

'¥0' 36

(37)

多項式の計算

多項式の計算

仕様

 多項式関数 f(x) = c xn + c xn-1 + + c x + c  多項式関数 f(x) = cnx + cn-1x + … + c1x + c0 と実数aが与えられたときに,f(a)を計算する. 

考え方

考え方

 係数 c0, c1, c2, … cn を,配列変数で保持する. • c は xのi次の係数 • ci は,xのi次の係数  f(a) = (…(cn * a) + cn-1) * a + …) + c0 により求め(ホーナー法) 乗算の回数を減らす により求め(ホーナー法),乗算の回数を減らす. • v0 = cn • v v * a + c • v1 = v0 * a + cn-1 • v2 = v1 * a + cn-2 = cn*a*a + cn-1*a + cn-2 * • vi = vi-1 * a + cn-i 37 polynomial1.c

(38)

多項式の計算を行う関数

多項式の計算を行う関数

係数の配列(の先頭を

コード(抜粋)

 double calc(double f[]double calc(double f[] intint sizesize double x)double x)

係数の配列(の先頭を 指し示すポインタ変数)

 double calc(double f[], double calc(double f[], intint size, double x)size, double x)

{ {

double

double valval;; f の配列の要素数xの次数 + 1) f(x) を求める

ための の値 ; ; int int ii;; val

val = f[size = f[size -- 1];1];

(xの次数 + 1) ためのxの値 v ← cn

for(

for(ii = size = size -- 2; 2; ii >= 0; >= 0; ii----){){ val

val = = valval * x + f[* x + f[ii];]; }

} v ← v*x + cn-i

} }

return

return valval;; } } v = f(x) = cnxn + cn-1xn-1 + … + cnx + c0 } } 

関数定義の効果:異なる次数の多項式でも,一つの(

Cの)関

calcにより 値を求められる

calcにより,値を求められる.

38 polynomial2.c

(39)

変数の有効範囲の補足

変数の有効範囲の補足

破棄されるまでは,ブロックの外からでも(ポインタなどで間

接的に)オブジェクトの参照や値の書き換えができる.

接的に)オブジェクトの参照や値の書き換えができる.

⇒ ポインタによる参照渡しが可能となる.

関数内の自動変数に対応するオブジェクトは 関数処理が

関数内の自動変数に対応するオブジェクトは,関数処理が

行われるたびに生成される.

⇒ 「再帰呼び出しをする関数」が構成できる

⇒ 「再帰呼び出しをする関数」が構成できる.

何らかの関数の中

message

何らかの関数の中 message[0] = 'w'; message[0] = 'w'; としてよい

'W'

' '

'k'

' '

' '

' '

' ' ' '

'¥0'

g

k

としてよい 39

'W'

'a'

'k'

'a'

'y'

'a'

'm' 'a'

'¥0'

wakayama

リp.121

(40)

まとめ

まとめ

関数を自分で定義し呼び出すとき,どのような点に注意しな

ければならないか?

ければならないか?

参照渡しにはポインタが不可欠であるのはなぜか?

グロ バル変数とロ カル変数 静的変数と自動変数の違

グローバル変数とローカル変数,静的変数と自動変数の違

いは何か? グローバルな自動変数は存在するか?

関数の中で配列を扱うとき どのような点に注意しなければ

関数の中で配列を扱うとき,どのような点に注意しなければ

ならないか?

40

参照

関連したドキュメント

非自明な和として分解できない結び目を 素な結び目 と いう... 定理 (

問題はとても簡単ですが、分からない 4人います。なお、呼び方は「~先生」.. 出席について =

○ 4番 垰田英伸議員 分かりました。.

ヒュームがこのような表現をとるのは当然の ことながら、「人間は理性によって感情を支配

このような情念の側面を取り扱わないことには それなりの理由がある。しかし、リードもまた

なお、相続人が数人あれば、全員が必ず共同してしなければならない(民

( 同様に、行為者には、一つの生命侵害の認識しか認められないため、一つの故意犯しか認められないことになると思われる。