プログラミング言語論0518

プログラミング言語論
第六回
理工学部
情報システム工学科
新田直也
課題1の解答

整数剰余(x % y)を計算する While プログラム
z = x;
while (y < z) {
c = 0;
d = y;
while (d < z) {
c++;
d++;
}
z = c;
}
if (y == z) {
z = 0;
}
c = z – y;
z –= y;
課題2の解答
int x, y, z, f;
scanf(“%d”, &x);
for (y = 2; y < x; y++) {
f = 1;
for (z = 2; z < y; z++) {
if (y % z == 0) {
f = 0;
break;
}
}
if (f == 1) {
while (x % y == 0) {
printf(“[%d]”,y);
x /= y;
}
}
}
if (x != 1) printf(“[%d]”,x);
// yが素数のときf == 1
// yは素数でない
// yが素数である場合
// yでxを割れるだけ割る
// 最後の素因数
手続き

手続き:一連の処理を行う機能単位.





FORTRAN, Basic
Pascal
C, C++
Java
---------
サブルーチン
プロシージャ(手続き)
関数
メソッド
名前をつけることができ,その名前で何度でも呼び
出すことができる.
手続きの有効性

z = x * y を行うWhile プログラム
z = 0;
c = 0;
while (c < y) {
d = 0;
while (d < x) {
z++;
d++;
}
c++;
}
int plus(int z, int y) {
int d = 0;
while (d < y) {
z++;
d++;
}
return z;
}
main() {
int z = 0;
int c = 0;
while (c < y) {
z = plus(z, y);
c++;
}
}
手続きの定義と呼び出し
int plus(int z, int y) {
int d = 0;
while (d < y) {
z++;
d++;
}
return z;
}
関数plusの定義(関数宣言)
main() {
int z = 0;
int c = 0;
while (c < y) {
z = plus(z, y);
c++;
}
}
関数plusの呼出し
手続きの引数と戻り値
int plus(int z, int y) {
int d = 0;
while (d < y) {
z++;
d++;
}
return z;
}
main() {
int z = 0;
int c = 0;
while (c < y) {
z = plus(z, y);
c++;
}
}
仮引数:定義側の引数
戻り値
実引数:呼出し側の引数
手続きの型
int plus(int z, int y) {
int d = 0;
while (d < y) {
z++;
d++;
}
return z;
}
main() {
int z = 0;
int c = 0;
while (c < y) {
z = plus(z, y);
c++;
}
}
すべての関数は型を持つ.
関数定義と呼出し側で型が一致
してなければならない.
前方参照とプロトタイプ宣言
int plus(int z, int y) {
int d = 0;
while (d < y) {
z++;
d++;
}
return z;
}
後方参照
main() {
int z = 0;
int c = 0;
while (c < y) {
z = plus(z, y);
c++;
}
}
int plus(int, int);
プロトタイプ宣言
main() {
int z = 0;
int c = 0;
while (c < y) {
z = plus(z, y);
c++;
}
前方参照
}
int plus(int z, int y) {
int d = 0;
while (d < y) {
z++;
d++;
}
return z;
}
値を返さない手続き

値を返さない手続きは以下のように定義する.



C, C++, Javaの場合: 戻り値を void に.
VBの場合: サブルーチンプロシージャとして定義.
値を返さない手続きの呼出し.
void view(int a) {
printf(“%d\n”, a);
}
main() {
view(10);
}
式として扱われない.
(値を評価できない.)
値呼出しと参照呼出し

値呼出し:
関数に実引数の値を渡すが,呼出しによって実引数の値が
変更されることはない.
12
:
12 12
x
func(a);
a
:
void func(int x) {

参照呼出し:
:
関数に実引数の参照(ポインタ)を渡す.関数内部で実引数
の値が変更することが可能である.
:
12
func(&a);
a
:
void func(int *x) {
参照渡し(2)

厳密には参照渡しも値渡しの一種である.
14
12
a
1536
1536
:
func(&a); &a = 1536
:
x
void func(int *x) {
:
*x = 14;
1次元配列の引数渡し

配列名は配列の先頭アドレス.
main() {
int a[100];
:
func(a);
:
}
void func(int x[]) {
受け側は要素数を指定しない.
int *x で受けても良い.
いずれにせよサイズがわからな
いので注意.
2次元配列の引数渡し

配列名は配列の先頭アドレス.
main() {
int a[100][10];
:
func(a);
:
}
:
0xffff番地
a[1][0]
a[0][9]
:
a[0][1]
int が 10 個分
a[0][0]
0x0000番地
void func(int x[][10]) {
受け側は最高次元の要素数を
指定しない.
再帰呼び出し(1)

(もちろん)関数の中で関数を呼出すことが可能.
main() {
printf(“%d\n”, max3(12, 15, 11));
}
int max3(int x, int y, int z) {
return max2(max2(x, y), z);
}
int max2(int x, int y) {
if (x >= y) return x; else return y;
}
再帰呼び出し(2)

関数の中で自分自身を呼び出すとどうなるか?
int factorial(int x) {
if (x == 1) {
return 1;
} else {
return x * factorial(x – 1);
}
}