23
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

std::cin「空白文字? いえ、知らない子ですね」

Posted at

プロローグ

ある日、う し た ぷ に き あ く ん 笑はう し た ぷ に き あ 王 国 笑の王様の命令でテキストファイルの内容をすべて読み込んて出力するコードを書きました。

u_shi_ta_pu_ni_ki_a_ku_n_lmao.txt
う  し  た  ぷ  に  き  あ  く  ん  笑
read_all.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>

int main() {
    std::ifstream ifs{ "u_shi_ta_pu_ni_ki_a_ku_n_lmao.txt" };
    std::string s(std::istream_iterator<char>{ ifs }, {});  // ファイルの内容を全部コピーしたつもり

    std::cout << s;
}

しかし、実行結果は次のようなものでした。

出力
うしたぷにきあくん笑

空白文字がなくなってしまっています。
このままでは王様が怒ってう し た ぷ に き あ く ん 笑はう し た ぷ に き あ 王 国 笑から追放されてしまうかもしれません。

std::cin >> c は空白を読み飛ばす

C++の書式化入力( >> を使った入力)では空白文字が読み飛ばされます。
std::istream_iterator では >> が使われるので、空白文字が読み込まれなかったというわけです。

scanf("%c", &c) では空白文字も読まれるので、う し た ぷ に き あ く ん 笑は勘違いしていたようです。

しかし、非書式化入力関数を使ったコードに書き換えるのは面倒です。
何か楽な方法はないでしょうか?

std::noskipws マニピュレータ

std::noskipws は書式化入力で空白文字を読み飛ばさないことを指示するマニピュレータです。

これを使えば、修正は最小限で済みます。
早速さっきのコードを書き換えます。

read_all.cpp
  #include <iostream>
  #include <fstream>
  #include <string>
  #include <iterator>
  
  int main() {
      std::ifstream ifs{ "u_shi_ta_pu_ni_ki_a_ku_n_lmao.txt" };
+     ifs >> std::noskipws;
      std::string s(std::istream_iterator<char>{ ifs }, {});
  
      std::cout << s;
  }

実行してみると次のようになりました。

出力
う  し  た  ぷ  に  き  あ  く  ん  笑

しっかり空白も含めて出力されています。
これなら、う し た ぷ に き あ く ん 笑は王様に怒られずに済むでしょう。

エピローグ

全角スペースの代わりに半角スペース2個を使っていたので、う し た ぷ に き あ く ん 笑は追放されました。

23
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?