Transcript 戻り値

C言語
第11講
生物機能制御学講座 濱田
農学部7号館209室
1
本日の講義内容
• おさらい
関数など
テキスト Lesson 8
• 関数つづき
テキスト Lesson 8
• プログラムの作成
• アンケート
2
アンケート結果
質問および要望
1.「引数」の意味が良くわからない
2.「戻り値」の意味が良くわからない
3.第11講の関数の内容について
わかった(特に問題ない) 13名
むずかしい
7名
ノーコメント
3
関数
プログラムが、以下の構成の場合!
1) 同じ内容のブロックを何度も
記述しないといけない
2) 1つのブロックが冗長
すっきりしたプログラムを作成したいですね!
すっきりしたプログラムは、デバッグ効率を
格段に向上させ、メンテナンスも楽になります!
main()
{
Block_A
・・・・
Block_A
Block_A
・・・・
Block_A
}
1)や2)のブロックをmain()以外の箇所に記載(関数)し、main()
の実行したい当該箇所とリンクする! コーディングがすっきりします
4
関数のしくみ
main()
{
A1; ・・・
・・・・
A1; ・・・
・・・・
A1; ・・・
}
F_A()
詳述
処理の呼び出し
{
A1; ・・・ AN;
}
AN;
AN;
AN;
restructure
何度も A1; ・・・ AN;がある
(A1;・・・AN;はBlock!)
F_A() : 関数!
実は、main()も関数!
main()
{
粗筋
F_A();
・・・・
F_A();
・・・・
F_A(); 次の処理へ
}
5
関数の定義
構文 <#include文からmain()の間に記載>
戻り値の型 関数名(仮引数リスト)
z  f x, y
{
変数宣言;
int f(int x, int y)
(例1)
intに限りません
{
文;
int z;
return 式or値;
z = x + y;
}
return z;
← 戻り値
}

void: 該当なし!
戻り値なし;引数なし
voidは省略可能!
void output(void)
(例2)
{
printf(“関数名output!\n”);
} 戻り値なしの場合、return 文を省略可 6

関数の仕様パターン
構文 <#include文からmain()の間に記載>
戻り値の型 関数名(仮引数リスト)
{
変数宣言;
# 戻り値
引数リスト
文;
1 ×(void)
×(void)
return 式or値;
2 ×(void)
○(変数宣言)
}
3
4
○(return) ×(void)
○(return) ○(変数宣言)
7
関数のよびだし 1
構文
1) 関数の戻り値が void
関数名(実引数リスト);
2) 関数の戻り値が 値
変数 = 関数名(実引数リスト);
関数は何度もよびだせる!
voidの実引数は空欄にする
output関数定義部
void output(void)
{
printf(“output!\n”);
}
void main()
{
output();
output(); 関数よびだし
}
関数を呼び出すと、定義しておいた処理がまとめて行なわれる8
関数のよびだし 2
void output(void)
{
printf(“output!\n”);
}
関数定義部
2) 関数の戻り値が 値
void ope1(void)
変数 = 関数名(実引数リスト); {
output(); 関数よびだし
関数はmain()中だけでなく、
}
任意の関数中からもよびだせる! main()
(カスケードできる)
{
関数よびだし
ope1();
全てのよびだしはmain()に帰着
}
構文
1) 関数の戻り値が void
関数名(実引数リスト);
関数はよびだし元よりも上記すること!
9
関数の利用(練習)
問題1 関数を用いて、以下の出力を行うプログラム
を開発してください。関数名は、任意です。
「関数のよびだし1または2」を参考に以下のアルゴ
リズムに従って作成してください。。。
<アルゴリズム>
1 main()にて任意名の関数()をよびだす
2 1の関数内にてprintfを利用して出力する
仮引数および戻り値
voidの関数を用いる
% a.out
2値を入力してください。
%
10
関数の利用 問題1
問題1のプログラム例 (主要部のみ)
void output(void) output関数定義部
{
printf(“2値を入力してください。\n”);
}
void main()
{
output();
}
関数よびだし
% a.out
2値を入力してください。
%
戻り値なし・引数なしのケース
11
関数の引数 1 (変数)
構文
戻り値の型 関数名(仮引数リスト)
void buy(int z)
(例)
intに限りません
{
printf(“%d万円です\n”,z);
}
main()
{
int x;
printf(“いくら?\n”);
x = 500;
buy(x); /*実引数:変数*/
buy(300); /*実引数:値*/
}
引数は、関数のよびだ
し元から関数内に情報
(値)を渡す。
関数はその情報に応じ
た処理を行う。
x:実引数; z:仮引数;
xとzの型は一致すること!
仮引数初期値は実引数の値
% a.out
いくら?
500万円です
300万円です
12
関数の引数 2 (変数)
構文
戻り値の型 関数名(仮引数リスト)
void buy(int a, int b) (例)
intに限りません
{
printf(“%d万円と”,a);
printf(“%d万円です\n”,b);
}
main()
{
int x;
printf(“いくら?\n”);
x = 100;
buy(x,200); /*実引数:変数*/
}
関数には複数の引数を
渡すことができる。
引数リストの順に値が
代入される。
実引数と仮引数は対応
仮引数
a
b
実引数
x
200
% a.out
いくら?
100万円と200万円です13
関数の引数 3 (なし)
構文
戻り値の型 関数名(仮引数リスト)
void output(void)
(例)
{
printf(“C言語大好き\n”);
}
main()
{
int x;
output(); /*実引数:なし*/
}
プログラムを断片化する
と、プログラムが理解し
やすくなる。引数のない
関数を用いて、プログラ
ムを分散させよう。
戻り値および引数の型
voidは、省略可能。
% a.out
C言語大好き
注意事項:C言語は、基本的に実引数の値の更新を許さない!14
残念ながら、引数は情報を流すだけ(配列は例外)。
戻り値
構文
1) 関数の戻り値が void
関数名(引数リスト);
2) 関数の戻り値が 値
変数 = 関数名(引数リスト);
関数内の計算結果(戻り値)は、
1つだけ、return 文でよびだし元
に返還される。
戻り値と受け側変数の型が一致し
なくてはならない(ここではint)。
z  f x, y 
int f(int x, int y)
{
intに限りません
int z;
z = x + y;
return z; /*戻り値z*/
}
関数定義部
main()
{
int a,b,c;
a = 4; b = 2;
c = f(a,b); 関数よびだし
}
15
関数の利用(練習)
問題2 入力された任意の2つの倍精度浮動小数の大
きい数と小さい数を判断する判別関数を作成し、大小
関係を出力するプログラムを作成してください。判別
関数の名前は任意です。
<アルゴリズム>
1 main()で2つの倍精度浮動小数を入力させる。
2 2つの数を判別関数に渡し、大小関係を検討し、関
数内で、大小関係を出力(printf)する。
判別関数は、引数あり戻り値なしの関数を用いる
16
関数の利用 問題2
問題2のプログラム例 (主要部のみ)
void hanbetsu(double x, double y)
{
if (x>y) {
printf(“%lf > %lf\n”,x,y);
else
{
printf(“%lf > %lf\n”,y,x);
}
main()
{
double a,b;
printf(“a=”); scanf(“%lf”,&a);
printf(“b=”); scanf(“%lf”,&b);
hanbetsu(a,b);
}
}
% a.out
a=11.22
b=12.33
12.33 > 11.22
}
引数あり・戻り値なしのケース
17
関数の利用(練習)
問題3 問題2のプログラムに、倍精度浮動小数2値
の四則演算を行う演算関数を加え、以下のアルゴリ
ズムに従って作成してください。関数名は、任意です。
<アルゴリズム>
1 main()にて任意の2値を入力させる(問題2で完
了)。
2 四則演算を別々に行う4つの関数を作成する。
3 main()にて関数の戻り値(四則演算結果)を出力
する。
演算関数は、引数あり戻り値ありの関数を用いる
18
関数の利用 問題3
問題3のプログラム例 (主要部のみかつ和算のみ)
double wa(double x, double y)
{
return x + y;
}
/* 差・積・除算の関数は割愛 */
void main()
{
double a,b,z;
printf("a="); scanf("%lf",&a);
printf("b="); scanf("%lf",&b);
z =wa(a,b);
printf("a + b = %lf\n",z);
/* 差・積・除算の関数よびだしは割愛 */
}
% a.out
a=1.1
b=0.11
a + b = 1.21
引数あり・戻り値ありのケース
19
関数の引数 4 (一次元配列)
構文
戻り値の型 関数名(仮引数リスト)
#define MAX 2
void output(int t[MAX])
(例)
{
仮引数:
int i;
配列名[要素数]
for(i=0;i<MAX;i++){
printf(“t[%d]=%d\n”,i,t[i]);}
}
main()
実引数:
{
配列名
int a[MAX];
a[0]=0; a[1]=1;
output(a); }
/*実引数:配列*/
変数と同様、
配列も引数に
適用可能!
要素数の設定
にはマクロを!
% a.out
t[0]=0
t[1]=1
20
関数の引数 5 (二次元配列)
構文
戻り値の型 関数名(仮引数リスト)
void output(int t[1][2])
(例)
{
仮引数:配列名[要素数] [要素数]
int i;
for(i=0;i<2;i++){
printf(“t[0][%d]=%d\n”,
i,t[0][i]);}
}
main()
実引数:
{
配列名
int a[1][2];
a[0][0]=0; a[0][1]=1;
output(a); }
/*実引数:配列*/
二次元配列も
一次元配列と
同様!
% a.out
t[0][0]=0
t[1][1]=1
21
関数の引数 6 (配列:値更新1)
構文
戻り値の型 関数名(仮引数リスト)
関数に渡された配列
は、関数の中で実引
数の更新可能!
(変数はダメ!!)
void vector(int t[2])
(例)
{
t[0]=3; t[1]=6; /*値の更新*/
}
main()
% a.out
{
a[0]=0 a[1]=1
int a[2];
*a[0]=3 *a[1]=6
a[0]=0; a[1]=1;
printf(“a[0]=%d a[1]=%d\n”,a[0],a[1]);
vector(a);
printf(“*a[0]=%d *a[1]=%d\n”,a[0],a[1]);
}
22
関数の引数 6 (配列:値更新2)
構文
戻り値の型 関数名(仮引数リスト)
仮引数リストで、変
更したくない引数に
(例)
constを添付すると、
実引数の変更が不
可となる!
void vector(const int t[2])
{
t[0]=3; t[1]=6; /*値の更新*/
}
% a.out or Error!
main()
a[0]=0 a[1]=1
{
*a[0]=0 *a[1]=1
int a[2];
a[0]=0; a[1]=1;
printf(“a[0]=%d a[1]=%d\n”,a[0],a[1]);
vector(a);
printf(“*a[0]=%d *a[1]=%d\n”,a[0],a[1]);
23
}
変数とスコープ1
#include <stdio.h>
int a;
void func(void)
{
int b;
変数 bの値が
・・・・・・
保障される範囲
}
void main()
{
int c
変数 cの値が
・・・・・・
保障される範囲
}
変数 aの値はプログラ
ム全域で保障される
範囲:スコープ
変数 変数種類
a
b
C
グローバル変数
ローカル変数
ローカル変数
異なる関数内のローカル変数は
仮引数名を含めて、名前が重複
してもよい。異なる変数である。
24
変数とスコープ2
#include <stdio.h>
int a;
void func(void)
{
ローカル変数
int a;
aの値が保障
a = 1;
される範囲
}
void main()
{
a = 0; グローバル変数
・・・・・・
aの値が保障
}
される範囲
変数種類
値
グローバル変数 a
ローカル変数
a
0
1
変数値を更新するとき!
ローカル変数で宣言されている場合
は、ローカル変数を更新!
否は、グローバル変数を更新
グローバル変数とローカル変数
は同じ名前にしてもよい。が、
混乱を招くので避けよう! 25
変数とスコープ3
変数の種類
記憶クラス
グローバル変数
(大域変数)
ローカル変数
(局所変数)
記憶(値)保存期間
プログラム起動時から終了まで
static
プログラム起動時から終了まで
auto
宣言されてから関数終了まで
ローカル変数 static宣言の構文
static int a;
/*例*/
ローカル変数は関数がよびだされる度、変数や配列が
準備され、関数終了次第、廃棄(値は消滅)される。
一方、staticローカル変数は、値が保持される!
26
関数の利用(練習)
問題4 配列と関数を用いて、任意個数の数列の
合計と平均を算出するプログラムを開発してくだ
さい。
<アルゴリズム>
1 main()にて任意個数の数列を入力し、配列に
格納する。
2 配列を合計用関数と平均用関数に渡す。
3 関数で合計と平均を算出し、計算結果をmain()
に戻す。
4 main()にて関数の戻り値(合計と平均)を出力
する。
演算関数は、引数あり戻り値ありの関数を用いる
27
関数の利用(練習)
問題5 任意の関数を用いて、前作の直線回帰の
プログラムをすっきりと再構築しなおしてください。
<アルゴリズム>
1 関数を用いて、入力・計算・出力部に分割
2 さらに各関数を再分割(平均・和算など)
%
%
%
%
%
cp 元file名 新file名 ← file複製命令
lp file名
← file印刷命令
a.out < infile名
← file入力命令
a.out > outfile名
← file出力命令
a.out < infile名 > outfile名
28
次回の予定
○ 次回
関数つづき
おさらい
(テキスト:Lesson8~)
29
おわりに
• さて、問題です。
1.ローカル変数とグローバル変数って何?
2.仮引数の配列は関数内で実引数を
更新できる?
3.スコープって何?
3.その他、質問など
30