基礎プログラミング

基礎プログラミング
第11回(2007年5月21日)
関数(静的メソッド:static method)
Main(){}の殻を打ち破る
1
数学における関数
たとえば2次関数は
f x   3x  2 x  10
2
x = 2 を入力すると -2 が出力される
たとえば「平面」の関数は
f x, y   5x  4 y  9
x = 2, y = 3 を入力すると 13 が出力される
2
プログラミングにおける関数とは?
何かを入力すると
あらかじめ定められた処理をその入
力に対して施し
結果を出力する
入力
(引数)
関数
出力
(返値)
3
プログラミングでは,
どういう場合に関数を使うか
同じような処理をまとめておき再利用したい場合

ある意味をもつ処理をひとくくりにまとめることが多い
関数としてまとめて行う処理の例:








身長と体重を入力すると,BMI値を返す関数
3辺の長さを入力すると,三角形の角を判定する関数
入力された秒数だけSleep()で待つ関数
ユーザに正の数値を入力させる(入力してもらうまで何度
でも聞き直す)関数
黄金比を返す関数
累乗を計算してくれる関数
文字列をコピーしてくれる関数
4
何もしない関数...
関数を使うとなにがうれしい?
プログラムのコードが短く,シンプルになる
Array.Sort(ary); //配列を並べ替える関数を使う
int a = Math.Pow(x,n);
// xのn乗を計算する関数を使う
誰かが作ってくれた関数を使うのは簡単.

データを準備しておいて,()内に渡すだけでよい
関数を自分で作るにはどうするか?

関数の定義を行う必要がある
5
関数の作り方(抽象的な説明)
static 返値の型 関数名(引数の型1 引数1,
引数の型2 引数2,・・・) {
関数の中身の記述;
return 返値;
}
static ... =静的な(「クラスに属する」)
返値の型...=この型の返値を返す,
関数名... という名前の関数を定義する.
引数は[引数の型1]の引数1,[引数の型2]の
引数2,... をとり,最後に返値を返す.
6
関数の作り方(返値がintのとき)
以下のように定義する
static int 関数名(引数型1 引数1,・・・) {
関数の中身の記述;
return 返値;
}
static int Func(int x, int y){ // 例(スライド 2p)
int temp;
temp = 5 * x + 4 * y;
return temp;
}
7
関数の作り方(返り値なし: void)
以下のように定義する
static void 関数名(引数型1 引数1,・・・) {
関数の中身の記述;
return; //return; は省略可能
}
例:指定した秒数だけ待つ関数
static void WaitSec(int sec){
System.Threading.Thread.Sleep(sec*1000);
} //returnは省略
8
作成した関数の使い方
作成した関数を引数をつけて呼び出す
int retvalue = Func(2,3);
Console.WriteLine(“f(2,3)={0}”,
retvalue);
WaitSec(10); //10秒まつ
9
関数を作るときの注意
関数の中には関数を定義できない

Main(){} 関数の{ }の外で,かつ
class XXX { } の中にしか書けません
namespace NS
class A
static void Main()
class B
static void Bar()
static int Foo()
10
関数呼び出しの入れ子
class A
static void Main()
float f = Dist(1,1,4,5);
Console.WriteLine(“dist: ”+f);
static float Dist(x1,y1,x2,y2)
float d = Sqrt((x2-x1)*(x2-x1)
+ (y2-y1)*(y2-y1));
return では必ず呼
び出した箇所の次
の位置に処理が
戻る

別の場所に飛んだ
り,戻らなくするこ
とはできない
return d;
static float Sqrt(float x)
float sqrt = Math.Sqrt(x);
return sqrt;
11
参考:Main()も関数のひとつです
プログラム実行時に,最初に呼ばれる関数が
Main()
途中終了するのに,以前 return; を使った

returnは関数・メソッドを抜けるための命令
 breakに似ているが,breakはループを抜ける命令
Main()関数に渡す引数とは?(参考)

コマンドプロンプトから実行するときの「コマンドラ
イン引数」が渡される
12
本講義では「関数」=「静的メソッド」
用語の定義はプログラミング言語によってまちまち




メソッド(Method) =手段
ファンクション(Function)=関数
プロシージャ(Procedure)=手続き
サブルーチン(Subroutine) =副次処理
オブジェクト指向プログラミング言語では「Function」
や「Procedure」より「Method」のほうが一般的

FunctionとProcedure/Subroutineの違いは,返値がある
かないか,といったニュアンス(どちらも古い言葉)
本講義では今後,簡単のため「静的メソッド」のこと
を「関数」と呼ぶ

以前の資料では単に「メソッド」と呼んでいたこともある
13
関数とのデータ受け渡し方法
関数内部で使えるように渡す方法
「引数」として渡す
 (静的変数を介する)

関数内部で処理したデータを外に
渡す方法
「返値」として渡す
 (静的変数を介する)

14
引数と返値について
Call by Value (値渡し)


渡すときに中身をコピーして渡す
数値の場合
Call by Reference (参照渡し)


渡すときにはコピーせず,リンクのみ渡す
文字列や配列,List,Dictionary等の場合
どうしても数値を「参照渡し」したいという
場合は上のキーワードを覚えておくとよい.
滅多に使わないので,引数と返値は
「 = と同じルールで受け渡す」と覚えれば十分.
15
確認プログラム
static void Double(int x){
x *= 2;
}
static void Main(...){
int a = 5;
Double(a); //値渡し
Console.WriteLine(a);
}
static void Double(int[] x)
{
for( int i=0; i<x.Length;
i++) x[i] *= 2;
}
static void Main(...){
int[] a = new
int[3]{2,3,5};
Double(a); //参照渡し
for(int i=0; i < 3; i++)
Console.WriteLine(a[i]);
}
16
(無理に数値を参照渡ししなくても)
返値で結果を返せばよい
static void Double(int x){
x *= 2;
}
static int Double(int x){
x *= 2;
return x;
}
static void Main(...){
int a = 5;
Double(a); //値渡し
Console.WriteLine(a);
}
static void Main(...){
int a = 5;
a = Double(a);
Console.WriteLine(a);
}
17
関数のオーバーロード
引数の数は同じで,引数の型が異なる関数
をつくることをオーバーロードといいます
static void PrintType(int value){
Console.WriteLine(“int: {0}”,value);
}
static void PrintType(String value){
Console.WriteLine(“String: {0}”,value);
}
18
静的変数とメソッドローカル変数
静的変数:すべての関数(Main()含む)から
参照できる変数

関数外で 「static 変数名」として定義する
メソッドローカル(method local)変数:関数内
{}からのみ参照できる変数

関数内で定義する(staticはつけない)
同じ変数名の静的変数とメソッドローカルな
変数があったら,メソッドローカル変数が優先
される
19
静的変数を使った例 (count)
class CountMethodCall {
static int Count = 0; // メソッドの呼出し回数カウンタ
static void Main(string[] args) {
Console.WriteLine(“{0}”, Double(5)); // =>[10]
Console.WriteLine(“{0}”, Count);
// =>[1]
Console.WriteLine(“{0}”, Double(7)); // =>[14]
Console.WriteLine(“{0}”, Count);
// =>[2]
}
static int Double(int x) {
Count++; // カウンタを1つ増やす
return x*2;
}
}
20
練習問題11-1
(コミット不要:プロジェクトは各自作成すること)
(1)ユーザに正の数を入力してもらい,その数を返
値として返す関数を定義しなさい(引数なし)


static int InputPositiveInt()
ただし,0以下の数が入力されたら,再度入力してもらうこ
と
(2)引数に指定した秒数だけ待つ関数
static void WaitSec(int sec)
を作成し,(1)(2)をMain()関数から順次呼ぶこと
で,入力秒数だけ待つプログラムをつくりなさい
21
練習問題11-2
(コミット不要:プロジェクトは各自作成)
x
n
xのn累乗(べき乗)を返す関数MyPow
をつくってください
ただし,引数(x, n), 返値 はすべて整数と
します
 static int MyPow(int x, int n)

動作確認プログラムもつくり,動作確認
しなさい

ちなみに,Math.Pow(x,n) と同じ答えが返
れば,計算は合っている
22
プロジェクトの(新規)作成方法
(1)VS2005を起動 (2)メニューから「ファイル」>「新
規作成」>「プロジェクト」を選ぶ
(3)「新しいプロジェクト」で「コンソールアプリケーショ
ン」を選び,プロジェクト名と場所を入力してOKを押す
23
Report-F [17CopyAry] (配点4)
コミットの締切は 5月26日(土)23:59
intの配列を引数とし,その配列のコピーを
返す関数CopyArrayをつくってください
static int[] CopyArray(int[] ary)
★動作確認プログラムもつくること!!
 動作確認プログラムは, 9回目(5月14日)のプリントを
参考に,本当に「コピー」できているかどうか,までを
確認可能なものにすること
(注)Array.Copy()関数の使用は禁止
(ヒント)関数内部で新しい配列の『容器』を作
成し,ループで1つ1つintの数値をコピーした
あと,return 文で「作成した配列」を返す
24