「流れ図」,「擬似言語」,「基本制御構造」は,基本情報技術者試験やプログラミング学習で必須となる重要分野です。しかし,「while文とdo while文の違いが分からない」,「値渡しと参照渡しが混乱する」,「再帰呼出しの処理の流れが苦手」という方も多いのではないでしょうか。
このページでは,基本情報技術者試験で頻出となるプログラミングの基礎について,擬似言語・Python・C#の例を用いながらシンプルに整理していきます。
- 流れ図=アルゴリズムを図で表現する方法
- 擬似言語=処理手順を簡潔に表現する記法
- 順次型・分岐型・反復型=基本制御構造
- 副プログラム=共通処理をまとめるしくみ
- 値渡し・参照渡し=引数の渡し方
- 再帰的プログラム=自分自身を呼び出す処理
後半には練習問題も用意しています。プログラムの流れを実際に追いながら理解を深めていきましょう。
流れ図とは
流れ図は,アルゴリズムを表記するために使用します。
擬似言語とは
基本情報技術者試験で使用される擬似言語の記述形式は,次のとおりです。
繰り返しの条件について
- 流れ図の場合:繰り返しを終了する条件を記述する
- 擬似言語の場合:繰り返す条件を記述する
となります。気をつけましょう。
アルゴリズムとは
アルゴリズムとは,ある問題を解く手順や計算方法のことをいいます。同じ処理結果が得られる場合でも,コンピューターに負荷をかけず,高速で,無駄なリソースを使わないアルゴリズムを採用することが重要です。
基本制御構造とは
順次型(直線型)とは
順次型は,処理を順に実行する制御構造です。
順次型の例
例)変数xに10を,変数yに5を,変数zにx+yの計算結果を代入し,zの値を表示する
流れ図の例
擬似言語の例
整数型: x, y, z
x ← 10
y ← 5
z ← x + y
z を出力
1行目:変数の宣言
2~4行目:変数に値を代入
Pythonの例
x: int; y: int; z: int
x = 10
y = 5
z = x + y
print(z)
1行目:型ヒント(省略可能)。Pythonは動的型付け言語なので,明示的な型ヒントは不要
2~4行目:変数に値を代入
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
int x, y, z;
x = 10;
y = 5;
z = x + y;
Console.WriteLine(z);
1行目:変数の宣言
2~4行目:変数に値を代入
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
15
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型: a, b, c
a ← 4
b ← 7
c ← a × 2 + b
c を出力
15
分岐型(選択型)とは
分岐型は,条件に従い処理の流れを分ける制御構造です。
二分岐型の例
例)変数xに数値を入力して,その値が80以上ならば変数rに「合格」を,それ以外ならば「不合格」を代入して表示する
流れ図の例
擬似言語の例
整数型: x
文字列型: r
x を入力
if ( x ≧ 80 )
r ← "合格"
else
r ← "不合格"
endif
r を出力
1,2行目:変数の宣言
3行目:変数xに値を代入
4~8行目:合否の判定。変数xが80以上の場合は5行目の処理を行い,それ以外の場合は7行目の処理を行う
Pythonの例
x: int
r: str
x = int(input('xを入力:'))
if x >= 80:
r = '合格'
else:
r = '不合格'
print(r)
1,2行目:型ヒント(省略可能)。Pythonは動的型付け言語なので,明示的な型ヒントは不要
3行目:変数xに値を代入
4~7行目:合否の判定。変数xが80以上の場合は5行目の処理を行い,それ以外の場合は7行目の処理を行う
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
int x;
string r;
Console.Write("xを入力:");
x = Convert.ToInt32(Console.ReadLine());
if(x >= 80) {
r = "合格";
} else {
r = "不合格";
}
Console.WriteLine(r);
1,2行目:変数の宣言
4行目:変数xに値を代入
5~9行目:合否の判定。変数xが80以上の場合は6行目の処理を行い,それ以外の場合は8行目の処理を行う
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
xを入力:80
合格
多分岐型の例
例)変数sに文字を入力して,その文字が「g」ならば変数rに「グー」を,「t」ならば「チョキ」を,それ以外ならば「パー」を代入して表示する
流れ図の例
擬似言語の例
文字列型: s
文字列型: r
s を入力
if ( s = "g" )
r ← "グー"
elseif ( s = "t" )
r ← "チョキ"
else
r ← "パー"
endif
r を出力
1,2行目:変数の宣言
3行目:変数sに値を代入
4~10行目:ジャンケンの判定。変数sが「g」の場合は5行目の処理を,「t」の場合は7行目の処理を,それ以外の場合は9行目の処理を行う
Pythonの例
s: str
r: str
s = input('sを入力:')
if s == 'g':
r = 'グー'
elif s == 't':
r = 'チョキ'
else:
r = 'パー'
print(r)
1,2行目:型ヒント(省略可能)。Pythonは動的型付け言語なので,明示的な型ヒントは不要
3行目:変数sに値を代入
4~9行目:ジャンケンの判定。変数sが「g」の場合は5行目の処理を,「t」の場合は7行目の処理を,それ以外の場合は9行目の処理を行う
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
string? s;
string r;
Console.Write("sを入力:");
s = Console.ReadLine();
switch (s) {
case "g":
r = "グー";
break;
case "t":
r = "チョキ";
break;
default:
r = "パー";
break;
}
Console.WriteLine(r);
1,2行目:変数の宣言
4行目:変数sに値を代入
5~15行目:ジャンケンの判定。変数sが「g」の場合は7~8行目の処理を,「t」の場合は10~11行目の処理を,それ以外の場合は13~14行目の処理を行う
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
sを入力:g
グー
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型: x
文字列型: r
x ← 72
if ( x ≧ 60 )
r ← "合格"
else
r ← "不合格"
endif
r を出力
合格
問2 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型: x
文字列型: r
x ← 2
if ( x = 1 )
r ← "春"
elseif ( x = 2 )
r ← "夏"
elseif ( x = 3 )
r ← "秋"
else
r ← "冬"
endif
r を出力
夏
広告
反復型(繰り返し型)とは
反復型は,繰り返し条件を満たしている間(または,終了条件を満たすまで),処理を繰り返す制御構造です。
※ 反復処理…繰り返し同じ処理を実行すること。ループ処理ともいう
繰り返しの条件について
- 流れ図の場合:繰り返しを終了する条件を記述する
- 擬似言語,Python,C#の場合:繰り返す条件を記述する
となります。気をつけましょう。
前判定型(while文)の例
例)変数xに数値を入力(x≧1とする)して,その値の回数だけ「OK」と表示する
流れ図の例
擬似言語の例
整数型: x
x を入力
while ( x ≧ 1 )
"OK"を出力
x ← x - 1
endwhile
1行目:変数の宣言
2行目:変数xに値を代入
3~6行目:変数xが1以上の間,4~5行目の処理を繰り返す(4行目で「OK」と表示し,5行目で変数xの値を1減らす)。
Pythonの例
x: int
x = int(input('xを入力:'))
while x >= 1:
print('OK', end='')
x -= 1
1行目:型ヒント(省略可能)。Pythonは動的型付け言語なので,明示的な型ヒントは不要
2行目:変数xに値を代入
3~5行目:変数xが1以上の間,4~5行目の処理を繰り返す(4行目で「OK」と表示し,5行目で変数xの値を1減らす)
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
int x;
Console.Write("xを入力:");
x = Convert.ToInt32(Console.ReadLine());
while(x >= 1) {
Console.Write("OK");
x -= 1;
}
1行目:変数の宣言
3行目:変数xに値を代入
4~7行目:変数xが1以上の間,5~6行目の処理を繰り返す(5行目で「OK」と表示し,6行目で変数xの値を1減らす)
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
xを入力:3
OKOKOK
前判定型(for文)の例
例)配列xに文字列を代入し,順に表示する
流れ図の例
擬似言語の例
文字列型の配列: x ← { "おはよう", "こんにちは", "こんばんは" }
整数型: n ← 配列xの要素数
for ( iを1からnまで1ずつ増やす )
x[i]を出力
endfor
1行目:配列xの宣言と値の代入
2行目:変数nの宣言と値の代入
3~5行目:変数iが1からnまでの間,4行目の処理を繰り返す(変数iを1ずつ増やしながら配列の各要素の値を順に表示する)
※ 擬似言語では,配列の要素番号は1から始まる(IPAの擬似言語仕様に準拠)。一方,Python・C#では0から始まるため注意する
Pythonの例
x: list[str] = ['おはよう', 'こんにちは', 'こんばんは']
for i in range(0, len(x), 1):
print(x[i])
1行目:リストxの宣言(型ヒント)と値の代入。Pythonは動的型付け言語なので,型ヒントは省略可能
2~3行目:変数iが0からlen(x) (配列の要素数)未満までの間,3行目の処理を繰り返す(変数iを1ずつ増やしながらリストの各要素の値を順に表示する)
※ Pythonでは,リストの要素番号は0から始まる
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
string[] x = new string[] {"おはよう", "こんにちは", "こんばんは"};
for(int i = 0; i < x.Length; i++) {
Console.WriteLine(x[i]);
}
1行目:配列xの宣言と値の代入
2~4行目:変数iが0からx.Length(配列の要素数)未満までの間,3行目の処理を繰り返す(変数iを1ずつ増やしながら配列の各要素の値を順に表示する)
※ C#では,配列の要素番号は0から始まる
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
おはよう
こんにちは
こんばんは
後判定型(do while文)の例
例)変数xに数値を入力(x≧1とする)して,1から変数xの値までを加えたものを変数rに代入し,その結果を表示する
流れ図の例
擬似言語の例
整数型: x, r
x を入力
r ← 0
do
r ← r + x
x ← x - 1
while ( x ≧ 1 )
rを出力
1行目:変数x,rの宣言
2,3行目:変数x,rに値を代入
4~7行目:まず,5~6行目の処理を1回実行し,その後は変数xが1以上の間,5~6行目の処理を繰り返す(1から変数xの値までを順に加える)
Pythonの例
x: int; r: int
x = int(input('xを入力:'))
r = 0
while True:
r += x
x -= 1
if x < 1:
break
print(r)
1行目:型ヒント(省略可能)。Pythonは動的型付け言語なので,明示的な型ヒントは不要
2,3行目:変数x,rに値を代入
4~8行目:5~8行目の処理を繰り返しながら変数xが1未満になった場合にループを抜ける(7~8行目でループを抜ける)
※ Pythonにはdo while文がないため,while Trueとbreakを組み合わせて表現している
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
int x, r;
Console.Write("xを入力:");
x = Convert.ToInt32(Console.ReadLine());
r = 0;
do {
r += x;
x -= 1;
} while(x >= 1);
Console.Write(r);
1行目:変数x,rの宣言
3,4行目:変数x,rに値を代入
5~8行目:まず,5~7行目の処理を1回実行し,その後は変数xが1以上の間,5~7行目の処理を繰り返す(1から変数xの値までを順に加える)
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
xを入力:4
10
※ 4+3+2+1 = 10
二重ループの例
例)二次元配列の各要素の値を表示する
流れ図の例
擬似言語の例
整数型の配列: k ← { {11, 12, 13, 14}, {21, 22, 23, 24}, {31, 32, 33, 34} }
整数型: row ← 配列kの行数
整数型: col ← 配列kの列数
for ( iを1からrowまで1ずつ増やす )
for ( jを1からcolまで1ずつ増やす )
k[i][j] の値をコンマ区切りで出力する
endfor
改行を出力する
endfor
1行目:二次元配列kの宣言と値の代入
2,3行目:変数row,colの宣言と値の代入
4~9行目:変数iが1から変数rowの値までの間,5~8行目の処理を繰り返す(二重ループの外側のループ)
5~7行目:変数jが1から変数colの値までの間,6行目の処理を繰り返す(二重ループの内側のループ)
※ 擬似言語では,配列の要素番号は1から始まる(IPAの擬似言語仕様に準拠)。一方,Python・C#では0から始まるため注意する
Pythonの例
import numpy as np
k: np.ndarray = np.array([[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]])
row: int = k.shape[0]
col: int = k.shape[1]
for i in range(0, row, 1):
for j in range(0, col, 1):
if j != col - 1:
print(k[i, j], end=', ')
else:
print(k[i, j])
2行目:NumPyを用いた二次元配列kの生成
※ NumPy…数値計算を効率的に行うためのライブラリ。多次元配列を操作する機能などがある
3,4行目:変数row,colに値を代入
5~10行目:変数iが0から変数rowの値未満までの間,6~10行目の処理を繰り返す(二重ループの外側のループ)
6~10行目:変数jが0から変数colの値未満までの間,7~10行目の処理を繰り返す(二重ループの内側のループ)
7~10行目:列の終わりでない場合は二次元配列のi行j列の要素の値と「, 」を表示(表示後,改行はしない)し,それ以外の場合(列の終わりの場合)はi行j列の要素の値を表示して改行する
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
int[,] k = new int[,] {{11, 12, 13, 14}, {21, 22, 23, 24}, {31, 32, 33, 34}};
int row = k.GetLength(0);
int col = k.GetLength(1);
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {
if(j != col - 1) {
Console.Write(k[i, j] + ", ");
} else {
Console.WriteLine(k[i, j]);
}
}
}
1行目:二次元配列kの宣言と値の代入
2,3行目:変数row,colの宣言と値の代入
4~12行目:変数iが0から変数rowの値未満までの間,5~11行目の処理を繰り返す(二重ループの外側のループ)
5~11行目:変数jが0から変数colの値未満までの間,6~10行目の処理を繰り返す(二重ループの内側のループ)
6~10行目:列の終わりでない場合は二次元配列のi行j列の要素の値と「, 」を表示(表示後,改行はしない)し,それ以外の場合(列の終わりの場合)はi行j列の要素の値を表示して改行する
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
11, 12, 13, 14
21, 22, 23, 24
31, 32, 33, 34
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型: x
x ← 4
while ( x ≧ 1 )
x を出力
x ← x - 1
endwhile
4321
問2 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型の配列: a ← { 5, 8, 2 }
整数型: i, s ← 0
for ( iを1から3まで1ずつ増やす )
s ← s + a[i]
endfor
s を出力
15
問3 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型: x, r
x ← 3
r ← 1
do
r ← r × x
x ← x - 1
while ( x ≧ 1 )
r を出力
6
問4 次の擬似言語を実行したとき,出力される値を答えなさい。
整数型の配列: k ← { {7, 2}, {4, 1} }
整数型: i, j
for ( iを1から2まで1ずつ増やす )
for ( jを1から2まで1ずつ増やす )
k[i][j] を出力
endfor
endfor
7241
広告
副プログラム(サブルーチン)とは
副プログラムとは,複数のプログラムに共通する処理を別のプログラムとして独立させたものをいいます。
- 手続き…処理結果を呼び出し元へ返さない副プログラム
- 関数…処理結果を呼び出し元へ返す副プログラム
- 戻り値…関数が返す値
手続きの例
例)「おはよう」と表示する副プログラム(手続き)を,主プログラムから呼び出し実行する
流れ図の例
擬似言語の例
// 主プログラム
○main()
"あいさつ:"を表示
aisatsu ()
// 副プログラム
○aisatsu ()
"おはよう"を表示
4行目:副プログラム aisatsu() の呼び出し
7~8行目:副プログラム aisatsu() の宣言と定義
Pythonの例
# 主プログラム
def main():
print('あいさつ:', end='')
aisatsu()
# 副プログラム
def aisatsu():
print('おはよう')
if __name__ == "__main__":
main()
4行目:副プログラム aisatsu() の呼び出し
7~8行目:副プログラム aisatsu() の宣言と定義
※ main() 関数…プログラムの開始地点(エントリポイント)を明示的に示す関数。Pythonの場合は省略可能
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
class b_007 {
// 主プログラム
static void Main(string[] args) {
b_007 obj = new b_007();
Console.Write("あいさつ:");
obj.aisatsu();
}
// 副プログラム
void aisatsu() {
Console.WriteLine("おはよう");
}
}
6行目:副プログラム aisatsu() の呼び出し
10~12行目:副プログラム aisatsu() の宣言と定義
※ main() 関数…プログラムの開始地点(エントリポイント)を明示的に示す関数。C#の場合はクラス内に書く必要がある。クラスの詳細は「オブジェクト指向設計の基礎まとめ(クラスとは)」を参照
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
あいさつ:おはよう
関数の例
例)主プログラムで,変数nに値を入力(n≧1とする)し,副プログラム(関数)goukei () に変数nの値を渡して呼び出す。副プログラム goukei () は,1から受け取った変数nの値までを加えて,その結果を返す。主プログラムは,返ってきた値を変数rに代入し表示する
流れ図の例
擬似言語の例
// 主プログラム
〇main()
整数型: n, r
n を入力
r ← goukei ( n )
r を表示
// 副プログラム
○goukei ( 整数型: n )
return n × ( n + 1 ) ÷ 2
5行目:副プログラム goukei() を呼び出し,変数rに戻り値を代入
9~10行目:副プログラム goukei() の宣言と定義
10行目:副プログラム goukei() の実行を終了し,呼び出し元(main()関数)に制御を戻す
Pythonの例
# 主プログラム
def main():
n = int(input("nを入力:"))
r = goukei(n)
print('%d' %r)
# 副プログラム
def goukei(n: int) -> int:
return n * (n + 1) // 2
if __name__ == "__main__":
main()
4行目:副プログラム goukei() を呼び出し,変数rに戻り値を代入
8~9行目:副プログラム goukei() の宣言と定義
9行目:副プログラム goukei() の実行を終了し,呼び出し元(main()関数)に制御を戻す
※ main() 関数…プログラムの開始地点(エントリポイント)を明示的に示す関数。Pythonの場合は省略可能
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
class b_008 {
// 主プログラム
static void Main(string[] args) {
b_008 obj = new b_008();
int n, r;
Console.Write("nを入力:");
n = Convert.ToInt32(Console.ReadLine());
r = obj.goukei(n);
Console.WriteLine(r);
}
// 副プログラム
int goukei(int n) {
return n * (n + 1) / 2;
}
}
8行目:副プログラム goukei() を呼び出し,変数rに戻り値を代入
13~15行目:副プログラム goukei() の宣言と定義
14行目:副プログラム goukei() の実行を終了し,呼び出し元(main()関数)に制御を戻す
※ main() 関数…プログラムの開始地点(エントリポイント)を明示的に示す関数。C#の場合はクラス内に書く必要がある。クラスの詳細は「オブジェクト指向設計の基礎まとめ(クラスとは)」を参照
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
nを入力:4
10
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
○main()
saji( 5 )
○saji( 整数型: n )
n × 2 を出力
10
問2 次の擬似言語を実行したとき,出力される値を答えなさい。
○main()
整数型: r
r ← keisan( 6 )
r を出力
○keisan( 整数型: n )
return n ÷ 2
3
広告
局所変数(ローカル変数)・大域変数(グローバル変数)と有効範囲(スコープ)とは
局所変数は,宣言したプログラム内でのみ使用可能な変数です。
大域変数は,すべてのプログラムで使用可能な変数です。
大域変数(グローバル変数)の例
例)大域変数gに値を代入する。主プログラムでは,変数pに値を代入し,副プログラムcalc() に変数pの値を渡して呼び出す。副プログラムcalc() は,受け取った変数の値に大域変数gの値を加えて変数rに代入し,変数rの値を表示する
擬似言語の例
大域: 整数型: g ← 2
// 主プログラム
〇main()
整数型: p ← 3
calc( p )
// 副プログラム
○calc( 整数型: n )
整数型: r
r ← g + n
rを表示
1行目:大域変数gの宣言と値の代入(変数gは,すべてのプログラムで使用可能)
5行目:局所変数pの宣言と値の代入(変数pは,main()関数内でのみ使用可能)
10行目:局所変数rの宣言(変数rは,calc()関数内でのみ使用可能)
Pythonの例
g = 2
# 主プログラム
def main():
p = 3
calc(p)
# 副プログラム
def calc(n):
r = g + n
print(r)
if __name__ == "__main__":
main()
1行目:大域変数gに値を代入(変数gは,すべてのプログラムで使用可能)
5行目:局所変数pに値を代入(変数pは,main()関数の外からは参照できない)
10行目:局所変数rに値を代入(変数rは,calc()関数の外からは参照できない)
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
class b_009 {
static int g = 2;
// 主プログラム
static void Main(string[] args) {
b_009 obj = new b_009();
int p = 3;
obj.calc(p);
}
// 副プログラム
void calc(int n) {
int r;
r = g + n;
Console.WriteLine(r);
}
}
2行目:メンバ変数gの宣言と値の代入(C#には大域変数はない。しかし,メンバ変数にstaticを付けて静的メンバとして宣言すると,クラスのインスタンスに依存せず,クラスに属する変数として全インスタンスで共有される(大域変数のように扱える))
※ メンバ変数…クラスの中で使用される変数。クラスの詳細は「オブジェクト指向設計の基礎まとめ(クラスとは)」を参照
7行目:局所変数pの宣言と値の代入(変数pは,main()関数内でのみ使用可能)
13行目:局所変数rの宣言(変数rは,calc()関数内でのみ使用可能)
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
5
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
大域: 整数型: g ← 10
○main()
整数型: x ← 4
calc( x )
○calc( 整数型: n )
整数型: r
r ← g - n
r を出力
6
値渡し(値呼出し)と参照渡し(参照呼出し)とは
値渡しとは,主プログラムで宣言して初期化した変数の値のコピーを,副プログラムに渡して呼び出す方法をいいます。副プログラムで,渡された変数の値が変化した場合,元々の(主プログラムの)変数の値は変化しません。
参照渡しとは,主プログラムで宣言して初期化した変数のアドレス(主記憶装置内の変数の値の保存場所)を,副プログラムに渡して呼び出す方法をいいます。副プログラムで、渡されたアドレスの変数の値が変化した場合,元々の(主プログラムの)変数の値も変化します。
値渡し(値呼出し)と参照渡し(参照呼出し)の例
例)主プログラムで変数m1と変数m2に値を代入し,副プログラム(手続き)calc_2() に変数m1と変数m2を渡して呼び出す(変数m1は値渡し,変数m2は参照渡し)。副プログラムcalc_2() では,受け取ったそれぞれの変数の値に1を加えて,その値を表示する。その後,主プログラムで変数m1と変数m2の値を表示する
擬似言語の例
// 主プログラム
○main ()
整数型: m1 ← 2
整数型: m2 ← 3
calc_2 ( m1, m2 )
m1, m2の値を出力
// 副プログラム
○ calc_2 ( 整数型: a1, 整数型: a2 )
a1 ← a1 + 1
a2 ← a2 + 1
a1, a2の値を出力
5行目:変数m1と変数m2を渡してcalc_2()関数を呼び出す(変数m1は値渡し,変数m2は参照渡し)
Pythonの例
# 主プログラム
def main():
m1 = 2
calc_2(m1)
print('m1=', m1)
# 副プログラム
def calc_2(a1):
a1 = a1 + 1
print('a1=', a1)
if __name__ == "__main__":
main()
4行目:変数m1を渡してcalc_2()関数を呼び出す。Pythonには参照渡しのしくみはない。引数はオブジェクトへの参照が値として渡されるため,値渡しのように見える
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
class b_010 {
// 主プログラム
static void Main(string[] args) {
b_010 obj = new b_010();
int m1 = 2;
int m2 = 3;
obj.calc_2(m1, ref m2);
Console.WriteLine("m1= {0}, m2= {1}", m1, m2);
}
// 副プログラム
void calc_2(int a1, ref int a2) {
a1 = a1 + 1;
a2 = a2 + 1;
Console.WriteLine("a1= {0}, a2= {1}", a1, a2);
}
}
7行目:変数m1と変数m2を渡してcalc_2()関数を呼び出す(変数m1は値渡し,変数m2は参照渡し)。C#では,ref を付けると(明示的な)参照渡しになる
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
a1 = 3, a2 = 4
m1 = 2, m2 = 4
共有渡し(参照の値渡し)とは
共有渡しとは,主プログラムで宣言して初期化した変数のアドレス(主記憶装置内の変数の値の保存場所)のコピーを,副プログラムに渡して呼び出す方法をいいます。副プログラムで,渡された変数そのものに再代入した場合は,元々の(主プログラム)の変数には影響しませんが,参照先のオブジェクトに対して内容の変更を行った場合は,その変更が,元々の(主プログラム)の変数にも反映されます。
共有渡し(参照の値渡し)の例
例)主プログラムで配列n1,配列n2に値を代入し,副プログラム(手続き)calc_3() に配列n1,配列n2を渡して呼び出す(配列n1,配列n2は共有渡し)。副プログラムcalc_3() では,受け取った配列b1の要素b1[0]の値に100を加え,受け取った配列b2については値を再代入し,配列b1,配列b2の値を表示する。その後,主プログラムで配列n1,配列n2の値を表示する
Pythonの例
import numpy as np
# 主プログラム
def main():
n1 = np.array([11, 12])
n2 = np.array([21, 22])
calc_3(n1, n2)
print('n1=', n1, 'n2=', n2)
# 副プログラム
def calc_3(b1, b2):
b1[0] = b1[0] + 100
b2 = np.array([1, 2, 3])
print('b1=', b1, 'b2=', b2)
if __name__ == "__main__":
main()
7行目:配列n1と配列n2を渡してcalc_3()関数を呼び出す(配列n1,配列n2は参照のコピーが渡され,参照先のオブジェクトは共有される)
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
class b_010 {
// 主プログラム
static void Main(string[] args) {
b_010 obj = new b_010();
int[] n1 = {11, 12};
int[] n2 = {21, 22};
obj.calc_3(n1, n2);
Console.WriteLine("n1= {0}, n2= {1}", String.Join(", ", n1), String.Join(", ", n2));
}
// 副プログラム
void calc_3(int[] b1, int[] b2 ) {
b1[0] = b1[0] + 100;
b2 = new int[] {1, 2, 3};
Console.WriteLine("b1= {0}, b2= {1}", String.Join(", ", b1), String.Join(", ", b2));
}
}
7行目:配列n1と配列n2を渡してcalc_3()関数を呼び出す(配列n1,配列n2は参照のコピーが渡され,参照先のオブジェクトは共有される)
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
b1= [111 12], b2= [1 2 3]
n1= [111 12], n2= [21 22]
値渡し,参照渡し,共有渡しの比較とは
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
○main()
整数型: a ← 5
整数型: b ← 5
plus1( a ) // 値渡し
plus2( b ) // 参照渡し
a を出力
b を出力
○plus1( 整数型: x )
x ← x + 1
○plus2( 参照渡し 整数型: y )
y ← y + 1
56
プログラムの性質とは
再帰的(リカーシブ)プログラムとは
再帰的プログラムとは,プログラムの中で自身を呼び出して処理するプログラムのことをいいます。再帰呼び出しでは,実行途中の処理状態や戻り先を,LIFO方式で管理する必要があります。
※ LIFO … Last In First Out。後入れ先出しのこと
再帰的(リカーシブ)プログラムの例
例)主プログラムから副プログラム(関数)kaijo()を呼び出し,変数nの値の階乗を求める
流れ図の例
擬似言語の例
// 主プログラム
○main ()
整数型: n, r
n を入力
r ← kaijo ( n )
r を表示
// 副プログラム
○kaijo ( 整数型: a )
整数型: b
if ( a = 0 )
b ← 1
else
b ← a × kaijo ( a - 1)
endif
return b
14行目:再帰呼び出し
※ 「kaijo(5) → kaijo(4) → kaijo(3) → …」のように呼び出しが積み重なり,aが0になると値1を返し,最後に呼び出した処理から順に戻る
Pythonの例
# 主プログラム
def main():
n = int(input("nを入力:"))
r = kaijo(n)
print(r)
# 副プログラム
def kaijo(a):
if a == 0:
b = 1
else:
b = a * kaijo(a - 1)
return b
if __name__ == "__main__":
main()
12行目:再帰呼び出し
※ Pythonプログラムの作成と実行については,「Pythonプログラムの作成と実行」を参照
C#の例
class b_011 {
// 主プログラム
static void Main(string[] args) {
b_011 obj = new b_011();
int n, r;
Console.Write("nを入力:");
n = Convert.ToInt32(Console.ReadLine());
r = obj.kaijo(n);
Console.WriteLine(r);
}
// 副プログラム
int kaijo(int a) {
int b;
if(a == 0) {
b = 1;
} else {
b = a * kaijo(a - 1);
}
return b;
}
}
18行目:再帰呼び出し
※ C#プログラムの作成と実行については,「C#プログラムの作成と実行」を参照
実行結果
nを入力:5
120
※ 5! = 120
再入可能(リエントラント)プログラムとは
再入可能プログラムとは,複数の処理を同時に実行する要求に対して並列に処理し,それぞれに正しい結果を返すことのできるプログラムのことをいいます。プログラムは,実行によって内容が変化しない手続き部分と,実行ごとに内容が変化するデータ部分に分けます。手続き部分は複数のタスクで共有し,データ部分はタスクごとに分離することで,同時実行しても互いに影響しないようにします。
再使用可能(リユーザブル)プログラムとは
再使用可能プログラムとは,主記憶装置に存在する実行終了後のプログラムを再実行する際に,各変数の値を初期化することで,再び正しく実行できるプログラムのことをいいます。プログラムは主記憶装置上に存在するため,補助記憶装置から再度読み込まなくても実行できます。ただし,他のタスクがプログラムを使用中の場合は,同時に実行することはできません(プログラムが終了するまで待つことになります)。
※ プログラムの処理の終了後(または,プログラムの最初)に,各変数の値を初期化することで,再び正しく実行できる
※ 逐次再使用可能(シリアルリユーザブル)ともいう
再配置可能(リロケータブル)プログラムとは
再配置可能プログラムとは,主記憶装置の任意の位置に再配置することのできるプログラムのことをいいます。ベースレジスタに主記憶装置上のプログラムの先頭アドレスを設定し,命令を実行する際には,命令中の相対アドレスにベースレジスタの値を加えて実効アドレスとすることにより,プログラムがどのアドレスに配置されても,プログラムを変更せずに実行することができます。
練習問題
問1 次の擬似言語を実行したとき,出力される値を答えなさい。
○main()
整数型: r
r ← func( 3 )
r を出力
○func( 整数型: n )
if ( n = 0 )
return 0
else
return n + func( n - 1 )
endif
6
まとめ
今回は,流れ図と擬似言語によるプログラミングについて,基本情報技術者試験で重要となる内容を中心にシンプルにまとめました。
特に重要なのは,基本制御構造(順次型・分岐型・反復型)の処理の流れを正しく理解することです。順次型は処理を順番に実行する基本構造です。分岐型は条件によって処理を切り替えます。反復型は条件を満たす間,同じ処理を繰り返します。また,副プログラム,値渡し・参照渡し,再帰的プログラムは,基本情報技術者試験でも頻出となる重要分野です。特に再帰処理では,LIFO(後入れ先出し)の考え方が重要になります。暗記だけではなく,「プログラムがどの順番で動くのか」を実際に追いながら理解することが大切です。擬似言語だけでなく,PythonやC#でも実際にコードを書きながら学習してみましょう。
実践的な内容を学びたい方は,開発環境を構築するところからはじめてみてください。
理解が進んだら,基本情報技術者試験の過去問題にもチャレンジしてみてください。
- 流れ図と擬似言語によるプログラミングの過去問・解説
※ このページでは読みやすさを考慮し「コンピューター」,「サーバー」など長音付きで表記していますが,試験では「コンピュータ」,「サーバ」と表記されます




