🐚

[魚戸ホタル] C#勉強備忘録3日目

2022/03/18に公開

おはようございます
こんにちは
ほたー

今回の備忘録は主なテーマは以下の2点です。
使用教材は亀田健司(著)1週間でC#の基礎が学べる本になります。

対象ページは以下の通りです。

  1. 110~133
  2. 134~160
C#備忘録アーカイブ

C#における繰り返し処理

for文

1日目で書いたように、アルゴリズムの三大処理は順次処理、分岐処理、繰り返し処理です。
3日目では上記の三大処理のうち繰り返し処理について勉強しました。

条件分岐にはfor文、while文、do while文を使います。
「~の条件を満たせなくなるまで…の処理を繰り返す」という処理に用います。
例えばスイッチを押すと1分ごとに点滅し10分たったら点滅しなくなるライトがある場合、10分になるまで1分ごとの点滅を繰り返すといった感じです。

まずfor文について上記のライトの例のようなプログラムを実行するソースコードを書きました。
実行結果を見るとfor文の中の{}に囲まれた部分が10回実行されたことがわかりました。

for (int i = 1; i <= 10; i++)
{
       Console.Write(i + " 点滅 ");
}
Console.WriteLine ();

実行結果

for文はfor(初期化処理; 条件式; 増分処理;) { 処理 }という構造になっており、上記のソースコードを例に説明すると初期化処理は「int i = 1」なので、iの値は1から始まります。
条件式は「i <= 6」なのでiが6以上になるまでこの処理が繰り返されます。
増分処理は「i++」と書いてありますが、これはインクリメントといい、iの値を1ずつ増加させる処理です。
「i--」と書くと逆にiの値が1ずつ減少させる処理となり、これはデクリメントといいます。

while文、do while文

ループを行うのはfor文だけではなく、while文を用いることによっても実現できます。

while文はwhile( 条件式 ) { 処理 }という構造になっており、条件式が成り立つ間は{}内の処理が繰り返されます。

while文について次のソースコードを書きました。
実行するとコンソールで試合数を入力した後に、入力した数だけwhile文内の処理が実行されます。
まず乱数と呼ばれるでたらめな数を生成するためにRandomオブジェクトを生成します。
続いてこの発生させたオブジェクトから乱数を発生させます。
Next(1, 7)とすると最小値が1で7未満、すなわち最大値6までの乱数が発生します。
発生した乱数が奇数であれば 勝利 、偶数であれば 敗北 と表示し、while文内の処理が終了した後に勝敗の総数を表示します。

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UotoHotaru0317_4
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 乱数の初期設定
            Random rnd = new Random();
            Console.Write("試合数を入力してください:");
            int games = int.Parse(Console.ReadLine());
            int i = 1; // 試合数カウンタ
            int win = 0; // 勝利カウンタ
            int lose = 0; // 敗北カウンタ
	    // iの値がgames以下の場合繰り返し処理を実行する
            while (i <= games)
            {
                Console.Write("{0}試合目:", i);
                // 1~6までの乱数を発生させる
                int n = rnd.Next(1, 7);
                if (n % 2 == 1)
                {
                    Console.Write("勝利");
                    win++;
                }
                else
                {
                    Console.Write("敗北");
                    lose++;
                }
                Console.WriteLine();
                i++;
            }
            Console.WriteLine();
            Console.WriteLine(win + "勝" + lose + "敗");          
        }
    }
}

実行結果

上記のソースコードでコンソールに143と入力すると、野球のペナントレース143試合の勝敗結果が表示できます。
際立って肩入れしているチームはございませんが、スタジアムの臨場感が好きです。

do while文ではdo { 処理 } while (条件式)という構造になっており、条件式が成り立つ間は{}内の処理が繰り返されます。
while文との違いは条件が成り立たなくても最低1回は実行されるということです。
例えば下記のソースコードで変数nとiが両方10になっており、while文にある条件式がi < nであるため10 < 10となり条件が成り立たないはずですが実行されます。

int n = 10;
int i = 10;
do
{
     Console.Write(i + " 点滅 ");
     i++;
}
while (i < n);

実行結果

C#における配列変数

アルゴリズムとデータ構造はプログラムの構造を考えるうえで必要な知識です。
データがエサでアルゴリズムが捕まえ方というのは備忘録1日目で説明しました。
ここまで変数には1つのエサのみ入れてきましたが、エサがある度に変数を定義するのは面倒です。
エサの数が決まっていれば 配列変数を使うのがベストです。
配列変数 は単に 配列 とも呼ばれ、多数のデータを入れる箱になり、大量のデータを扱う場合に必要になります。

配列について次のソースコードを書きました。
入力された1週間分の食費から最大値・最小値を求めます。

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UotoHotaru0325_15
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("1週間分の食費を入力してください。");
            int[] p = new int[7]; // 食費を入れる配列を定義
            string[] weekdays = { "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"};
            for(int i = 0; i < p.Length; i++)
            {
                Console.Write("{0}: ", weekdays[i]);
                int num = int.Parse(Console.ReadLine());
                p[i] = num; // 変数の代入
            }

            Console.WriteLine(); //改行

            // 最初の値を仮の最大値・最小値に設定
            int maxprice = p[0];
            int minprice = p[0];
            // 最大値・最小値になった曜日名を入れる変数を設定
            string maxday = weekdays[0];
            string minday = weekdays[0];

            foreach (var day in weekdays.Select((value, index) => new { value, index }))
            {
                if (p[day.index] > maxprice)
                {
                    maxday = day.value;
                    maxprice = p[day.index];
                }
                if (p[day.index] < minprice)
                {
                    minday = day.value;
                    minprice = p[day.index];
                }
            }
            // 最大値・最小値の表示
            Console.WriteLine("最大値:{0}に{1}円", maxday, maxprice);
            Console.WriteLine("最小値:{0}に{1}円", minday, minprice);
        }
    }
}

実行結果

まず 14行目で int[] p = new int[7]; と書いて配列変数を定義しています。
配列の宣言の書式は以下のようになります。

変数weekdaysで書いたように配列の定義と同時に値を入れることができます。
入力した数値を変数に代入した後に最初の値を仮の最大値・最小値に設定しました。

次に配列のデータから最大値、最小値を求めます。
配列の場合foreachループによる繰り返し処理も紹介したほうがよいと思い最大値、最小値の取得処理をforeach文で書きました。
foreach文の宣言の書式は以下のようになります。

for文では条件を設定しfalseになればループを終了していましたが、foreach文では配列の要素分だけ繰り返すと処理が終了します。

何曜日という情報も出力した方がよいと思いましたが、上記のforeach文の書式ではインデックス番号を取得できません。
そこでこちらの記事[1]にあるLINQのSelectメソッドを使いました。
foreach文のままでインデックス番号を取得できます。
またforeachループ内の変数valueにはstring型、変数indexにはinteger型の値が入るため変数dayにこれまで通り前にstringやintをつけるとCS1061[2]と呼ばれる書式エラーになります。
そのため参照型である var を変数dayの前につけると変数value、indexを扱えるようになりました。
なぜ参照型varを推奨しているのかがわかりました。

最後に最大値と最小値をコンソールに出力して終了します。

3/25以前に書いた記録

C#における配列変数の説明は後日振り返って勉強したときに書きます。
使える知識になるには反復して勉強する必要があります。
反復して勉強する際は書いた備忘録と使用教材内の例題を見て、修正が必要な箇所は適宜修正します。

最後に

体に危険なサインが出たときは夜に勉強しないようにしています。
危険なサインは例えば昼間にうとうと、心臓がこわばる、頭痛がたびたび起こるといった具合が悪くなる状態のことです。
毎日勉強することで学習して習慣にしたい、ただし休みが必要な時は休みます。

ありがとうございました。Thank You。

脚注
  1. https://www.sejuku.net/blog/41892 ↩︎

  2. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs1061?f1url=%3FappId%3Droslyn%26k%3Dk(CS1061) ↩︎

Discussion