【C++】cinの使い方について詳しく解説

C++プログラミングにおいて、入力を受け取るcinは非常に重要な役割を担っています。

しかし、初心者にとってはcinの使い方がわかりづらく、エラーが発生してしまうこともあります。

そこで本記事では、cinの基本的な使い方から応用的な使い方まで詳しく解説します。

目次

cinとは何か

C++において、cinは標準入力ストリームを表します。つまり、ユーザーからのキーボード入力をプログラムで受け取るために使用されます。

cinは、iostreamライブラリに含まれています。以下のように、cinを使用する前にプログラムの先頭でiostreamヘッダーファイルをインクルードする必要があります。

#include <iostream>

cinは、次のような形式で使用されます。

std::cin >> 変数名

ここで、変数名はキーボードから入力された値を格納する変数です。例えば、整数型の変数numにキーボードから入力された値を格納する場合は以下のようになります。

int num;
std::cin >> num;

このコードでは、ユーザーがキーボードから入力した値がnum変数に格納されます。

cinの基本的な使い方

C++において、標準入力から値を受け取るためには、cinという標準入力ストリームを使用します。ここでは、cinの基本的な使い方について説明します。

変数への入力

まずは、変数への単一の値の入力方法です。以下は、整数型変数numに対して標準入力から値を受け取り、その値を出力するプログラム例です。

#include <iostream>

int main() {
    int num;
    std::cout << "整数を入力してください: ";
    std::cin >> num;
    std::cout << "入力された値は" << num << "です。\n";
    return 0;
}

上記プログラムでは、まず整数型変数numを宣言し、その後に「整数を入力してください: 」というメッセージを表示します。そして、std::cin >> num;で標準入力から値を受け取ります。

最後に、「入力された値は〇〇です。」というメッセージと共に、受け取った値を出力します。

C言語で使ってきたscanf関数と違い、入力した値を格納する変数のアドレスではなく、変数をそのまま渡さないといけないので気をつけてください(&numとは書かない)

複数の変数への入力

次に複数の変数への入力方法です。以下は、整数型変数a, b, cに対して標準入力からそれぞれ値を受け取り、その和を出力するプログラム例です。

#include <iostream>

int main() {
    int a, b, c;
    std::cout << "3つの整数を空白区切りで入力してください: ";
    std::cin >> a >> b >> c;
    int sum = a + b + c;
    std::cout << "3つの整数の和は" << sum << "です。\n";
    return 0;
}

上記プログラムでは、まず整数型変数a, b, cを宣言し、「3つの整数を空白区切りで入力してください: 」というメッセージを表示します。

そして、std::cin >> a >> b >> c;で標準入力からそれぞれ値を受け取ります。最後に、「3つの整数の和は〇〇です。」というメッセージと共に、それらの和を出力します。

改行を無視する方法

デフォルトでは、改行文字も含めて全てが読み込まれますが、「改行文字以外」だけ読み込む方法もあります。以下はその例です。

#include <iostream>
#include <limits>

int main() {
    int num1, num2;

    // 最初に改行文字列が残ってしまうためクリアする
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    // 数字以外が入力されるまで繰り返す
    while (true) {
        std::cout << "2つの数字(スペース区切り):";
        if (std::cin >> num1 >> num2) break;

        // 入出エラーが起きた場合(数字以外が来た場合)
        std::cerr << "不正な文字列が含まれています\n";

        // エラー内容クリア
        std::cin.clear();

        // 残ったバッファクリア(改行文字列等)
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
   }

   // 入出エラー処理終了後、num1,num2 を使って何か処理する...
   return 0;
}

上記プログラムでは、2つの数字(スペース区切り):と表示した後、ユーザーから2つの数字以外が含まれる文字列が来る限り繰り返し要求します。

この時、数字以外が来た場合、エラーメッセージ不正な文字列が含まれていますと表示されます。

また、繰り返しcinで入力を行う場合、エラー内容クリアや残ったバッファクリアも必要な場合があることに注意してください。

入力エラー処理

最後に、ユーザーから予期しない形式や範囲外など不正なデータが送信された場合でも安全かつ適切な動作するよう対策する方法です。 以下はその例です。

#include <iostream>
#include <limits>

int main() {
   int age;

   while (true) {
       std::cout << "年齢:";

       //ageへの格納成功(数字が入力された)かつ0以上120以下でなければやり直し
       if (std::cin >> age && age >= 0 && age <= 120) break;

       // 入出エラー処理(数字以外や範囲外)
       if (std::cin.fail()) {
           std::cerr << "不正な文字列が含まれています\n";
           // エラー内容クリア
           std::cin.clear();
       } else {
           std::cerr << "範囲外または負荷年齢\n";
       }

       // 残ったバッファクリア(改行文字列等)
       std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
   }

   // 入出エラー処理終了後、age を使って何か処理する...
   return 0;
}

上記プログラムでは、「年齢:」と表示した後、ユーザーから正しい数字(0以上120以下)が入力されるまで、入力を要求します。

この時、不正なデータ送信時は適切なエラーメッセージ「不正な文字列/範囲外または負荷年齢」と表示されます。 また、エラー内容クリアや残ったバッファクリアも必要な場合があることに注意してください。

cinの高度な使い方

cinは、基本的な入力方法だけでなく、より高度な入力方法も提供しています。以下では、cinの高度な使い方について説明します。

入力ストリームの操作

cinは、入力ストリームを扱うことができます。

入力ストリームとは、キーボードやファイルからデータを読み込むための仕組みです。cinを使用する場合、標準入力ストリーム(キーボードからの入力)が自動的に選択されます。

しかし、プログラム内で複数の入力ストリームを扱う必要がある場合もあります。その場合は、ifstreamクラスを使用して別の入力ストリームを指定することができます。

#include <fstream>
#include <iostream>

int main() {
    std::ifstream input_file("input.txt");
    int num;
    input_file >> num;
    std::cout << "num: " << num << std::endl;
}

上記の例では、input.txtファイルから数字を読み取っています。std::ifstreamクラスは、主にファイルから読み取るために使用されます。

入力ストリームの状態の確認

cinは、現在の状態を確認するためにいくつかの関数を提供しています。これらの関数は主にエラー処理に使用されます。

  • fail():前回実行した操作が失敗したかどうかを返します。
  • bad():I/Oエラーが発生したかどうかを返します。
  • eof():EOF(End Of File)に到達したかどうかを返します。
  • good():前回実行した操作が成功したかどうかを返します。

これらの関数はbool型で値を返すため、if文やwhile文と組み合わせて使用することができます。

#include <iostream>

int main() {
    int num;
    while (true) {
        std::cout << "Enter a number: ";
        std::cin >> num;

        //数字が入力されなかったらtrue
        if (std::cin.fail()) {
            std::cout << "無効な入力です。数値を入力してください。" << std::endl;
            std::cin.clear();
            std::cin.ignore(10000, '\n');
        } else {
            break;
        }
    }

    std::cout << "You entered: " << num << std::endl;
}

上記の例では、ユーザーから数字を受け取りますが、絶対に数字が入力されるとは限りません。

そこで、std::cin.fail()を使って正しく数値が入力されるか判定し、入力されてたらbreak;でループを抜け、数値じゃなかった場合は、数値が入力されるまでに入力処理を繰り返しています。

入力ストリームのクリア

先程サンプルコードで登場していますが、clear()関数はエラー処理時に役立ちます。この関数はエラーステータスフラグ(failbit, badbit, eofbit)およびエラーステータスフラグ以外(goodbit)すべてクリアします。

#include <iostream>

int main() {
    int num1, num2;

    while (true) {
        std::cout << "Enter the first number: ";
        std::cin >> num1;

        if (std::cin.fail()) {
            std::cout << "無効な入力です。数値を入力してください。" << std::endl;
            std::cin.clear(); //エラーステータスのクリア
            std::cin.ignore(10000, '\n');
        } else {
            break;
        }
    }

    cout << num1 << endl; 

   return 0; 
}

以上が、C++のcin使い方の例です。

cinの注意点

C++の標準入力ストリームであるcinには、いくつか注意すべき点があります。

入力のバッファリング

cinを使ってキーボードから入力を受け取る場合、実際にEnterキーを押すまで入力された文字列はバッファに蓄積されます。

そのため、Enterキーを押す前にプログラムがエラーで中断されてしまうと、バッファに残った文字列が次回の入力時に読み込まれてしまうことがあります。

この問題を解決する方法としては、以下の2つが挙げられます。

  • バッファをクリアする
  • getline関数を使う

バッファをクリアする

バッファをクリアする方法は、以下のようなコードで実現できます。

#include <iostream>
using namespace std;

int main() {
    string str;
    cin >> str;
    cin.ignore(1000, '\n'); // 1000文字分のバッファを無視する
    return 0;
}

上記の例では、cin.ignore()関数を使って1000文字分のバッファを無視しています。これにより、次回以降の入力時に余計な文字列が読み込まれることがなくなります。

入力の区切り文字

cinではスペースやタブなど空白類似文字(whitespace characters)が区切り文字として扱われます。そのため、以下のようなコードでは、4つ以上の値を入力しても、3つ目以降の変数に値が代入されず、バッファに残り続けます。

#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c; // "1 2 3" を入力した場合
    cout << a << ", " << b << ", " << c << endl; // 出力: "1, 2, 3"
    return 0;
}

cin.ignore()関数を使ってバッファをクリアしてから次のcinを実行しないと、残ったバッファを入力として処理されてしまうので注意しましょう。

目次