口頭の指示からプログラムを組み立てる力

― C#で5人の生徒情報を並び替えて表示する課題を通して ―


はじめに

現場や授業では、「仕様書」や「設計書」ではなく、講師や上司からの口頭指示で課題を受けることがあります。

このような状況では、聞き取った内容を自分で仕様に落とし込む力が求められます。

今回は、ある授業中に出された「生徒情報を並び替えて表示する」という課題の口頭指示を受け、それを元にC#のプログラムを構築する過程をまとめました。


🎙️ 実際の口頭指示(想定会話)

講師:

えーと、次の課題なんですけど…

5人の生徒がいる教室をイメージしてください。

まず、生徒の一覧表を作ってみてください。

生徒の情報は「名前・身長・住所」でお願いします。

(少し考えて)

あ、ごめんなさい。住所と身長の順番を入れ替えてください。

表示する時には「名前、住所、身長」の順で出力してください。

(さらに追加)

次に、その一覧を身長順(昇順)に並べて表示してみましょう。

あと、住所順(五十音順)でも並び替えて表示できると良いですね。

(最後に)

すいません、情報の一番目に生徒IDをつけてください。

IDは1から順番で構いません。

(言い忘れました・・・)

あ、プロジェクト名は、StudentRosterSorterにしましょう


🧠 指示から仕様を読み取る

要素内容
生徒数5人
保持情報ID(番号)・名前・住所・身長
表示①入力順に表示(表示順:ID, 名前, 住所, 身長)
表示②身長順(昇順)で表示
表示③住所順(五十音順)で表示

🏗️ Studentクラスを定義する

class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; } // 表示では身長より先
    public int Height { get; set; }
}

✅ 身長と住所の定義順は内部構造では自由だが、表示順は指示に従う必要があるという理解が大切。


🧪 ダミーデータの作成

以下のように、生徒5人分の情報を用意します。

var students = new List<Student>
{
    new Student { Id = 1, Name = "佐藤", Address = "東京", Height = 160 },
    new Student { Id = 2, Name = "鈴木", Address = "神奈川", Height = 170 },
    new Student { Id = 3, Name = "高橋", Address = "千葉", Height = 165 },
    new Student { Id = 4, Name = "田中", Address = "埼玉", Height = 172 },
    new Student { Id = 5, Name = "伊藤", Address = "茨城", Height = 158 },
};

🔁 並び替え処理の実装(LINQ)

身長順(昇順)でソート:

var heightSorted = students.OrderBy(s => s.Height).ToList();

住所順(五十音順)でソート:

var addressSorted = students.OrderBy(s => s.Address).ToList();

🖨️ 出力用の関数(メソッド)を定義

結果の表示は、メソッドにまとめてみましょう

static void DisplayStudents(List<Student> list)
{
    foreach (var s in list)
    {
        Console.WriteLine($"ID: {s.Id}, 名前: {s.Name}, 住所: {s.Address}, 身長: {s.Height}cm");
    }
}

🔄 表示時には、住所→身長の順で出力されていることに注目。


💻 完成プログラム全体

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

namespace StudentRosterSorter
{
    class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public int Height { get; set; }
    }

    class Program
    {
        static void Main()
        {
            var students = new List<Student>
        {
            new Student { Id = 1, Name = "佐藤", Address = "東京", Height = 160 },
            new Student { Id = 2, Name = "鈴木", Address = "神奈川", Height = 170 },
            new Student { Id = 3, Name = "高橋", Address = "千葉", Height = 165 },
            new Student { Id = 4, Name = "田中", Address = "埼玉", Height = 172 },
            new Student { Id = 5, Name = "伊藤", Address = "茨城", Height = 158 },
        };

            Console.WriteLine("【入力順】");
            DisplayStudents(students);

            Console.WriteLine("\n【身長順(昇順)】");
            var heightSorted = students.OrderBy(s => s.Height).ToList();
            DisplayStudents(heightSorted);

            Console.WriteLine("\n【住所順(五十音順)】");
            var addressSorted = students.OrderBy(s => s.Address).ToList();
            DisplayStudents(addressSorted);
        }

        static void DisplayStudents(List<Student> list)
        {
            foreach (var s in list)
            {
                Console.WriteLine($"ID: {s.Id}, 名前: {s.Name}, 住所: {s.Address}, 身長: {s.Height}cm");
            }
        }
    }
}

📝 まとめ

  • 口頭で与えられた曖昧な指示を正しく解釈し、仕様に落とし込むことが重要。
  • クラス設計、Listの扱い、LINQによる並び替え、整形出力の基本が学べる良課題。
  • 特に「表示順と内部の定義順が違っていてもよい」ことは、実務でも頻出の考え方。

🧩 発展課題(応用として)

  • 一番背の高い生徒だけを表示する
  • 「茨城」に住んでいる生徒を抽出する
  • 名前の五十音順に並び替える
  • 身長が160cm以上の生徒だけを表示する

以下のサンプルでは、元の課題で定義されている Student クラスと students リストをそのまま使い回し、LINQ を使って各発展課題を実装しています。


1. 一番背の高い生徒だけを表示する

var tallest = students.OrderByDescending(s => s.Height).First();  // 最初が最大値

Console.WriteLine($"一番背の高い生徒: {tallest.Name}({tallest.Height}cm)");

2. 「茨城」に住んでいる生徒を抽出する

var ibarakiStudents = students .Where(s => s.Address == "茨城");

foreach (var s in ibarakiStudents)
{
    Console.WriteLine($"{s.Name}({s.Height}cm, 住所: {s.Address})");
}

3. 名前の五十音順に並び替える

既定の OrderBy(s => s.Name) だけだと、.NET(Windows)の日本語カルチャではJIS X 0208 のコード順(Shift_JIS のバイト順)で比較が行われるため、あいうえお順にはなりません。

実際、Shift_JIS の先頭バイト順で見ると…

伊(0x88C9)→ 高(0x8D82)→ 佐(0x8DB2)→ 田(0x9363)→ 鈴(0x97E9)

…という並びになり、先ほどの結果(伊藤→高橋→佐藤…)と一致します。


あいうえお順で並べるには

名称(漢字)ではなく、読み仮名(ふりがな)でソートするのがもっとも確実です。

以下の例では、Student クラスに Reading プロパティを追加し、そこに全員の読み仮名を入れてから LINQ でソートします。

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Reading { get; set; }  // 五十音順ソート用の読み仮名
    public int Height { get; set; }
    public string Address { get; set; }
}

// Mainメソッド
var students = new List<Student>
{
    new Student { Id = 1, Name = "佐藤", Reading = "さとう", Address = "東京", Height = 160 },
    new Student { Id = 2, Name = "鈴木", Reading = "すずき", Address = "神奈川", Height = 170 },
    new Student { Id = 3, Name = "高橋", Reading = "たかはし", Address = "千葉", Height = 165 },
    new Student { Id = 4, Name = "田中", Reading = "たなか", Address = "埼玉", Height = 172 },
    new Student { Id = 5, Name = "伊藤", Reading = "いとう", Address = "茨城", Height = 158 }
}

var sortedByReading = students.OrderBy(s => s.Reading);

Console.WriteLine("名前の五十音順:");
foreach (var s in sortedByReading)
    Console.WriteLine($"- {s.Name}(ID: {s.Id})");

このようにすれば、出力は

伊藤五郎(ID: 5)
佐藤花子(ID: 2)
鈴木次郎(ID: 3)
高橋四郎(ID: 4)
田中太郎(ID: 1)

と、純粋に「あ→さ→す→た→た」の順(※たかはし→たなか の順序も正しく)になります。


なぜ漢字のままだとダメなのか

  • Windows の標準日本語ロケール(ja-JP)では、内部的に JIS X 0208 の行番号・セル番号順(Shift_JIS のバイト列順)でソートします。
  • これが「字典式」や「画数順」とは違い、厳密な五十音(あいうえお)順ではありません。

なぜふりがなだといいのか

ふりがな(Reading)の文字列は純粋なひらがなで構成されていて、ひらがなの Unicode コードポイント自体が五十音順(「あ」→「い」→「う」→「え」→「お」…)に並んでいます。

  • ひらがな Unicode コードポイント順
    • 「あ」…U+3042
    • 「い」…U+3044
    • 「う」…U+3046
    • 「え」…U+3048
    • 「お」…U+304A

…というふうに、Unicode 上の並びがそのまま五十音の並びになっているためです

まとめ

  • 漢字でソート → JIS コード順になる
  • 読み仮名でソート → 実際のあいうえお順になる

そのため、名前のあいうえお順を保証したい場合は、必ず「ふりがな(Reading)」をデータとして持たせてソートしてください。


4. 身長が160cm以上の生徒だけを表示する

var tallStudents = students.Where(s => s.Height >= 160);

foreach (var s in tallStudents)
{
    Console.WriteLine($"{s.Name}({s.Height}cm)");
}

これらのサンプルを元に、実データや表示形式を調整して発展課題に取り組んでみてください。

課題を含めた全てのコード

using System;
using System.Collections.Generic;
using System.Linq;

namespace StudentRosterSorter
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Reading { get; set; }  // 五十音順ソート用の読み仮名
        public int Height { get; set; }
        public string Address { get; set; }
    }


    class Program
    {
        static void Main()
        {
            var students = new List<Student>
            {
                new Student { Id = 1, Name = "佐藤", Reading = "さとう", Address = "東京", Height = 160 },
                new Student { Id = 2, Name = "鈴木", Reading = "すずき", Address = "神奈川", Height = 170 },
                new Student { Id = 3, Name = "高橋", Reading = "たかはし", Address = "千葉", Height = 165 },
                new Student { Id = 4, Name = "田中", Reading = "たなか", Address = "埼玉", Height = 172 },
                new Student { Id = 5, Name = "伊藤", Reading = "いとう", Address = "茨城", Height = 158 }
            };

            Console.WriteLine("【入力順】");
            DisplayStudents(students);

            Console.WriteLine("\n【身長順(昇順)】");
            var heightSorted = students.OrderBy(s => s.Height).ToList();
            DisplayStudents(heightSorted);

            Console.WriteLine("\n【住所順(五十音順)】");
            var addressSorted = students.OrderBy(s => s.Address).ToList();
            DisplayStudents(addressSorted);

            var tallest = students.OrderByDescending(s => s.Height).First();  // 最初が最大値
            Console.WriteLine($"一番背の高い生徒: {tallest.Name}({tallest.Height}cm)");

            var sortedByReading = students.OrderBy(s => s.Reading);

            Console.WriteLine("名前の五十音順:");
            foreach (var s in sortedByReading)
                Console.WriteLine($"- {s.Name}(ID: {s.Id})");

            var tallStudents = students.Where(s => s.Height >= 160);

            foreach (var s in tallStudents)
            {
                Console.WriteLine($"{s.Name}({s.Height}cm)");
            }
        }

        static void DisplayStudents(List<Student> list)
        {
            foreach (var s in list)
            {
                Console.WriteLine($"ID: {s.Id}, 名前: {s.Name}, 住所: {s.Address}, 身長: {s.Height}cm");
            }
        }
    }
}

🎤 おわりに

この課題は、「聞いてすぐ作る力」「曖昧さを整理する力」「順序や整形に気を配る力」など、プログラミングに必要な本質的な力を育ててくれます。

特に初心者にとっては、「言われたことをそのまま写す」のではなく、「言われた内容の意図を読み取る」という姿勢が重要であることを体感できる機会です。


訪問数 37 回, 今日の訪問数 38回