【第7章】データの再利用(執筆途中)
2022.06.15
ここまででプログラミングの3つの基本、順次処理、繰り返し処理、選択処理について学びました。これらについてはまだまだお話したいことがあるのですが、何度も言っているようにこのカテゴリーの目的は短期間でプログラミング的思考とコンピュータの基本を覚えていただくことなので、とりあえず先に進みます。ここからはヒンピュータならではの処理についてお話してゆきます。
[データの再利用]
コンピュータの得意技のひとつとしてデータの再利用があります(もちろんそのようなプログラムが可能という意味です)。電卓にもメモリーキーがありますが、コンピュータならもっと高度なことができます。まず、データの再利用について、円柱の体積を求めるプログラムを例に説明します。
図7-1.円柱の体積
円柱の体積は
または
で求められます。
①の考え方で書いたプログラムはこのようになります。
1:Dim pai As Single = 3.14159
2:Dim V As Single
3:Dim S As Single
4:Dim r As Single
5:Dim h As Single
6:Console.WriteLine()
7:Console.Write(" 底面の半径は?") : r = Console.ReadLine()
8:Console.Write(" 高さは?") : h = Console.ReadLine()
9:V = pai * r ^ 2 * h
10:Console.WriteLine(" 円柱の体積=" & V)
11:Console.ReadKey()
そして②の考え方で書くとこうなります。
1:Dim pai As Single = 3.14159
2:Dim V As Single
3:Dim S As Single
4:Dim r As Single
5:Dim h As Single
6:Console.WriteLine()
7:Console.Write(" 底面の半径は?") : r = Console.ReadLine()
8:Console.Write(" 高さは?") : h = Console.ReadLine()
9:S = pai * r ^ 2
10:V = S * h
11:Console.WriteLine(" 円柱の体積=" & V)
12:Console.ReadKey()
プログラムとしてはどちらも誤りではありません。実行結果はどちらも同じです(図7-2)。
図7-2.円柱の体積を求める
①のプログラムは必要な値、底面の半径、円周率、高さをいっぺんに計算式に入れて体積を求めるやり方です。②のプログラムは一旦底面積を求めてそれを変数に代入し、それに高さを掛けて体積を求める方法です。ここまでやってきたプログラムでおわかりいただけたと思いますが、変数に代入した値はプログラムで変数の値を書き換えない限りプログラム終了まで保存されます。②は9行目で変数Sに代入した底面積の値を10行目で再利用していることになります。底面の半径と高さを入力し円柱の体積を求めるプログラムとしてはどちらの組み方でもいいのですが、管理人はここは②の組み方をおすすめします。というのは、後に円柱の体積の他、たとえばこの円柱の表面積も求めたいという要求が出てきた場合、プログラムの改造(メンテナンス)が容易になるからです。
図7-3.円柱の体積と表面積を求める
上のプログラム例②を円柱の表面積も求める(図7-3)ように改造すると次のようになります。
1: ' 円柱の体積と表面積を求めるプログラム
2: ' 2022/07/10
3: ' B.S.I. Works Corp.
4:
5: ' 変数の宣言
6: Dim pai As Single = 3.14159 ' 円周率
7: Dim V As Single ' 体積
8: Dim S As Single ' 底面積
9: Dim SA As Single ' 側面積
10: Dim SS As Single ' 表面積
11: Dim L As Single ' 底面の円周
12: Dim r As Single ' 底面の半径
13: Dim h As Single ' 高さ
14:
15: Console.WriteLine("円柱の体積と表面積")
16: Console.WriteLine()
17: Console.Write(" 底面の半径は?") : r = Console.ReadLine() ' 半径入力
18: Console.Write(" 高さは?") : h = Console.ReadLine() ' 高さ入力
19:
20: S = pai * r ^ 2 ' 底面積計算
21: L = 2 * pai * r ' 底面の円周計算
22: SA = L * h ' 側面積計算
23: V = S * h ' 体積計算
24: SS = S * 2 + SA ' 表面積計算
25: ' 計算結果の表示
26: Console.WriteLine()
27: Console.WriteLine(" 円柱の底面積=" & S)
28: Console.WriteLine(" 円柱の側面積=" & SA)
29: Console.WriteLine(" 円柱の体積=" & V)
30: Console.WriteLine(" 円柱の表面積=" & SS)
31: ' 終わり
32: Console.ReadKey()
[配列]
変数に途中までの計算結果(処理結果)を代入(保存)してくことによって、それを後で再利用できることはおわかりいただけたと思います。ただ、ここでやったサンプルプログラム程度のものならコンピュータでなくてもメモリー機能付きの電卓が上手に使いこなせればできます。コンピュータならではのデータの再利用なら、これから学ぶ配列(*2)を使います。まず配列とはどういうものかを説明します。
ここにハイツ立山というアパートがあります。1号室は相沢さんの部屋、2号室には加藤さん、3号室には鈴木さん、4号室は空室で5号室には渡辺さんが住んでいます(図7-4)。これをプログラミング言語風に書くと
N=ハイツ立山(1)、Nの値は"相沢"
N=ハイツ立山(2)、Nの値は"加藤"
N=ハイツ立山(3)、Nの値は"鈴木"
N=ハイツ立山(4)、Nの値は""
N=ハイツ立山(5)、Nの値は"渡辺"
そして
ハイツ立山(4)="高橋"
とすると4号室には高橋さんが入居します。配列とはこのようなものです。
図7-4.配列の概念
配列を使用するには、Dimによる宣言が必要になります。
Dim 配列名(配列上限) As データ型
配列名は変数名と同じ規則で決められます。配列上限は正の整数です。データ型も変数の使用宣言と同じくInteger、Single、Stringなどです(*3)。たとえば
Dim uriage(5) As Integer
と宣言するとuriage(0)、uriage(1)、uriage(2)、uriage(3)、uriage(4)、uriage(5)の6つが、整数型データを扱える配列uriageとして使用できるようになります。
Dimの後ろの名前(この例ならuriage)を配列名、宣言後使えるようになるひとつひとつ(この例ならuriage(0)、uriage(1)・・・uriage(5))を配列の要素、配列の要素の( )の中の数字を添え字といいます。配列の要素は次のように変数のように使うことができます。
uriage(0) = 450
uriage(1) = tanka * suryo
ただ、このような使い方では配列を使う意味はありません。配列がその強みを発揮するのは繰り返し処理とデータの再利用です。
[配列を活用したデータの再利用]
これよりしばらく試験の成績処理のプログラムで説明します。学校の試験には良い思い出がないという方もいらっしゃると思いますが、しばらくお付き合いください。
今、試験実施後の結果が図7-5のようになっているとします。No.は出席番号、それぞれの右の数字は点数でか。これを入力し、平均を求め、各生徒の点数が平均とどれだけ離れているかを計算し表示します。その際上位1/4をS、下位1/4はFとします(図7-6)。点数の範囲は0~100点、平均は点数合計÷受験人数、欠席者は点数合計にも人数にもカウントしない、上位は(100+平均点)÷2を超える者、下位は平均点÷2未満の者とします(図7-7)。
図7-5.テストの成績
図7-6.テストの成績入力と結果表示
図7-7.上位者と下位者
このプログラムを実現するためには最初に平均を求めてから各点数-平均点を計算することになりますが、平均を求めるには受験者全員の点数を入力しなくてはなりません。その後に各点数との差を計算するのですから、入力した各点数をいったん保存しておく必要があります。ここではデータ保存と繰り返し処理両方に強い配列を使うことにします。
[プログラム概要]
図7-8.プログラムの大まかな流れ
図7-8に基づいて作成したプログラムは次のようになります。25~45行目は図7-8のstep1に、46~55行目はStep2に、56~82行目はStep3に相当します。
1: '**************************
2: '* テストの成績処理 *
3: '* 2022/07/15 *
4: '* by B.S.I.Works *
5: '**************************
6:
7: ' 配列と変数の準備
8: Dim tensu(50) As Integer ' 点数保存用
9: Dim ten As Integer ' 点数入力用
10: Dim gokei As Integer = 0 ' 点数保存用
11: Dim ninzu As Integer = 0 ' 受験人数
12: Dim heikin As Single ' 平均点
13: Dim s_line As Single ' 秀ライン
14: Dim f_line As Single ' 補習ライン
15: Dim i As Integer ' 配列添え字
16: Dim saigo As Integer ' 添え字最大
17:
18: ' プログラムの使用方法
19: Console.WriteLine("テストの成績処理")
20: Console.WriteLine("出席番号の後に点数を入れてください")
21: Console.WriteLine("入力終了時は999を入れてください")
22: Console.WriteLine("欠席はマイナスの点数を入れてください")
23: Console.WriteLine()
24:
25: ' 最初に全員の点数を入力
26:
27: For i = 1 To 50
28: Console.Write(" No." & i & "の点数 ")
29: ten = Console.ReadLine()
30: ' 999が入ってきたら入力終了
31: If ten = 999 Then
32: Exit For
33: End If
34: ' 点数が 0以上の時、合計に加算し配列に保存、人数もカウントアップ、
35: ' 点数が 0未満の時は点数を配列に保存するだけ
36: If ten >= 0 Then
37: gokei += ten
38: tensu(i) = ten
39: ninzu += 1
40: Else
42: tensu(i) = ten
43: End If
44: Next
45:
46: ' 入力終了後の処理
47: saigo = i - 1 ' 添え字の最後の値
48: ' 受験者数が 0でなければ平均を計算、秀の最低ライン、補習対象者の最高ラインを求める
49: If ninzu <> 0 Then
50: heikin = gokei / ninzu ' 平均計算
51: s_line = (100 + heikin) / 2 ' 秀の最低ライン
52: f_line = heikin / 2 ' 補習対象者の最高ライン
53: End If
54:
55: Console.WriteLine()
56:
57: ' 配列に保存した各点数の平均との差を計算、秀の対象か、補習の対象かを判別する
58: ' (受験者が 0のとき、変数saigoの値は -1になっているので
59: ' 次のFor ~ Nextループは実行されない)
60:
61: For i = 1 To saigo
62: Console.Write("No," & i & " ")
63: ' 欠席(在籍なし)の場合、次のIf~End Ifブロックは実行されない
64: If tensu(i) >= 0 Then
65: Console.Write(tensu(i) & " " & tensu(i) - heikin)
66: ' 点数が秀の最低ラインを超えていればSと表示
67: If tensu(i) > s_line Then
68: Console.WriteLine(" S")
69: ' 点数が補習対象者の最高ライン未満なら*と表示
70: ElseIf tensu(i) < f_line Then
71: Console.WriteLine(" *")
72: ' 秀でも補習対象者でもなければ何も表示しない
73: Else
74: Console.WriteLine()
75: End If
76: Else
77: Console.WriteLine()
78: End If
79: ' 表示10人分ごとにスクロールを一時停止
80: If i Mod 10 = 0 Then
81: Console.ReadKey()
82: End If
83: Next
84:
85: Console.WriteLine()
86: If ninzu <> 0 Then
87: Console.WriteLine("平均 " & heikin)
88: Console.WriteLine("受験人数 " & ninzu)
89: End If
90: Console.ReadKey()
[プログラムはわかりやすく書こう]
プログラムを詳しく解説する前に、今後のために先にこちらのお話をさせていただきます。
一度作ったプログラムは未来永劫そのままということは滅多にありません。使っているうちに不具合が見つかったり新たな要求が出てきて修正・改造の必要が出てくることは多々あります。そのような時、最初に作ったプログラムがわかりやすく書かれているのとそうでないのとでは、その後の作業効率が天と地ほどの差が出てしまいます。
VB2022に限って言えば、プログラム中に空行が何行あっても文法エラーにはなりません。そこで上のププログラム例では、図7-8の流れに従って各stepをひとかたまりにしてstep間に空行を入れました。
そして行頭や行の途中に '(ハングルクォーテーション)がある箇所があります。VB2022では ' があるとそこから行の最後までは注記とみなされ、何でも書くことができます。注記を入れることにより、プログラム作成日付、作成者などを記録することができる他、変数や配列の使用目的、プログラムの流れを記しておくことができるので、後から修正・改造を施すことになったとき作業が大変楽になります。
27行目から44行目を見てください。27行目の For と44行目の Next がペアで繰り返しブロックになっていますが、このブロックに囲まれた28~43行目はじの行も先頭に空白が何文字か入っています。このような行頭に空白を入れての字下げをインデントといいます。このようにブロック内の各行をインデントしておくとプログラムの構造がわかりやすくなります。
[プログラム詳細]
ということで、今回のサンプルプログラムは、注記を付けてプロックごとにインデントしてあるので、プログラムの流れについては特に詳細な説明がなくてもわかると思います。ここではこれ以外の点についてお話します。
このプログラムは小中学校・高校でクラス単位での使用を前提としています。1クラスの人数は50人まで対応しています。クラス内の出席番号は1から始まり、転校等でいなくなった児童(生徒)の番号はそのまま(学年の途中で出席番号の付け直しはしない)とします。
27~44行目のForブロックがstep1(受験者全員の点数をまとめて入力する)です。For~Nextは50回繰り返すことになっていますが、全員の点数を入力し終わったら50回繰り返してなくてもFor~Nextループを抜けるようにしています。
46~53行目はstep2です。受験者がひとりもいなかった場合、平均は計算できません(分母が0の割り算になってしまいます)。また秀(S)、補習対象者(F)が出ることもありませんから、受験者が0のときはこれらの計算は行なわないようになっています。
61~83行目はstep3です。step2で求めた平均、秀(S)ライン、補習対象者(F)ラインと、保存した各点数を比較するところです。このとき、受験者が0人だったときは、このstep3は実行されないようになっています。その仕掛けは変数saigoです。変数saigoはデータを保存した配列の最後の添え字 i の値を保持しています。もし受験者がひとりもいなければsaigoの値は0になります。そうすると61行目のFor制御文では開始値>終端値となり62~82行目は実行されません。
[昔はよかったなぁ]
昔のBASICにも配列はありました。昔のBASICでは
【第6章】選択処理
2022.05.08
[選択処理]
図6-1.選択処理のイメージ
前章で繰り返し処理について学びました。同じことを何回も繰り返し実行するというのはコンピュータの得意技です。繰り返し処理についてはまだまだお話したいことがあるのですが、このカテゴリーの目的のひとつに、短期間でプログラミング的思考を身につけるというのがあるので、繰り返し処理の続きは後の章で学ぶとして、ここはひとまず次の話題に進むことにします。
昔話になりますが、管理人が小学校3年生のとき我が家に初めてカラーテレビが来ました。そのテレビは電源を入れた直後にマイコン制御で垂直同期が行われるようになっていたのですがテレピのボディに誇らし気に「人工頭脳付」というシールが貼ってありました。当時コンピュータは「人工頭脳」と呼ばれたものでした。今でも中国語では「電腦」(繁体)といいます。
どうしてコンピュータが人間の脳に例えられるのかというと、コンピュータにはこれから学ぶ判断、処理の選択ができるという能力があるからです(もちろんそのようなプログラムが入っているからなのですが)。
コンピュータが判断・処理の選択は、条件式が成立する(true)か成立しない(false)かで次の処理を実行するかどうかを決定する、というのが基本です(図6-1左)
。
[偶数奇数判定プログラム]
では。キーボードから入力された整数が偶数す奇数かを判定するプログラムを作ってみましょう。偶数とは2で割り切れる整数(0、2、4、6・・・)のことをいいます。対して奇数は2で割り切れない整数(1、3、5、7・・・)です。この判定を行なうには入力された数を2で割ってみて余りが出るかどうかをみればよいのですが、これをやるのにVB2022には便利な算術演算子がありましたね。そう、mod です。忘れてしまった方は第2章をもう一度見てください。
プログラムの流れは図6-1右のようになります。
この流れにもとづいて作ったプログラムは次のようになります。
1: Dim su As Integer
2: Dim amari As Integer
3: Console.Write(" 整数を入力してください ")
4: su = Console.ReadLine()
5: amari = su Mod 2
6: If amari = 0 Then
7: Console.WriteLine("偶数です")
8: Else
9: Console.WriteLine("奇数です")
10: End If
11: Console.ReadKey()
[プログラムの説明]
1行目はキーボードから入力した整数を保存する変数、2行目は入力した整数を2で割った余りを代入する変数の宣言です。3行目は何を入力するかを表示し、4行目でキーボードから整数の入力を受けます。そして5行目は入力した整数を2で割った余りを求めるところです。
次からが本章で中心になる判断・選択処理です。まず6行目です。If amari = 0 Thenとありますが、これは「もし、変数amariの値が0ならば次の処理を実行せよ」という意味です。どの処理を実行するのかというと7行目の「偶数です」と表示するところです。8行目の、Elseは「そうでなければ次の処理を実行せよ」という意味です。この場合なら9行目の「奇数です」と表示するところです。このようにIfとElseは条件が成立するかしないかで処理内容を分けるときに使いますが、どこまでが選択処理なのかということを示しているのが10行目のEnd Ifです。
[If 条件式 による処理の選択 ]
If制御文の使い方をまとめておきます。最も基本的な使い方は
If 条件式 Then
条件が成立したときの処理(複数行でも可)
End If
これは条件が成立したときだけ特定の処理を行なう(条件が成立しないときは何もしない)場合です。
If 条件式 Then
条件が成立したときの処理(複数行でも可)
Else
条件が成立しなかったときの処理(複数行でも可)
End If
今のサンプルプログラムに出てきたもので、条件が成立するかしないかで処理内容を分ける場合です。
[条件式]
選択処理や繰り返し処理の条件を指定する式を条件式といいます。条件式の書き方の基本を覚えましょう。
条件式の書き方の基本的な形は
式 比較演算子 式
です。条件式の場合、左辺は変数1個とは限りません。上のサンプルプログラムの6行目のamari = 0 は 0 = amari でもエラーにはなりません。あとはプログラムがわかりやすいかどうかです。そして条件式での = は代入演算子ではなく等号です。ややこしいですが早いところ慣れてください。
VB2022で使える比較演算子は次のとおりです。
図6-3.VB2022の比較演算子
[条件が複数あるとき~論理演算子]
図6-4.複数の条件式がある場合
条件式は1つではなく2つ以上書くこともできます。図6-4左を見てください。今、2つの条件式AとBがあるとします。条件式Aが成立する範囲はAとCです。そして条件式Bが成立するのはBとCです。そうするとCはA、B両方の条件式が成立する範囲ということになります。これを A And B と書きます。AかB、少なくともどちらか一方が成立する範囲はA、B、Cになります。これは A Or Bと書きます。Not は条件式が成立しない場合です。左の図で Not(A Or B) と書くと、Dの範囲になります。
この条件式と条件式を結ぶAnd、Or、Notのことを論理演算子といいます。VB2022で使える論理演算子はもっとあるのですが、この3つが基本になります。そして条件が成立することを真(True)、成立しないことを偽(False)といいます。
[Ifプロック]
If~End IfまでのひとかたまりをIfブロックとよびます。Elseがある場合、Ifブロックの中はさらに2つのブロックに分かれます。それぞれのブロックは独立した部屋のようなものです。1つのブロックで1つのプログラムと考えてもけっこうです。これだけではさっぱりわからないと思いますので、実際のプログラムでみてみましょう。
[最小公倍数を求めるプログラム1]
キーボードから入力した2つの整数aとbの最小公倍数を求めるプログラムを考えてみます。最小公倍数とは2つの整数の公倍数で共通するもののうちいちばん小さいものをいいます。ここでは小さい整数から順に2つの整数の公倍数かどうかを調べてゆくという方法をとります。整数a、bはせいぜい100くらいまで、調べる範囲は1~10000とします。プログラムの流れは下の図のようになります。
図6-5.最小公倍数を求めるプログラムの流れ
この流れに基づいて作成したプログラムはこのようになります。
1: Dim i As Integer
2: Dim a As Integer
3: Dim b As Integer
4: Dim amari1 As Integer
5: Dim amari2 As Integer
6: Console.WriteLine("2つの数の最小公倍数を求める")
7: Console.Write("1つめの数(整数) ") : a = Console.ReadLine()
8: Console.Write("2つめの数(整数) ") : b = Console.ReadLine()
9: For i = 1 To 10000
10: amari1 = i Mod a
11: If amari1 = 0 Then
12: amari2 = i Mod b
13: If amari2 = 0 Then
14: Console.WriteLine()
15: Console.WriteLine(i)
16: Exit For
17: End If
18: End If
19: Next i
20: Console.ReadKey()
[プログラムの説明]
今まで何回も出てきたところは省略し、要点だけに絞って説明します。
9行目のForと19行目のNext iに囲まれた部分は整数1から10000までについて以下の処理(倍数かどうかを調べる)を繰り返しますという指示です。10行目は今調べている i の値 を整数aで割った余りを求めています。ここで余りが0でなければこれはaの倍数ではありませんからaとbの公倍数にはなり得ず以下の処理は不要となります。11行目のIfと18行目のEnd Ifに囲まれた中がIfプロックです。Ifブロックの中は独立した空間(この例の場合、aの倍数だけが入れる部屋と考えてください)ですから、この中にさらにIfブロックを置くこともできます。12行目では i の値をbで割った余りを求めます。
ここで i はすでにaの倍数という条件はクリアしているのでさらにbの倍数でもあるという条件もクリアできていればこの i の値はaとbの公倍数ということになります。そして1から順番に調べていくうちに、最初にみつかった公倍数なのでこれが最小公倍数ということになります。このプログラムでは最小公倍数がみつかればあとの数について調べる必要はありません。16行目のExit Forは今入っているFor~Nextループから脱出せよ、という意味です。したがって最小公倍数がみつかれば20行目に移ってプログラム終了です。このようにForとIfを組み合わせて使うと、ある条件を満たしたら繰り返し処理終了という流れが作れます。
[最小公倍数を求めるプログラム2]
このプログラムは2つの整数の最小公倍数を求めるものなので、論理演算子Andを使って次のように書くこともできます。
1: Dim i As Integer
2: Dim a As Integer
3: Dim b As Integer
4: Dim amari1 As Integer
5: Dim amari2 As Integer
6: Console.WriteLine("2つの数の最小公倍数を求める")
7: Console.Write("1つめの数(整数) ") : a = Console.ReadLine()
8: Console.Write("2つめの数(整数) ") : b = Console.ReadLine()
9: For i = 1 To 10000
10: amari1 = i Mod a
11: amari2 = i Mod b
12: If amari1 = 0 And amari2 = 0 Then
13: Console.WriteLine()
14: Console.WriteLine(i)
15: Exit For
16: End If
17: Next
18: Console.ReadKey()
このプログラムでは10、11行目でa、bで割った余りを求め、12行目でa、bの公倍数かどうかをいっぺんで判定しています。論理演算子を使うとこのようにIfブロックの中にまたIfブロックということをしなくてプログラムの行数も少なくて済みます。どちらの形で書くかはプログラムへの要求によって異なってきます。
[演習3]三択クイズのプログラム
簡単な三択クイズを作ってみましょう。問題文の選択肢を表示し、答えを番号で入力、正解なら「正解です」と不正解なら「残念でした」と表示することにします(図6-6参照)。
図6-6.三択クイズのプログラム実行画面
[コラム]コンピュータは忠実過ぎる部下
ここまでプログラミングをやってきた皆さんは、コンピュータは自分が作ったプログラムに従って忠実に動く部下のようにみえてきたことと思います。たしかにコンピュータは皆さんが指示したとおりの仕事を「疲れた~」とか「めんどくせ~」とか文句言わずにこなしてくれます。ただコンピュータは忠実過ぎて少々融通がきかないという面もあります。たとえば皆さんがプログラムを作って実行しようとしたところこのような画面になって実行できなかったということがあったりしませんでしたか。
図6-7.文法エラー
プログラミング言語には「言語」というくらいですから文法があります。文法といっても主語とか述語というものではなく、プログラムの書き方のルールのことです。図6-7ではConsole.Writelineと書かなくてはならないところがdonsole.Writelineになっているので、コンピュータが???になってしまい実行できないのです。「こんなの1文字タイプミスしただけ。見りゃConsoleだってわかるだろが」と言いたいところですが、それをコンピュータに求めるのは無理なのです。このようなプログラムの書き方の間違いによるエラーを文法エラーといいます。
図6-8.実行時エラー
プログラミング言語の文法どおりに書かれていればコンピュータはそれを忠実に実行しようとします。たとえ行く手に落とし穴があったとしてもです。図6-8のプログラムは文法どおりに書かれていますが、分母が0の割り算をやってしまっています。算数でも割る数が0の割り算は「不能」になりますが、コンピュータでも同じで扱えないデータが入ってきたり扱えない演算を実行しようとすると実行時エラーとなります。「計算できないとわかっているならその手前で止まれよ」と言いたくなりますが、これも無理です。そうしたいのならそのようにプログラムを組まなくてはなりません。
図6-9.論理エラー
文法も間違いない、あり得ないデータも入ってこない、無理な演算もない、それでも発生するエラーがあります。それは論理エラーといい、プログラム中の命令や式にミスがあって正しい結果が得られない、というものです。論理エラーのやっかいなところは文法エラーや実行時エラーのようにエラーが発生したところでコンピュータが止まらないことです。なのでプログラムのミスをさがすのに大変苦労します。図6-9のプログラムは半径10の円の面積を求めるもののつもりなのですが、結果が間違っています(314.159になるはずです)。これは円の面積を計算するところで、S = pai * r ^ 2(またはS = pai * r * r)とすべきところをS = pai * r * 2としてしまっているためです(ちなみにこれだと円周の長さになってしまいます)。
コンピュータによる計算、処理が正確だというのはプログラムやデータが正しく与えられている場合のことであり、これらが誤っていれば、間違った処理結果が出てしまったり途中で止まってしまったりします。
[昔はよかったなぁ]
最小公倍数を求めるプログラム1を昔のBASICで書くと次のようになります。
図6-10.最小公倍数を求めるプログラムを昔のBASICで書くと
昔のBASICではIfの後ろのEnd Ifというのがありませんでした。書かなくていいならラッキー!と思ってしまいそうですが、ちょっと待ってください。End IfがないということはIfブロックもないということです。条件が成立したときに行なう処理が複数行ある場合には、↑のプログラムの行番号60のようにthenの後ろに : で区切って複数の処理を書き連ねてゆくことになります。ここで条件が成立したときの処理が100行あったらどうなるでしょう。thenの後ろに : で区切られた処理が連なることになり大変見辛いプログラムになります。
図6-1.選択処理のイメージ
前章で繰り返し処理について学びました。同じことを何回も繰り返し実行するというのはコンピュータの得意技です。繰り返し処理についてはまだまだお話したいことがあるのですが、このカテゴリーの目的のひとつに、短期間でプログラミング的思考を身につけるというのがあるので、繰り返し処理の続きは後の章で学ぶとして、ここはひとまず次の話題に進むことにします。
昔話になりますが、管理人が小学校3年生のとき我が家に初めてカラーテレビが来ました。そのテレビは電源を入れた直後にマイコン制御で垂直同期が行われるようになっていたのですがテレピのボディに誇らし気に「人工頭脳付」というシールが貼ってありました。当時コンピュータは「人工頭脳」と呼ばれたものでした。今でも中国語では「電腦」(繁体)といいます。
どうしてコンピュータが人間の脳に例えられるのかというと、コンピュータにはこれから学ぶ判断、処理の選択ができるという能力があるからです(もちろんそのようなプログラムが入っているからなのですが)。
コンピュータが判断・処理の選択は、条件式が成立する(true)か成立しない(false)かで次の処理を実行するかどうかを決定する、というのが基本です(図6-1左)
。
[偶数奇数判定プログラム]
では。キーボードから入力された整数が偶数す奇数かを判定するプログラムを作ってみましょう。偶数とは2で割り切れる整数(0、2、4、6・・・)のことをいいます。対して奇数は2で割り切れない整数(1、3、5、7・・・)です。この判定を行なうには入力された数を2で割ってみて余りが出るかどうかをみればよいのですが、これをやるのにVB2022には便利な算術演算子がありましたね。そう、mod です。忘れてしまった方は第2章をもう一度見てください。
プログラムの流れは図6-1右のようになります。
この流れにもとづいて作ったプログラムは次のようになります。
1: Dim su As Integer
2: Dim amari As Integer
3: Console.Write(" 整数を入力してください ")
4: su = Console.ReadLine()
5: amari = su Mod 2
6: If amari = 0 Then
7: Console.WriteLine("偶数です")
8: Else
9: Console.WriteLine("奇数です")
10: End If
11: Console.ReadKey()
[プログラムの説明]
1行目はキーボードから入力した整数を保存する変数、2行目は入力した整数を2で割った余りを代入する変数の宣言です。3行目は何を入力するかを表示し、4行目でキーボードから整数の入力を受けます。そして5行目は入力した整数を2で割った余りを求めるところです。
次からが本章で中心になる判断・選択処理です。まず6行目です。If amari = 0 Thenとありますが、これは「もし、変数amariの値が0ならば次の処理を実行せよ」という意味です。どの処理を実行するのかというと7行目の「偶数です」と表示するところです。8行目の、Elseは「そうでなければ次の処理を実行せよ」という意味です。この場合なら9行目の「奇数です」と表示するところです。このようにIfとElseは条件が成立するかしないかで処理内容を分けるときに使いますが、どこまでが選択処理なのかということを示しているのが10行目のEnd Ifです。
[If 条件式 による処理の選択 ]
If制御文の使い方をまとめておきます。最も基本的な使い方は
If 条件式 Then
条件が成立したときの処理(複数行でも可)
End If
これは条件が成立したときだけ特定の処理を行なう(条件が成立しないときは何もしない)場合です。
If 条件式 Then
条件が成立したときの処理(複数行でも可)
Else
条件が成立しなかったときの処理(複数行でも可)
End If
今のサンプルプログラムに出てきたもので、条件が成立するかしないかで処理内容を分ける場合です。
[条件式]
選択処理や繰り返し処理の条件を指定する式を条件式といいます。条件式の書き方の基本を覚えましょう。
条件式の書き方の基本的な形は
式 比較演算子 式
です。条件式の場合、左辺は変数1個とは限りません。上のサンプルプログラムの6行目のamari = 0 は 0 = amari でもエラーにはなりません。あとはプログラムがわかりやすいかどうかです。そして条件式での = は代入演算子ではなく等号です。ややこしいですが早いところ慣れてください。
VB2022で使える比較演算子は次のとおりです。
図6-3.VB2022の比較演算子
[条件が複数あるとき~論理演算子]
図6-4.複数の条件式がある場合
条件式は1つではなく2つ以上書くこともできます。図6-4左を見てください。今、2つの条件式AとBがあるとします。条件式Aが成立する範囲はAとCです。そして条件式Bが成立するのはBとCです。そうするとCはA、B両方の条件式が成立する範囲ということになります。これを A And B と書きます。AかB、少なくともどちらか一方が成立する範囲はA、B、Cになります。これは A Or Bと書きます。Not は条件式が成立しない場合です。左の図で Not(A Or B) と書くと、Dの範囲になります。
この条件式と条件式を結ぶAnd、Or、Notのことを論理演算子といいます。VB2022で使える論理演算子はもっとあるのですが、この3つが基本になります。そして条件が成立することを真(True)、成立しないことを偽(False)といいます。
[Ifプロック]
If~End IfまでのひとかたまりをIfブロックとよびます。Elseがある場合、Ifブロックの中はさらに2つのブロックに分かれます。それぞれのブロックは独立した部屋のようなものです。1つのブロックで1つのプログラムと考えてもけっこうです。これだけではさっぱりわからないと思いますので、実際のプログラムでみてみましょう。
[最小公倍数を求めるプログラム1]
キーボードから入力した2つの整数aとbの最小公倍数を求めるプログラムを考えてみます。最小公倍数とは2つの整数の公倍数で共通するもののうちいちばん小さいものをいいます。ここでは小さい整数から順に2つの整数の公倍数かどうかを調べてゆくという方法をとります。整数a、bはせいぜい100くらいまで、調べる範囲は1~10000とします。プログラムの流れは下の図のようになります。
図6-5.最小公倍数を求めるプログラムの流れ
この流れに基づいて作成したプログラムはこのようになります。
1: Dim i As Integer
2: Dim a As Integer
3: Dim b As Integer
4: Dim amari1 As Integer
5: Dim amari2 As Integer
6: Console.WriteLine("2つの数の最小公倍数を求める")
7: Console.Write("1つめの数(整数) ") : a = Console.ReadLine()
8: Console.Write("2つめの数(整数) ") : b = Console.ReadLine()
9: For i = 1 To 10000
10: amari1 = i Mod a
11: If amari1 = 0 Then
12: amari2 = i Mod b
13: If amari2 = 0 Then
14: Console.WriteLine()
15: Console.WriteLine(i)
16: Exit For
17: End If
18: End If
19: Next i
20: Console.ReadKey()
[プログラムの説明]
今まで何回も出てきたところは省略し、要点だけに絞って説明します。
9行目のForと19行目のNext iに囲まれた部分は整数1から10000までについて以下の処理(倍数かどうかを調べる)を繰り返しますという指示です。10行目は今調べている i の値 を整数aで割った余りを求めています。ここで余りが0でなければこれはaの倍数ではありませんからaとbの公倍数にはなり得ず以下の処理は不要となります。11行目のIfと18行目のEnd Ifに囲まれた中がIfプロックです。Ifブロックの中は独立した空間(この例の場合、aの倍数だけが入れる部屋と考えてください)ですから、この中にさらにIfブロックを置くこともできます。12行目では i の値をbで割った余りを求めます。
ここで i はすでにaの倍数という条件はクリアしているのでさらにbの倍数でもあるという条件もクリアできていればこの i の値はaとbの公倍数ということになります。そして1から順番に調べていくうちに、最初にみつかった公倍数なのでこれが最小公倍数ということになります。このプログラムでは最小公倍数がみつかればあとの数について調べる必要はありません。16行目のExit Forは今入っているFor~Nextループから脱出せよ、という意味です。したがって最小公倍数がみつかれば20行目に移ってプログラム終了です。このようにForとIfを組み合わせて使うと、ある条件を満たしたら繰り返し処理終了という流れが作れます。
[最小公倍数を求めるプログラム2]
このプログラムは2つの整数の最小公倍数を求めるものなので、論理演算子Andを使って次のように書くこともできます。
1: Dim i As Integer
2: Dim a As Integer
3: Dim b As Integer
4: Dim amari1 As Integer
5: Dim amari2 As Integer
6: Console.WriteLine("2つの数の最小公倍数を求める")
7: Console.Write("1つめの数(整数) ") : a = Console.ReadLine()
8: Console.Write("2つめの数(整数) ") : b = Console.ReadLine()
9: For i = 1 To 10000
10: amari1 = i Mod a
11: amari2 = i Mod b
12: If amari1 = 0 And amari2 = 0 Then
13: Console.WriteLine()
14: Console.WriteLine(i)
15: Exit For
16: End If
17: Next
18: Console.ReadKey()
このプログラムでは10、11行目でa、bで割った余りを求め、12行目でa、bの公倍数かどうかをいっぺんで判定しています。論理演算子を使うとこのようにIfブロックの中にまたIfブロックということをしなくてプログラムの行数も少なくて済みます。どちらの形で書くかはプログラムへの要求によって異なってきます。
[演習3]三択クイズのプログラム
簡単な三択クイズを作ってみましょう。問題文の選択肢を表示し、答えを番号で入力、正解なら「正解です」と不正解なら「残念でした」と表示することにします(図6-6参照)。
図6-6.三択クイズのプログラム実行画面
[コラム]コンピュータは忠実過ぎる部下
ここまでプログラミングをやってきた皆さんは、コンピュータは自分が作ったプログラムに従って忠実に動く部下のようにみえてきたことと思います。たしかにコンピュータは皆さんが指示したとおりの仕事を「疲れた~」とか「めんどくせ~」とか文句言わずにこなしてくれます。ただコンピュータは忠実過ぎて少々融通がきかないという面もあります。たとえば皆さんがプログラムを作って実行しようとしたところこのような画面になって実行できなかったということがあったりしませんでしたか。
図6-7.文法エラー
プログラミング言語には「言語」というくらいですから文法があります。文法といっても主語とか述語というものではなく、プログラムの書き方のルールのことです。図6-7ではConsole.Writelineと書かなくてはならないところがdonsole.Writelineになっているので、コンピュータが???になってしまい実行できないのです。「こんなの1文字タイプミスしただけ。見りゃConsoleだってわかるだろが」と言いたいところですが、それをコンピュータに求めるのは無理なのです。このようなプログラムの書き方の間違いによるエラーを文法エラーといいます。
図6-8.実行時エラー
プログラミング言語の文法どおりに書かれていればコンピュータはそれを忠実に実行しようとします。たとえ行く手に落とし穴があったとしてもです。図6-8のプログラムは文法どおりに書かれていますが、分母が0の割り算をやってしまっています。算数でも割る数が0の割り算は「不能」になりますが、コンピュータでも同じで扱えないデータが入ってきたり扱えない演算を実行しようとすると実行時エラーとなります。「計算できないとわかっているならその手前で止まれよ」と言いたくなりますが、これも無理です。そうしたいのならそのようにプログラムを組まなくてはなりません。
図6-9.論理エラー
文法も間違いない、あり得ないデータも入ってこない、無理な演算もない、それでも発生するエラーがあります。それは論理エラーといい、プログラム中の命令や式にミスがあって正しい結果が得られない、というものです。論理エラーのやっかいなところは文法エラーや実行時エラーのようにエラーが発生したところでコンピュータが止まらないことです。なのでプログラムのミスをさがすのに大変苦労します。図6-9のプログラムは半径10の円の面積を求めるもののつもりなのですが、結果が間違っています(314.159になるはずです)。これは円の面積を計算するところで、S = pai * r ^ 2(またはS = pai * r * r)とすべきところをS = pai * r * 2としてしまっているためです(ちなみにこれだと円周の長さになってしまいます)。
コンピュータによる計算、処理が正確だというのはプログラムやデータが正しく与えられている場合のことであり、これらが誤っていれば、間違った処理結果が出てしまったり途中で止まってしまったりします。
[昔はよかったなぁ]
最小公倍数を求めるプログラム1を昔のBASICで書くと次のようになります。
図6-10.最小公倍数を求めるプログラムを昔のBASICで書くと
昔のBASICではIfの後ろのEnd Ifというのがありませんでした。書かなくていいならラッキー!と思ってしまいそうですが、ちょっと待ってください。End IfがないということはIfブロックもないということです。条件が成立したときに行なう処理が複数行ある場合には、↑のプログラムの行番号60のようにthenの後ろに : で区切って複数の処理を書き連ねてゆくことになります。ここで条件が成立したときの処理が100行あったらどうなるでしょう。thenの後ろに : で区切られた処理が連なることになり大変見辛いプログラムになります。
【第5章】繰り返し処理(1)
2022.04.07
ここまでで、当カテゴリーで必要なVB2022の操作は習得できたと思います。本章以後はプログラム作成・修正画面、実行画面は省略します。VB2022の操作がまだ不安な方は、ここまでの章をもう一度復習してください。
[順次処理と繰り返し処理]
ここまででやってきたプログラムをもう一度見直してみましょう。コンピュータのプログラムはコンサートや運動会のプログラムと同じで、最初から終わりまで書かれている指示(命令)が順番に実行されてゆくものです。これを順次処理(順処理)といいます。順次処理はコンピュータのプログラミングの基本中の基本です。
図5-1.コンサートのプログラム
図5-1はピアノリサイタルのプログラムの例です(しつこいようですが管理人の本業は・・・えーい、それもういいから)。音楽会では普通プログラムの順に曲が演奏されます。この例ならベートーヴェン、シューベルト、ドビュッシーの順に演奏されて終わります。よほどの事態が発生しない限りドビュッシーまで終わったところでベートーヴェンに戻ってもう一度全曲演奏されたり、シューベルトかドビュッシーのどちらか一方のみ演奏され他方は演奏されないということはありません。しかしコンピュータのプログラムでは、このようなことはしばしば行われます。同じ処理を繰り返し実行することを繰り返し処理、条件によりどちらか一方の処理のみ実行されることを選択処理といいます。この章では繰り返し処理について学びます。
まずは簡単な平均を求めるプログラムで繰り返し処理の基本を身につけてください。
たとえば次のような5つの数の平均を求めるとします。
67, 55, 42, 28, 30
暗算が得意な方なら、これをパッと見て44.4とすぐにわかることでしょう。しかし記憶力も計算速度も人間よりはるかに勝っているはずのコンピュータにはそれができないのです。コンピュータで数の平均を求めるにはひとつひとつの数をエッチラオッチラと足し算していって、その合計をデータ件数で割る、という行程をたどる必要があります。この考え方に基づいたVB2022のプログラムはこうなります。
1:Dim Gokei As Integer
2:Dim Ninzu As Integer
3:Dim Tensu As Integer
4:Dim i As Integer
5:Dim Heikin As Single
6:Gokei = 0
7:Ninzu = 0
8:For i = 0 To 4
9: Console.Write(" 点数 = ")
10: Tensu = Console.ReadLine()
11: Gokei = Gokei + Tensu
12: Ninzu = Ninzu + 1
13:Next i
14:Heikin = Gokei / Ninzu
15:Console.WriteLine()
16:Console.WriteLine(" 平均 = " & Heikin)
17:Console.ReadKey()
以後、説明をスムーズに行なうためにプログラムリストに行番号を付けます。上のプログラムリストをコピー&ペーストで
Sub Main~End Subに貼り付ける場合、面倒ですが、行番号は消してください。
[プログラムの説明]
1~5行目はプログラム中で使用する変数の宣言です。
Gokei 各々の生徒のテストの点数を加算する(整数型、テストの点は正の整数とします)
Ninzu データの数(この場合、受験した生徒の人数)をカウントする(整数型)
Tensu キーボードから入力したデータを受け付ける(整数型、テストの点は正の整数とします)
i 繰り返しの回数をカウントする(整数型)
Heikin 計算した平均点を代入する(実数型、割り算が入る以上、結果は少数になることもある)
順番が入れ替わりますが、先に8行目の
For i = 0 To 4
について説明します。ここで ForはPresent for you💓のforではなく「~の間」の意味と考えてください。つまり
「変数i の値が0から(1ずつ増加して)4になるまで、以下の処理を繰り返せ」
ということになります。これが繰り返し処理の指示です。どこまでを繰り返すのか、ということを示しているのが13行目のNext iです。
これで9~12行目は、i=0 として1回目、i=1 として2回目・・・i=4 として5回目と5回繰り返されます。繰り返される処理内容はこうなります。
9行目:画面に「点数 = 」と表示します
10行目:キーボードから読み込んだデータを変数Tensuに格納します(変数Tensuにキーボードから入力されたデータを保存する、と考えてもOKです)
11行目:今、入力されたデータを変数Tensuに加算します
12行目:データの件数を+1します
この11~12行目は、数学の先生に叱られてしまいそうな式ですね。=は数学では等号といい左辺と右辺の値が等しいという意味でした。VB2022に限らずプログラミング言語では=は条件判定(後述)の場合を除き、統合ではなく代入演算子(右辺の値を左辺に代入する)です。忘れてしまった方は第3章をもう一度復習してください。
繰り返しを抜けた後は平均の計算です。
14行目:データの合計÷データの件数を変数Heikinに代入(保存)します
15行目:結果を表示する前に1行空けます
16行目:計算結果(ここでは平均)を表示します
17行目:何かキーが押されるまで画面を閉じるのを待ちます
[コンピュータのプログラムならではの書き方]
繰り返し処理の流れについてはご理解いただけたでしょうか。ではちょっと戻って先程説明を飛ばしてしまった6、7行目です。これらの変数GokeiとNinzuはキーボードからデータが入力される度に、そのデータを加算(足しこみ)し、データ件数をカウントするものですが、これを最初に0としています。そろばんで最初に「ご破算で願いましては」とやる(電卓なら最初にオールクリアキーを押す)のと同じです。どうしてこんなことをしなくてはならないかというと、変数は最初に宣言しただけではそこにどういうデータが入っているかわからない、からです。たとえば1行目でデータの合計をとるGokeiという整数型変数を宣言していますが、宣言した段階でここに100というデータが入ってしまっていて、かつ6行目がなかったらどうなるでしょうか。計算結果は全く誤ったものとなってしまいます(VB2022では数値型変数は宣言した段階で0が、ストリング型変数ではNull""が代入されるようになっているのですが、すべてのプログラミング言語がそうなっているとは限りません。管理人がコンピュータ屋だった頃使っていたCOBOLやFORTRAN言語ではそのような親切なことはやってくれませんでした)。合計をとるための変数は繰り返し処理に入る前に0にしておく、と覚えておきましょう。
[For ~ Nextによる繰り返しの条件]
For ~ Nextで繰り返し処理の範囲を指定するには
For 数値変数 = 初期値 To 終端値 Step 増分値
Next 数値変数
という書き方になります。ここで Nextの後の数値変数はForの後の数値変数と同じものにする必要があります。ただしNextの後の数値変数は省略することができます。省略した場合、そのNextはそこからさかのぼっていちばん近いForとペアとみなされます。
For ~ Nextは「Forの後の数値変数が初期値から始まって増分値ずつ変化し、終端地を越えるまでの間、Nextの手前までの処理を繰り返せ」という指示になります。Step 増分値を省略するとStep 1とみなされます。つまり、次の3つのプログラムはどれも「VB2022」が5回表示されることになります。
Dim i As Integer
For i = 0 To 4
Console.WriteLine("VB2022")
Next i
Console.ReadKey()
Dim i As Integer
For i = 3 To 7
Console.WriteLine("VB2022")
Next i
Console.ReadKey()
Dim i As Integer
For i = 4 To 0 Step -1
Console.WriteLine("VB2022")
Next i
Console.ReadKey()
次のプログラムは初期値と終端値が同じです。この場合「VB2022」は1回だけ表示されます(For ~ Next内は1回だけ実行されます)。
Dim i As Integer
For i = 3 To 3
Console.WriteLine("VB2022")
Next i
Console.ReadKey()
次のように初期値が終端値を越えていると「VB2022」は1回も表示されません(For ~ Next内は1回も実行されません)。
Dim i As Integer
For i = 3 To 2
Console.WriteLine("VB2022")
Next i
Console.ReadKey()
[注意]
1)Forの後の数値変数(繰り返しの回数を数えるのでループカウンタとよびます)は特に必要がない限り整数型にしておきましょう。次のプログラムは「VB2022」と10回表示されるかと思いきや実際には9回しか表示されません。この理由については後の章で詳しくお話します。
Dim i As Single
For i = 0.1 To 1 Step 0.1
Console.WriteLine("VB2022")
Next i
Console.ReadKey()
2)ループカウンタは参照するのはかまいませんが値を変えるのは慣れないうちはやめておきましょう。具体的には式の右辺に使うのやConsole.Writeline()などで表示するのはかまいませんが、式の左辺に使うのやConsole.Readline()で値を代入するのは避ける方が無難です。
次のプログラムを実行するとどうなるでしょう。
1: Dim i As Integer
2: For i = 11 To 20
3: Console.WriteLine("ピーターパンは" & i & "歳になりました")
4: i = 10
5: Next i
6: Console.ReadKey()
実行するとこうなります。
ループカウンタは11から始まって1ずつ増えて20を越えたら終わるはずです。3行目を見るとConsole.Writelineの( )の中にループカウンタの i が入っているのでその時点でのループカウンタ i の値が表示されるので「ピーターパンは11歳になりました」「ピーターパンは12歳になりました」 ・・・と表示されてゆき「ピーターパンは20歳になりました」で止まるはずなのですが、実行すると「ピーターパンは11歳になりました」と延々と表示され終わりません。なんでこんなことになってしまうのでしょうか。そうです。4行目に i = 10 があるため(ここを通る度にループカウンタ i に10が代入されてしまうので)、Next iで繰り返しに戻っても i の値は常に11になってしまい終端値の20を超えることはないのです。「ピーターパンは永遠に歳とらない男の子だからこれでいいのだ」ではなく、プログラムのミスでコンピュータが止まらなくなっているのですからこれは立派な暴走です。
[演習2]粗利益の合計を求めるプログラム
前章の[演習1]で作ったプログラムを改造し、照り扱い商品が5つある場合のそれぞれの粗利益と最後にすべての商品の粗利益合計を求めるプログラム(下図参照)を作りましょう。
【第4章】キーボードからデータを入力するプログラム
2022.04.06
変数を使う意味
前章のプログラムで学んだとおり変数には、違う数値(データ)で同じ計算(処理)をしたい場合、変数に入れる数を変えるだけで済むという利点があります(図4-1)。
図4-1.変数を使うと
しかし、このままだと違う数値で同じ計算をする度にいちいちプログラムの修正が必要になります(図3-3の8~10行目)。VB2022の起動に時間がかかり、ConsoleApp1の呼び出しにはタバコ1本吸うくらい待たされ(非喫煙な方にはわかりにくい例えでごめんなさい)、こんなの筆算でやった方が早いわ!そんな声が聞こえてきそうです。この章では、前章のプログラムの変数に値を代入する部分をプログラムを変更することなくできるように改造してみましょう。
[実習4]キーボードからデータを読み込むプログラム
では再びVB2022を起動しConsoleApp1を呼び出してください。呼び出したらこのプログラムを次のように改造します(例によってキー入力が面倒な方はSub Main()とEnd Subの間をすべて消して下のプログラムをコピペで入れていただいてもかまいません)。
Dim a As Integer
Dim b As Integer
Dim c As String
c = Console.ReadLine()
a = Console.ReadLine()
b = Console.ReadLine()
Console.WriteLine("Hello! " & c & "さん")
Console.WriteLine(a + b)
Console.WriteLine(a - b)
Console.WriteLine(b * a)
Console.WriteLine(b / a)
Console.WriteLine(b ¥ a) '(¥は半角に直してください)
Console.WriteLine(b Mod a)
Console.WriteLine(b ^ a)
Console.Readkey()
図4-2.プログラム修正後
図4-2のように修正出来たら保存し実行してみましょう。今度は最初に図4-3のように真っ黒な画面の左上でカーソルが点滅していると思います。
図4-3.プログラム実行開始直後
ではここでご自分の名前でも好きな人の名前でも「青春のバカ野郎!」(筆者の歳がバレますね・・・大汗)でもいいので入れてEnterキー(Returnキー)を押しましょう。するとカーソルの点滅が次の行に移ります。こんどは半角で 3 と入れてEnterキーです。同じようにカーソル点滅が次の行に移ったら半角で 5 と入れましょう(数値は必ず半角の整数で、小数や全角で入れると不都合が発生します)(*1)。
図4-4.名前と2つの数値を入れ終わった
2つ目の数値(この例では 5)まで入れてEnterキーを押すと、実行画面が図4-5のようになります。
図4-5.プログラム実行結果
[プログラムの解説]
今回のプログラムは実行するとすぐにキーボードからの入力待ち状態になりました。カーソルが点滅している状態がそれです。これはプログラム中のどこがなせる業かといいますと、図4-2の8~10行目です。この3行に
というのが出てきますが、これはキーボードから1行分のデータを読み込みなさい、という命令です。1行分というのはキー入力を始めてからEnterキーを押すまでのことです。つまりプログラムは実行開始後8行目でオペレーター(このプログラムの使用者)が何かデータを入れるのを待っているわけです。ここで自分の名前などを入れてEnterキーを押すと次は9行目で入力待ちに、何か数を入れてEnterキーを押すと10行目で入力待ちに、ここでもうひとつ数を入れてEnterキーを押すと11行目以下の処理を行い図4-5のようになります。
Console.Readline()で読み込んだデータはそのままでは入力を受け付けただけで消えてしまいます。そこで8~10行目のように、
で読み込んだものを変数に代入しておくのが普通です。
変数に代入する値をキーボードから入力できるようにすると、異なるデータで同じ処理(*2)を行う場合、プログラムの修正の必要がなくなるなどの利点はたしかにあるのですが、キーボードを操作するのは人間です。人間のやることにはミスが付き物です(筆者はそう思っています)。もし銀行の窓口に預金に行って10000円預金するところを行員さんが誤って1000000円と入力してしまったら?
[実習5]台形の面積を求めるプログラム~誤操作対策を施す(1)
台形の面積を求めるプログラムを考えましょう。台形の面積は一時期、小学校の算数から消えていたため、習っていないという方もいらっしゃるかもしれませんから簡単に説明しておきます。台形とは少なくとも2辺が平行な四角形のことで、その平行な2辺をそれぞれ「上底」「下底」とよびます。そして台形の面積は(上底+下底)×高さ÷2で求められます(図4-6)
図4-6.台形
ここでは、上底、下底、高さはキーボードからの入力で整数のみとします。そして求めた面積も変数に代入してから表示することにします(*3)。
ではさっそくプログラムを作りましょう。今度は全く新しいプログラムを作るので、新規作成にします。VB2022を一度終了した方は再起動して新しいプロジェクトの作成にしてください(忘れてしまった方は第1章をご覧ください)。図4-2の画面のままの方は保存した後、画面左上のファイルメニューから新規作成→プロジェクト→コンソールアプリと進んでください。どちらにしても今度は名称がConsoleApp2になります。
ここまでの内容がマスターできた方は、プログラムは次のようになることは容易にわかると思います。
Dim a As Integer
Dim b As Integer
Dim h As Integer
Dim s As Single
a = Console.ReadLine()
b = Console.ReadLine()
h = Console.ReadLine()
s = (a + b) * h / 2
Console.WriteLine(s)
Console.Readkey()
変数a、b、hはそれぞれキーボードから入力された上底、下底、高さを代入するものです。今回は整数に限定されていますので、Dimによる型宣言はIntegerでOKです。変数sは計算した台形の面積が代入されるものですが、a、b、hすべてが整数だとしても最後に÷2がある以上、計算結果は小数になる可能性もあります。小数を代入する変数の型はSingle(実数型)でした(【第3章】変数とデータの型の[プログラムの解説]参照)。
(a + b)× h ÷ 2 をVB2022で書くと
となります。ここで( )は半角で入れてください。演算の優先順位は算数と同じで、最初に( )内が計算されます。次にべき乗、乗除算、加減算の順に計算されます。ここまでは算数と同じ(VB2022に限らずほとんどのプログラミング言語でそうなっています)ですが、ひとつ注意を要するのは算数で使う{ }(大括弧)がないことです。たとえばx - { y + ( a + b )× h ÷ 2 }という式の場合、VB2010ではこう書きます。
{ }の部分は( )となります。かなりゴチャゴチャしてきますので( )の対に注意してください。
このプログラムを実行すると図4-7のようになるのですが・・・。
図4-7.プログラムの実行画面
いかがですか?皆さんはこの画面を見てどう思いますか?オペレーターになったつもりで見てください。
このプログラムは実行開始直後にすぐ入力待ちとなり、まずここで上底の長さを入力します。次に下底の長さ、最後に高さを入れるのですが、この画面では入力待ちでカーソルが点滅するだけで、何の値を入れればよいのかが(プログラムを作った当人でない限り)わかりません。また、VB2022ではConsole.WriteLine( )で表示すると数値もストリングもすべて左詰めになるので画面が大変見づらくなります。「操作がわかりにくい」「画面が見辛い」は誤操作を引き起こす最大原因です。しかし、これが図4-8のような実行画面ならかなりオペレーターに優しいものになります。
図4-8.改良された実行画面
では、このようになるようプログラムを改造しましょう。こうなります。
Dim a As Integer
Dim b As Integer
Dim h As Integer
Dim s As Single
Console.WriteLine(" 台形の面積を求める")
Console.WriteLine()
Console.Write(" 上底 ") : a = Console.ReadLine()
Console.Write(" 下底 ") : b = Console.ReadLine()
Console.Write(" 高さ ") : h = Console.ReadLine()
s = (a + b) * h / 2
Console.WriteLine()
Console.WriteLine(" 面積 = " & s)
Console.Readkey()
[プログラムの解説]
図4-9.画面の見やすさを改良したプログラム
5~8行目はもう説明不要ですね。まだよくわからない方は【第3章】データの型を復習してください。
9行目では「何のプログラム」かを表示しています。これも誤操作防止のひとつです。LINEなどのコミュニケーションツールでは送信相手の名前が画面最上段に表示されるのが普通ですがあれも誤送信防止のためです。「今から帰る。愛してるよ、Chu」と奥様に送るのを間違えて、学生連絡用のグループに送信してしまったら?翌日どのツラ下げて出勤するんだ、ということになります。筆者に言わせてもらえれば、情報漏洩の原因のうちかなりのパーセンテージを誤操作が占めます。これと同じで、コンピュータを使う仕事が1日1つしかないのならともかく、1日に3つも4つもある場合、今何のプログラムを起動したのかを表示しておくことにより、違うプログラムを誤って実行してしまうミスを防げます。
10行目はConsole.Writeline()だけで表示する内容が書かれていません。これで空白行が1行できます。ここでは画面を見やすくするために入っています。空白行の場合でもConsole.Writeline()と、()が必要になることに注意してください。11~13行目では
というのが出てきました。Console.Writeline()は行単位の表示(1行表示された後改行)ですが、Console.Write( )は表示後の改行はしません。
11~13行目では、さらに : が出てきました。これはマルチステートメントといい、プログラムの1行の中に複数のステートメント(プログラム中に書かれる命令や計算式などのこと)を書きたい場合に使用します。たとえば11行目は、「上底」と表示し、キーボードからの入力待ちとなります。これは
Console.Write(" 上底 ")
a = Console.ReadLine()
と2行に分けて書いてもコンピュータは同じ動作をします。12、13行目も同様に「下底」と表示して入力待ち、「高さ」と表示して入力待ちとなります。このマルチステートメントはむやみに使うと、プログラムがわかりにくくなるので使う際には注意が必要です。このプログラムでは実行画面の1行の表示と入力待ちをプログラムの1行に対応させる目的で使っています。
それから、Console.Write( )で表示するストリングはすべて左に全角1文字分のスペースを入れました。これにより表示内容が画面の左にギュッと寄ってしまうことはなくなります。
16行目は計算結果の表示ですが、ここでは1行に表示する内容が「面積 =」というストリングと s という実数型変数が混在しています。このようにストリングと数値を連結するときはストリング演算子の & を使います( + を使うと不具合が起こります)(*4)。
誤操作防止は操作をわかりやすくする、画面を見やすくするの他にもいろいろあります。以後のサンプルプログラムでも少しずつお話してゆきます。
[演習1]粗利益を求めるプログラム
ここまでで覚えた知識を使って、自分でプログラムを作ってみましょう。最初は粗利益を計算するプログラムです。会社員の方には説明不要ですが、このサイトは小学生も見ている可能性もあるので説明しておきます。
粗利益とは売上金額から仕入金額を引いたものです。たとえば1個100円で仕入れた品物を150円で売ると150円-100円で、50円利益が出たことになります。この品物が10個売れたとすると売上金額(150円×10個=1500円)から仕入金額(100円×10個=1000円)を引いた500円がこの品物を売って得られた利益ということになるのですが、会社をやってゆくためにはこの利益から社員の給料や会社で使うパソコンを買ったり電気代などを支払います。なのでこの500円はそういう必要なお金を支払う前の大雑把な利益という意味で粗利益(そりえき)といいます。
では次の画面のようなプログラムを作ってください。
[コラム]コンピュータってどういう機械(2)
筆者がコンピュータの勉強を始めた頃読んだ入門書にこんなことが書かれていました。
たしかにそのとおりです。ここまでで皆さんが学んだ範囲でも、プログラムを入れ替えることによって、四則演算のための計算機になったり台形の面積を求める機械になったりしました。さらに家計簿のプログラムを入れれば家計簿になりますし、ネット回線につないでインターネット上のコンテンツを見るためのブラウザを使えば、いろいろな人とコミュニケーションをとることができたり、動画を鑑賞したりもできます。
第2章のコラムではコンピュータを構成する様々な装置についてお話しました。この機械(装置)そのもののことをハードウェアといいます。ハードウェアは元々金物という意味です。これに対し皆さんが作ったプログラムや市販のパソコン家計簿、インターネットブラウザなどのことをソフトウェアといいます(*5)。ソフトウェアという言葉は、コンピュータの出現により出てきた造語で、狭義ではコンピュータを動かすプログラムのこと、広義ではコンピュータの利用技術全般を意味します。コンピュータ以外の世界でも「ハード面の整備はできた。これからはソフト面の充実が課題だ」などと使われたりします。コンピュータとはプログラム(ソフトウェア)により、様々な動作をする機械ということになります(*6)。
[昔はよかったなぁ]
この章のサンプルプログラムを昔のBASICで書くとこうなります。
100 DEFINT A,B,H
110 DEFSNG S
120 PRINT
130 PRINT "台形の面積"
140 PRINT
150 INPUT " 上底 ",A
160 INPUT " 下底 ",B
170 INPUT " 高さ ",H
180 S = (A + B) * H /2
190 PRINT
200 PRINT " 面積 = ";S
210 END
DEFINTは整数型変数の、DEFSNGは単精度型本数の宣言でした。第2章でもお話ししたとおり、昔のBASICではこの2行はなくてもプログラムは問題なく動きました。INPUT命令は行番号150~170のようにストリングを間に入れることができました。図4-9の11~13行目のように、1行で入力内容の表示とキー入力を行ないたい場合は大変便利でしたが、VB2022ではこれはできません。a = Console.ReadLine("上底")などとやると実行時に不具合が発生します。ご注意ください(*7)。
(注)
*1)VB2022が数値として認識するのは半角数字と符合を示す +(プラス)と -(マイナス)、 .(小数点)だけです。全角文字はすべてストリングとみなされます。VB2022だけでなく、筆者が知る限りほとんどのプログラミング言語でそうです。
*2)計算に限らず、コンピュータが行う仕事全般を「処理」といいます。
*3)実用プログラムでは計算結果は一度変数に代入してから表示するようにするのが普通です。その計算結果をあとでもう一度使うということが起こることはしばしばあるからです。
*4)後の章でデータ型変換について学びますが、そこでガッツリ説明します。
*5)近年、スマートフォンやタブレットでの言い方に合わせて「アプリ」とよぶことが多いようです。
*6)昔よくいわれたことに「コンピュータ、ソフトがなければただの箱」というのがあります。どんなに高性能なパソコンを買ってもその性能を充分引き出せるソフトウェアがなければただの粗大ゴミです。
*7)VB2022のコンソールアプリを使う限り、画面出力、キーボード入力は昔のBASICに比べると不便です。Windowsアプリ(フォームアプリ)では画面レイアウトが昔のBASICとは比べ物にならないくらい便利になったことがわかります。
【第3章】変数とデータの型
2022.04.05
[実習3]変数を使うプログラム
VB2022を起動し、前章でやった要領でConsoleApp1を呼び出してください。「今までもそうだったけど呼び出しにしても新規作成にしてもすごく時間がかかるな」、ほとんどの方は今そのような感想をお持ちのことと思います。図3-1のような画面が出たきり、長い時は5分くらい待たされます。今日はプログラムの話をする前に最初にこのことを説明しておきます。
図3-1.プロジェクトの起動中
これはVB2022ではたとえ数行の短いプログラムでもプロジェクト、ソリューションが作成されるためです。たとえば鉄道を作ることを考えてみます(筆者の趣味が入った例ですみません)。鉄道建設は線路を敷く、駅を作る、そこを走る電車を作るなど、様々な仕事が融合しているものです。この1つ1つがプロジェクト(project=事業)です。そしてたとえば線路を敷くにしてもこの鉄道が通る場所が平坦な所ばかりとは限りませんから、高架線を作る、トンネルを掘る、鉄橋を掛けるなどの作業が融合しています。これらの作業がプログラムです。そしてこうしたプログラム、プロジェクトが一体となって鉄道建設というソリューション(solution=解決)が実現します。VB2022のプロジェクト、ソリューションもこれと同じ考え方です。
図3-2.プログラムとプロジェクト、ソリューションの関係
前章でみなさんが作ったプログラムは図3-2でいえばプロジェクトAの中のプログラム1だけです。しかし、1つの短いプログラムだとしても、それを作る時にはVB2022はプロジェクト用の作業場所や会議室に相当するスペース、さらに将来的にたくさんのプロジェクトが誕生することを見越してソリューション用のビルを用意するものと思ってください。それゆえ、プログラム新規作成時も呼び出し時もかなりの時間がかかるのです。
お話している間に、前章で作ったプログラムが出てきたと思います。ではこのプログラムを次のように改造してみましょう。
Dim a As Integer
Dim b As Integer
Dim c As String
a = 3
b = 5
c = "Boys and Girls"
Console.WriteLine("Hello! " & c)
Console.WriteLine(a + b)
Console.WriteLine(a - b)
Console.WriteLine(b * a)
Console.WriteLine(b / a)
Console.WriteLine(b ¥ a)
Console.WriteLine(b Mod a)
Console.WriteLine(b ^ a)
Console.Readkey()
変更する箇所がかなりたくさんあるので、キー入力が得意ではない方は、前に作ったプログラム(Sub Main()とEnd Subの間に書き込まれているプログラム)をいったん消して、上のプログラムをコピー&ペーストで入れていただいてもけっこうです。
図3-3.プログラム追加・修正が終わったところ
図3-3のように追加・修正ができたら、保存してから実行してみましょう。今度は図3-4のような実行結果になったと思います。
図3-4.実行結果
[プログラムの解説]
図3-3のプログラムと前章の図をもう一度見てください。お気づきのことと思いますが、前章でやったプログラムのConsole.WriteLine(3 + 5)の3、5に相当する部分がa、bに、そして"Everyone"に相当する部分がcという文字に置き換わっていて、8~10行目を見ると中1の数学で初めて習った、あの式みたいなのが新たに入りました(筆者は中1で数学で初めてこれを習った時、なんかボク、すごいことができるようになったのかな、とワクワクした記憶があります)。さらに実行結果(図3-4)と照らし合わせてみると、どうやら今度はこのa、b、cに代入された数値やストリングをもとにプログラムが実行されたことがわかります。
このプログラムに出てきたa、b、cのようなものを変数といいます。数学でいう変数とは少し意味が違っていて、コンピュータのプログラミングでいう変数とは「データの入れ物」とお考えください(*1)。そしてこのデータの入れ物には数値だけでなく、ストリングも入れられます。
この変数をプログラム中で使用するには、使用する前に何という名前の変数にどのようなデータを入れます、という宣言(*2)が必要になります。それが5~7行目です。変数の宣言の仕方は
となります。ここで変数名は何でもかまいません。試してみたところVB2022では日本語(全角)も変数名として使えるようです。
次にデータ型です。たとえば紙袋は軽い書類やおみやげのお菓子などを入れるもので、5kgもあるような重い書類を入れれば持ち手の紐が切れたりしますし、水を直接注入することはできません。重い書類を持ち運ぶには丈夫なバッグが、水を持ち歩くにはペットボトルやポットが必要なように変数もどのようなデータを入れるのかによって用途に合わせたものを用意しなくてはなりません。とりあえず今は次の3つだけ覚えてください。
Integer 整数型 整数のみ入れられる
Single 実数型 小数を含む数値が入れられる
String 文字列型 ストリングが入れられる
データ型はこの他にもたくさんあるのですが、必要になったところでまだ追加説明します。現段階ではこれだけ覚えておけばサンプルプログラムは理解できます。
ところで変数もなのですが、数学で使用するものとプログラミングで使用するものではまるで意味が違うのが=(イコール)です。数学では=は左辺の値と右辺の値が等しいことを表す「等号」でしたが、プログラミングの世界では=は代入演算子と呼ばれ、右辺の値を左辺に代入するという意味になります(*3)。ですから数学のように、a + b = b + aのような使い方はできません。=の左辺は必ず変数1個です(*4)。代入演算子の使い方は次のようになります。
したがって、このプログラムはaを3、bを5とし、11~18行目の計算を行うプログラムということになります。18行目の^(べき乗)はまだ説明していませんでしたが、これは a ^ nのように使います。この場合aのn乗というとになります。
今まで覚えた算術演算子、代入演算子の他、このプログラムでは&という演算子が出てきました。これはストリング(文字列)連結演算子とよばれ、文字列を連結する際に使います。このプログラムでは&のかわりに+でも同じ結果が表示されるのですが、ストリング連結では&と+では少し意味が異なります(後にデータ型の変換のところで学びます)。
Dim a As String
Dim b As String
Dim c As String
Dim d As String
a = "I "
b = "Love"
c = "You"
d = a & b & c
Console.Writeline(d & ".")
Console.Read()
というプログラムなら実行結果は I Love You. となります。
[昔はよかったなぁ]
この章の実習でやったプログラムを昔のBASICで書くとこうなります。
100 A=3
110 B=5
120 C$="Boys and Girls"
140 PRINT A+B
150 PRINT A-B
160 PRINT B*A
170 PRINT B/A
180 PRINT B¥A
190 PRINT B MOD A
200 PRINT B^A
210 WHILE INKEY$="":WEND
220 END
昔のBASICでは変数の使用宣言はとくに必要ありませんでした。ストリングを入れる変数のみ変数名の末尾に$を付けるだけでOKでした。VB2022では変数名+$というのはありません。
昔のBASICではDEFINT、DEFSNGなどによる型宣言はしなくてもプログラムは問題なく動作しましたが、VB2022では変数はデータ型に関係なく使用宣言が必要になります。
また昔のBASICでは計算式はA+B、A¥Bのように書けたものが、VB2022では演算子の左右には半角スペース1個が必要になります。今のBASICはいろいろと面倒になったもんじゃのう。しかしその面倒さを差し引いてもVB2022には昔のBASICでは想像もつかなかった便利な機能がたくさんあります。これから少しずつ覚えてゆくことにします。
(注)
*1)もう少し正確にいうと、データが入っている場所を示すものです。本や書類で必要な、大事なところに貼っておく付箋紙のようなものです。詳しくは後の章で説明します。
*2)パソコンに向かって「宣誓!我々は~」とやるわけではありません。プログラミングでは何かをするための準備段階のこととお考え下さい。
*3)後の章で学びますが、条件判定のときには等号となります。
*4)正確に言うと、オブジェクト1個です(後の章で学びます)。