はじめに
C++の cin
や ifstream
といった入力ストリームは、>>
演算子を使うと、デフォルトで入力中の空白文字(スペース、タブ、改行など)を自動的に読み飛ばしてくれます。これにより、「10 20
」という入力を2つの整数として簡単に読み込めます。
しかし、時にはこの「空白の読み飛ばし」を無効にしたい場合や、逆に不要な空白だけを意図的に読み飛ばしたい場合もあります。
この記事では、入力ストリームにおける空白文字の扱いを制御するための2つの重要なマニピュレータを解説します。
std::noskipws
: 空白の自動読み飛ばしを無効にする。std::ws
: 先頭の連続する空白文字を全て読み飛ばす。
1. >>
演算子のデフォルト動作(空白をスキップ)
>>
演算子は、読み込みを開始する前に、まず先頭にある全ての空白文字を読み飛ばします。そして、空白以外の文字が現れてから、次の空白文字が現れるまでを一つのデータとして読み取ります。
2. std::noskipws
: 空白の読み飛ばしを無効にする
ストリームに std::noskipws
を渡すと、それ以降、そのストリームは空白文字も通常の文字として読み込むようになります。
サンプルコード
#include <iostream>
#include <string>
#include <sstream> // istringstream
using namespace std;
int main() {
string data = " A B C";
// --- デフォルトの動作 (skipws) ---
istringstream iss1(data);
char ch1, ch2;
iss1 >> ch1 >> ch2; // 先頭のスペースは無視され、'A'と'B'が読み込まれる
cout << "デフォルト (skipws): '" << ch1 << "' and '" << ch2 << "'" << endl;
// --- noskipws を使った場合 ---
istringstream iss2(data);
char ch3, ch4;
iss2 >> noskipws >> ch3 >> ch4; // 空白も文字として読み込まれる
cout << "noskipws の場合: '" << ch3 << "' and '" << ch4 << "'" << endl;
return 0;
}
実行結果
デフォルト (skipws): 'A' and 'B'
noskipws の場合: ' ' and ' '
解説: noskipws
を指定した iss2
では、先頭の2つのスペースが文字として ch3
と ch4
に読み込まれています。
3. std::ws
: 不要な空白を能動的に読み飛ばす
>>
で数値を読み取った後、getline
で次の行を読み取ろうとすると、数値の後に残った改行文字を getline
が読み込んでしまい、空の文字列が読み取られる、という問題が頻繁に発生します。
std::ws
マニピュレータは、このような入力バッファに残った不要な空白文字を、次の本格的な読み込みの前に一掃するために使います。
サンプルコード
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
stringstream test_input("42\nThis is a line.");
int number;
string line;
test_input >> number; // 42が読み込まれる。改行'\n'はストリームに残る
// ここで ws を使わないと、getlineは残った'\n'だけを読んでしまう
test_input >> ws;
getline(test_input, line); // wsのおかげで、'\n'が除去され、"This is a line."が正しく読み込める
cout << "数値: " << number << endl;
cout << "文字列: " << line << endl;
return 0;
}
まとめ
今回は、C++の入力ストリームにおける空白文字の扱いについて解説しました。
>>
演算子は、デフォルトで空白を読み飛ばす (skipws
)。std::noskipws
を使うと、空白も一文字として読み込むようになる。std::ws
を使うと、次の読み込みの前に、先頭の不要な空白を一掃できる。
特に、>>
演算子と getline
を混在させる際の std::ws
の使い方は、確実な入力処理を行うための必須のテクニックです。