ストリームの入出力について知っておくべきこと

本日の投稿は、Iostream について知っておくべきことについてです。特に、フォーマット済みおよび未フォーマットの入出力について書いています。

入力関数と出力関数

C++ には、キーボードとモニターの扱いに便利な 4 つの定義済みストリーム オブジェクトがあります。

ストリーム オブジェクトを使用して、コマンド ラインから読み取り、合計を返すプログラムを作成できます。

// Iostreams.cpp

#include <iostream>

int main(){

 std::cout << std::endl;
 
 std::cout << "Type in your numbers(Quit with an arbitrary character): " << std::endl;
 
 int sum{0};
 int val;

 while ( std::cin >> val ) sum += val;

 std::cout << "Sum: " << sum << std::endl;
 
 std::cout << std::endl;

}

このプログラムは、ストリーム演算子 <<と>> およびストリーム マニピュレータ std::endl を使用します。

  • 挿入演算子 <<は、文字を出力ストリーム std::cout にプッシュします。
  • 抽出演算子>> は、入力ストリーム std::cin から文字を取り出します。
  • どちらの演算子も自分自身への参照を返すため、挿入演算子または抽出演算子のチェーンを構築できます。

std::endl は、'\n' 文字を std::cout に置き、出力バッファーをフラッシュするため、ストリーム マニピュレーターです。

以下は、最も頻繁に使用されるストリーム マニピュレータです。

入力

入力ストリームから 2 つの方法で読み取ることができます:エクストラクター>> でフォーマットされ、明示的なメソッドでフォーマットされていません。

書式付き入力

抽出演算子>>

  • すべての組み込み型と文字列に対して定義済み
  • ユーザー定義のデータ型に実装できます
  • フォーマット指定子によって構成できます。

次のコード スニペットは、2 つの int を読み取る簡単な方法を示しています。

#include <iostream>
...
int a, b;
std::cout << "Two natural numbers: " << std::endl;
std::cin >> a >> b; // < 2000 11>
std::cout << "a: " << a << " b: " << b;

std::cin はデフォルトで先頭の空白を無視します。

フォーマットされていない入力

入力ストリームは、フォーマットされていない入力に対していくつかのメソッドをサポートしています。

  • std::string には getline 関数があります

std::string の getline 関数には、istream の getline 関数よりも大きな利点があります。 std::string は、そのメモリを自動的に処理します。逆に、呼び出し is.get(buf, num) でバッファ buf 用のメモリを予約する必要があります。区切り文字も指定できるので、getline 関数を使用すると非常に便利です。

// inputUnformatted.cpp

#include <fstream>
#include <iostream>
#include <string>

int main(){

 std::cout << std::endl;

 std::string line;
 std::cout << "Write a line: " << std::endl;
 std::getline(std::cin, line); // (1)
 std::cout << line << std::endl;

 std::cout << std::endl;
 
 std::ifstream inputFile("test.txt"); 
 while ( std::getline(inputFile, line, ';') ) { // (2)
 std::cout << line << std::endl;
 }

}

まず、プログラムは行 (1) で std::cin を読み取ります。次に、ファイル test.txt から行 (2) を読み取ります。

簡単にするために、コードはエラー処理を行いません。エラー処理の詳細については、前回の投稿「C++ コア ガイドライン:iostreams」を参照してください。ファイル test.txt には、「;」で区切られた数字が含まれています。

出力

前回の投稿 C++ コア ガイドライン:iostreams で約束したように、ここに iostream の書式指定子があります。それらの場所を知っているか、少なくとも知っておく必要があります。

重要なフォーマット指定子

経験豊富な C++ プログラマーである学生が、私のクラスで、C++ の算術演算は十分に正確ではないという不満をよく耳にします。その理由はほとんどの場合、C++ ではなく、Iostream のデフォルトの書式指定子にあります。知っておくべきことを見てみましょう:

初めに。マニピュレータまたはフラグを使用してフォーマットを指定できます。

マニピュレータとフラグ

// formatSpecifier.cpp

#include <iostream>

int main(){

 std::cout << std::endl;

 int num{2011};

 std::cout << "num: " << num << "\n\n";

 std::cout.setf(std::ios::hex, std::ios::basefield); // (1)
 std::cout << "hex: " << num << std::endl;
 std::cout.setf(std::ios::dec, std::ios::basefield); // (1)
 std::cout << "dec: " << num << std::endl;

 std::cout << std::endl;

 std::cout << std::hex << "hex: " << num << std::endl; // (2)
 std::cout << std::dec << "dec: " << num << std::endl; // (2)

 std::cout << std::endl;

}

行 (1) はフラグを使用し、行 (2) マニピュレーターを使用して出力をフォーマットします。

可読性と保守性の観点から、私はマニピュレーターを強く好みます。

Iostream のマニピュレータ

よし、最も重要なマニピュレータから始めよう.

次の表は、関連する書式指定子を示しています。各アプリケーションの後にリセットされるフィールド幅を除いて、フォーマット指定子はスティッキーです。
引数を持たないマニピュレータにはヘッダ が必要であり、引数を持つマニピュレータにはヘッダ が必要です。

  • ブール値

  • フィールドに文字を入力して入力

  • テキストの配置

  • 正符号と大文字/小文字

  • 数値ベース

  • 浮動小数点数

浮動小数点数には特別なルールがあります:

  • 有効桁数 (カンマの後の桁数) はデフォルトで 6 です。
  • 有効桁数が十分でない場合、数値は科学表記法で表示されます。
  • 前後のゼロは表示されません。
  • 可能であれば、小数点は表示されません。

多くの理論を経て、ここに実際のフォーマット指定子があります。

// formatSpecifierOutput.cpp

#include <iomanip>
#include <iostream>

int main(){

 std::cout << std::endl;

 std::cout << "std::setw, std::setfill and std::left, right and internal: " << std::endl;

 std::cout.fill('#');
 std::cout << -12345 << std::endl;
 std::cout << std::setw(10) << -12345 << std::endl;
 std::cout << std::setw(10) << std::left << -12345 << std::endl;
 std::cout << std::setw(10) << std::right << -12345 << std::endl;
 std::cout << std::setw(10) << std::internal << -12345 << std::endl;

 std::cout << std::endl;

 std::cout << "std::showpos:" << std::endl;

 std::cout << 2011 << std::endl;
 std::cout << std::showpos << 2011 << std::endl;


 std::cout << std::noshowpos << std::endl;

 std::cout << "std::uppercase: " << std::endl;
 std::cout << 12345678.9 << std::endl;
 std::cout << std::uppercase << 12345678.9 << std::endl;

 std::cout << std::nouppercase << std::endl;

 std::cout << "std::showbase and std::oct, dec and hex: " << std::endl;
 std::cout << 2011 << std::endl;
 std::cout << std::oct << 2011 << std::endl;
 std::cout << std::hex << 2011 << std::endl;

 std::cout << std::endl;

 std::cout << std::showbase;
 std::cout << std::dec << 2011 << std::endl;
 std::cout << std::oct << 2011 << std::endl;
 std::cout << std::hex << 2011 << std::endl;

 std::cout << std::dec << std::endl;

 std::cout << "std::setprecision, std::fixed and std::scientific: " << std::endl;

 std::cout << 123.456789 << std::endl;
 std::cout << std::fixed << std::endl;
 std::cout << std::setprecision(3) << 123.456789 << std::endl;
 std::cout << std::setprecision(4) << 123.456789 << std::endl;
 std::cout << std::setprecision(5) << 123.456789 << std::endl;
 std::cout << std::setprecision(6) << 123.456789 << std::endl;
 std::cout << std::setprecision(7) << 123.456789 << std::endl;
 std::cout << std::setprecision(8) << 123.456789 << std::endl;
 std::cout << std::setprecision(9) << 123.456789 << std::endl;

 std::cout << std::endl;
 std::cout << std::setprecision(6) << 123.456789 << std::endl;
 std::cout << std::scientific << std::endl;
 std::cout << std::setprecision(6) << 123.456789 << std::endl;
 std::cout << std::setprecision(3) << 123.456789 << std::endl;
 std::cout << std::setprecision(4) << 123.456789 << std::endl;
 std::cout << std::setprecision(5) << 123.456789 << std::endl;
 std::cout << std::setprecision(6) << 123.456789 << std::endl;
 std::cout << std::setprecision(7) << 123.456789 << std::endl;
 std::cout << std::setprecision(8) << 123.456789 << std::endl;
 std::cout << std::setprecision(9) << 123.456789 << std::endl;

 std::cout << std::endl;

}

出力は、プログラム formatSpecifierOutput.cpp を説明するのに十分なはずです。

次は?

同期しすぎると負ける。 Iostream の場合、パフォーマンスが低下します。次の投稿で数字をお見せします。