C#でキーボードから文字列を入力させる方法|Console.ReadLineの使い方とサンプルコード

コンソールアプリケーションでユーザーから文字列を入力させる基本は、Console.ReadLineを正しく理解し、適切にバリデーションや変換を行うことです。

本記事では、Console.ReadLineの戻り値やブロッキングの挙動から、空行の扱い、数値・日付変換、複数行入力の終了条件まで、実用的なサンプルコードとともに詳しく解説します。

Console.ReadLineとは?

Console.ReadLineは、標準入力から1行の文字列を読み取るための最も基本的なAPIです。

ユーザーがEnterキーを押すまで入力を待ち、行末の改行は返す文字列に含まれません。

Console.ReadLineの概要と戻り値(string?)

  • 戻り値の型はstring?です。これは、文字列が返る場合とnullが返る場合があることを意味します。
  • 標準入力が終端(EOF)に達した場合や入力がリダイレクトされていて末尾に達した場合、nullが返ります。
  • 通常の対話入力では、ユーザーがEnterを押すと、改行を除いた文字列が返ります。

典型的にnullになるケース

  • Windows: コンソールでCtrl+Zの後にEnterを押す
  • macOS/Linux: Ctrl+Dを押す
  • 入力をファイルやパイプから受け取り、その終端に達した場合

改行までの読み取りとブロッキングの挙動

Console.ReadLineはブロッキング呼び出しです。

ユーザーが改行(Enter)を送るまで、呼び出し元スレッドは待機します。

これにより、以下のような挙動になります。

  • 同期的に1行単位で入力を受け取る
  • キャンセルしない限り(例:Console.CancelKeyPressで制御)処理は進まない
  • 改行は返される文字列に含まれないため、そのまま画面に出力しても余分な改行が入らない

基本の使い方とサンプルコード

Console.ReadLineの基本は、ユーザーにプロンプトを表示し、入力された文字列をそのまま使う、あるいは最低限のチェックをすることです。

プロンプトを表示して1行の文字列を取得する

C#HelloInput.cs
// 目的: ユーザーから名前を1行で受け取り、挨拶を表示する基本例

using System;

class Program
{
    static void Main()
    {
        Console.Write("あなたの名前を入力してください: "); // 改行なしでプロンプト表示
        string? name = Console.ReadLine();                 // 1行読み取り(nullの可能性あり)

        if (name is null)
        {
            Console.WriteLine("入力が終了(EOF)しました。プログラムを終了します。");
            return;
        }

        Console.WriteLine($"こんにちは、{name}さん!");
    }
}
実行結果
あなたの名前を入力してください: 山田太郎
こんにちは、山田太郎さん!

空行を許可しない基本バリデーションと再入力

入力を必須にしたい場合は、ループで空行を弾きます。

EOFは別扱いにして早期終了すると丁寧です。

C#NonEmptyInput.cs
// 目的: 空行を許可せず、必ず非空の文字列を取得する

using System;

class Program
{
    static void Main()
    {
        while (true)
        {
            Console.Write("メールアドレスを入力してください(必須): ");
            string? input = Console.ReadLine();

            if (input is null)
            {
                Console.WriteLine("入力が終了(EOF)しました。処理を中断します。");
                return; // または break; で後続処理へ
            }

            if (input.Length == 0)
            {
                Console.WriteLine("空行は無効です。もう一度入力してください。");
                continue;
            }

            Console.WriteLine($"入力を受け付けました: {input}");
            break;
        }
    }
}
実行結果
メールアドレスを入力してください(必須):
空行は無効です。もう一度入力してください。
メールアドレスを入力してください(必須): user@example.com
入力を受け付けました: user@example.com

文字列の前処理とエラーハンドリング

ユーザー入力は余分な空白や制御文字を含むことがあります。

最初に整形し、想定外の状況(EOFやI/Oエラー)を安全に扱います。

Trimで前後の空白を除去する

Trimは先頭・末尾の空白やタブ、改行などを取り除きます。

空白のみの入力を禁止したい場合はstring.IsNullOrWhiteSpaceが便利です。

C#TrimAndValidate.cs
// 目的: 前後空白の除去と空白のみの入力を拒否する

using System;

class Program
{
    static void Main()
    {
        Console.Write("ユーザーIDを入力してください(空白のみ不可): ");
        string? raw = Console.ReadLine();

        if (raw is null)
        {
            Console.WriteLine("EOFを検知しました。終了します。");
            return;
        }

        string trimmed = raw.Trim(); // 前後の空白・タブ・改行を除去

        if (string.IsNullOrWhiteSpace(trimmed))
        {
            Console.WriteLine("空白のみの入力は無効です。");
            return;
        }

        Console.WriteLine($"受理したID: [{trimmed}]");
    }
}
実行結果
ユーザーIDを入力してください(空白のみ不可):    alice
受理したID: [alice]

null/EOFの検知と安全な処理

EOFが来たらnullが返ります。

パイプやファイル入力では起こりやすいため、毎回の読み取りでnullチェックを行うのが安全です。

まれにコンソールの入出力に対するIOExceptionが発生する可能性もあるため、必要に応じてtry-catchでガードします。

C#SafeReadLine.cs
// 目的: EOFとI/O例外を考慮した安全な読み取り

using System;
using System.IO;

class Program
{
    static void Main()
    {
        try
        {
            Console.Write("コマンドを入力してください(EOFで終了): ");
            string? line = Console.ReadLine();

            if (line is null)
            {
                Console.WriteLine("EOFを検知しました。プログラムを終了します。");
                return;
            }

            Console.WriteLine($"受信: {line}");
        }
        catch (IOException ex)
        {
            Console.Error.WriteLine($"コンソールI/Oエラー: {ex.Message}");
        }
    }
}
実行結果
コマンドを入力してください(EOFで終了): help
受信: help

数値・日付への変換と検証

文字列入力をアプリで使いやすい型(数値や日付)に変換する場合、TryParse系メソッドが有効です。

例外を使わずに成否を判定できます。

int.TryParseで数値入力を受け付けるサンプル

数値のみを受け付け、範囲チェックも行う例です。

C#ReadIntWithValidation.cs
// 目的: int値を入力させ、範囲(1~120)を検証する

using System;

class Program
{
    static void Main()
    {
        while (true)
        {
            Console.Write("年齢を入力してください(1~120): ");
            string? s = Console.ReadLine();

            if (s is null)
            {
                Console.WriteLine("EOFを検知しました。入力を中断します。");
                return;
            }

            if (int.TryParse(s.Trim(), out int age) && age >= 1 && age <= 120)
            {
                Console.WriteLine($"登録しました。年齢: {age}");
                break;
            }

            Console.WriteLine("無効な入力です。整数で1~120の範囲で入力してください。");
        }
    }
}
実行結果
年齢を入力してください(1~120): 0
無効な入力です。整数で1~120の範囲で入力してください。
年齢を入力してください(1~120): 25
登録しました。年齢: 25

DateTime.TryParseで日付を読み取るサンプル

ロケールの影響を受けやすい日付入力は、CultureInfoを指定するか、フォーマットを固定するのが安全です。

C#ReadDate.cs
// 目的: 日付の入力を "yyyy/MM/dd" 形式で受け取り、検証する

using System;
using System.Globalization;

class Program
{
    static void Main()
    {
        var culture = CultureInfo.GetCultureInfo("ja-JP");
        const string format = "yyyy/MM/dd";

        while (true)
        {
            Console.Write($"誕生日を {format} 形式で入力してください: ");
            string? s = Console.ReadLine();

            if (s is null)
            {
                Console.WriteLine("EOFを検知しました。入力を中断します。");
                return;
            }

            // 厳密にフォーマットを固定したい場合は TryParseExact を使用
            if (DateTime.TryParseExact(s.Trim(), format, culture, DateTimeStyles.None, out DateTime date))
            {
                Console.WriteLine($"受理した日付: {date:yyyy年M月d日}");
                break;
            }

            Console.WriteLine($"無効な日付です。例: 1990/12/31 のように {format} で入力してください。");
        }
    }
}
実行結果
誕生日を yyyy/MM/dd 形式で入力してください: 1990-12-31
無効な日付です。例: 1990/12/31 のように yyyy/MM/dd で入力してください。
誕生日を yyyy/MM/dd 形式で入力してください: 1990/12/31
受理した日付: 1990年12月31日

補足として、柔軟な入力を許したい場合はDateTime.TryParseに文化情報を渡す方法もありますが、ユーザーに一貫した入力形式を求めたい場合はTryParseExactが適しています。

応用:複数行入力・終了条件の作り方

複数行の入力を集めたいとき、終了条件を明確に設けるとユーザーが迷いません。

典型的には「空行で終了」や「特定キーワードで終了」を使います。

空行で終了するループ入力

空行が入力されたタイミングで終了し、それまでの行をまとめます。

EOFも終了条件に含めます。

C#MultilineUntilEmpty.cs
// 目的: 複数行のメモを受け取り、空行またはEOFで確定する

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var lines = new List<string>();
        Console.WriteLine("メモを入力してください。空行で終了します。");

        while (true)
        {
            string? line = Console.ReadLine();

            if (line is null)
            {
                Console.WriteLine("EOFを検知しました。入力を終了します。");
                break;
            }

            if (line.Length == 0) // 空行
            {
                break;
            }

            lines.Add(line);
        }

        Console.WriteLine("--- 入力結果 ---");
        foreach (var l in lines)
        {
            Console.WriteLine(l);
        }
    }
}
実行結果
メモを入力してください。空行で終了します。
一行目
二行目
三行目

--- 入力結果 ---
一行目
二行目
三行目

特定のキーワード(exit/quit)で終了する実装

ユーザーに明示的に終了コマンドを打ってもらう方式です。

大文字小文字を区別しない比較にしておくと親切です。

C#CommandLoop.cs
// 目的: exit/quit で終了する簡易コマンドループ

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("コマンドを入力してください。exit または quit で終了します。");

        while (true)
        {
            Console.Write("> "); // プロンプト
            string? input = Console.ReadLine();

            if (input is null)
            {
                Console.WriteLine("EOFを検知しました。終了します。");
                break;
            }

            string command = input.Trim();

            if (command.Equals("exit", StringComparison.OrdinalIgnoreCase) ||
                command.Equals("quit", StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine("終了コマンドを受け付けました。さようなら。");
                break;
            }

            // ここでコマンドを処理する
            Console.WriteLine($"コマンド[{command}]を処理しました。");
        }
    }
}
実行結果
コマンドを入力してください。exit または quit で終了します。
> help
コマンド[help]を処理しました。
> Quit
終了コマンドを受け付けました。さようなら。

まとめ

Console.ReadLineはシンプルですが、EOFや空行、文化依存の解析といった現実的なケースに丁寧に対処することで、堅牢で使いやすいコンソール入力体験を実現できます。

必要に応じてTrimTryParseで前処理と検証を行い、終了条件を明確にすることがポイントです。

Console.ReadKeyとの違いと使い分け

Console.ReadLineは1行単位で文字列を取得し、Enterまでブロッキングします。フォームやコマンド入力、複数トークンの取得に向いています。

Console.ReadKeyはキー1打鍵を即座に取得します。メニューの単一キー操作(例: y/n確認)やキーイベントの検出に適します。行編集機能(バックスペースで編集する等)は自前で実装する必要があります。

使い分けの目安は「行として意味を成す入力」ならReadLine、「単発のキー操作・ショートカット」ならReadKeyです。

エンコーディング(UTF-8)と日本語入力の注意

近年の.NET(.NET 5以降)では、WindowsでもUTF-8が既定になっている環境が増えましたが、環境によってはコンソールのコードページが異なる場合があります。

日本語が文字化けする場合は、入出力エンコーディングを明示します。

C#C#側での明示例
// 目的: コンソールの入力・出力エンコーディングをUTF-8に設定

using System;
using System.Text;

class Program
{
    static void Main()
    {
        Console.InputEncoding = Encoding.UTF8;
        Console.OutputEncoding = Encoding.UTF8;

        Console.Write("日本語を入力してください: ");
        string? s = Console.ReadLine();
        Console.WriteLine($"受信: {s}");
    }
}
実行結果
日本語を入力してください: こんにちは
受信: こんにちは

Windowsの古いコンソールでは、UTF-8を使うために事前にchcp 65001(コードページの変更)やWindows Terminalの使用が必要なことがあります。

入力がファイルやパイプから供給される場合は、そのソース側のエンコーディングとも整合させてください(例: UTF-8のテキストファイルをリダイレクトする)。

これらのポイントを押さえれば、Console.ReadLineを使ったC#のコンソール入力は、対話的で信頼性の高いものになります。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!