いっつも忘れるC++ ファイル入出力関数を図にしてみた

# C++ ファイル入出力関数

## 継承関係

+ 継承関係については、

>> https://www.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html 真ん中らへんの図
>
>![image](https://www.ntu.edu.sg/home/ehchua/programming/cpp/images/IOclasses.png)

がわかりやすそうです。

## ファイル入出力関数のダイアグラム

さて、C++でファイルの入出力を扱うに当たって、C言語のscanf系やprintf系は結構落とし穴があるので、C++のifstreamとか〇〇streamとかを使いたいのですが、いつも使い方を忘れてしまいます(私だけではないはず)。そこで、普段使いに便利なダイアグラムをつくってみました！：

![iostream2.png](https://qiita-image-store.s3.amazonaws.com/0/133922/1d98e180-55ce-dc3f-8c18-ec8247cb2e61.png)
※2については、https://www.jpcert.or.jp/sc-rules/c-int06-c.html あたりも参考にしてください。あ、strtol関数はstdlib.hをincludeです。

## サンプル

```cpp:main.cpp
#include <string>
#include <iostream>  //std::right, std::out, std::endl
#include <iomanip> //std::setw(int w)
#include <fstream>   // ifstream, ofstream
#include <sstream>   // istringstream, ostringstream

/* sample.txt
001.bmp,0,34
002.bmp,5,563
003.bmp,4,979
*/

int main()
{
	//入力ストリームの作成
	const std::string input = "sample.txt";
	std::ifstream ifs(input, std::ios::in);

	//出力ストリームの作成
	const std::string output = "output.txt";
	std::ofstream ofs(output, std::ios::out);
	std::string buf;

	char linedelimiter = ',';

	//一行づつ読み込む
	while (std::getline(ifs, buf))
	{
		std::string fn;

		std::istringstream iss(buf);
		getline(iss, fn, linedelimiter);

		int num1, num2;
		char dummy; //','をよみこませるためのdummy
		iss >> num1 >> dummy >> num2;
		int num = num1*num2;

		//もしくは
		//std::string data;
		//int num = 1;
		//while (std::getline(iss, data, linedelimiter))
		//{
		//	num *= std::stoi(data);
		//}


		//ファイルに書き込み
		//書式設定(下記)を参照のこと
		ofs << fn << std::setw(10) << std::right << num << std::endl;
		//ついでに標準出力にも。
		std::cout << fn << std::setw(10) << std::right << num << std::endl;
	}
	return 0;
}

/* output.txt
001.bmp         0
002.bmp      2815
003.bmp      3916
*/


```

## 書式設定

+ ostream, ofstream, ostringstream に関しては、ios(iostreamはiosがincludeされている), iomanipをincludeして、書式を設定できます。(http://www.sist.ac.jp/~suganuma/cpp/3-bu/16-sho/16-sho.htm あたりを参考にしました。)


`#include <iostream>` もしくは  `#include <ios>`

```cpp:フラグ
skipws     = 0x0001 // ストリームの入力中，先頭の空白文字を読み飛ばす
left       = 0x0002 // 出力を左寄せ
right      = 0x0004 // 出力を右寄せ
internal   = 0x0008 // 符号と数字の間にブランクを入れ出力幅一杯にする
dec        = 0x0010 // 10進表記（デフォルト）
oct        = 0x0020 // 8進表記
hex        = 0x0040 // 16進表記
showbase   = 0x0080 // 数値の基数の表示
showpoint  = 0x0100 // 浮動小数点の出力で小数点，右端の0，eを表示
uppercase  = 0x0200 // 浮動小数点のe等を大文字で表示
showpos    = 0x0400 // 正の数値の前に+を表示
scientific = 0x0800 // 実数値を浮動小数点表示
fixed      = 0x1000 // 固定小数点表示（デフォルト）
unitbuf    = 0x2000 // 出力の度に，すべてのストリームをフラッシュ
stdio      = 0x4000 // 出力の度に，stdout及びstderrをフラッシュ

int width(int <長さ>);      // 出力幅制御
char fill(char <文字>);     // 空白を埋める文字
// 小数点以下の桁数（デフォルトは 6 桁．固定小数点の場合は，小数点や符号を除いた全体の桁数になり，
//表示できないときは浮動小数点表示となる
int precision(int <桁数>); 
```

`#include <iomanip>`

```cpp
dec                  // 10 進表記
endl                 // 改行文字の出力
ends                 // 空白文字の出力
flush                // ストリームのフラッシュ
hex                  // 16 進表記
oct                  // 8 進表記
resetioflags(long f) // f で指定されたフラッグを off
setbase(int base)    // 基数を base にする
setfill(int ch)      // 文字 h で埋める
setioflags(long f)   // f で指定されたフラッグを on
// 小数点以下 p 桁（デフォルトは 6 桁．固定小数点の場合は，小数点や符号を除いた全体の桁数になり，表示できないときは浮動小数点表示となる）
setprecision(int p)
setw(int w)          // 出力幅を w
ws                   // 先頭の空白を読み飛ばす
```

### 使用例

```cpp
#include <iostream> //std::right
#include <iomanip> //std::setw(int w)
int main(){
  double a=3.14159;

  //混在できる
  std::cout << std::setw(10) << std::right << a << std::endl; //output : "   3.14159"
  return 0;
}
```

---
すっきりした！