入出力ストリーム

コンパイル時に「error C2065: 'cout': 定義されていない識別子です。」のようにエラーとなるならば、using namespace std;としてusingディレクティブで指定するか、std::coutとして名前空間を指定します。

主要なクラス

  char (バイト単位) wchar_t (ワイド単位)
  入力 出力 入力 出力
文字 istream ostream wistream wostream
ファイル ifstream ofstream wfstream wofstream
文字列 istringstream ostringstream wistringstream wostringstream
typedef basic_istream<char, char_traits<char>> istream;
typedef basic_ifstream<char, char_traits<char>> ifstream;
typedef basic_istringstream<char> istringstream;

読み書きを制御するオブジェクト

  char
(バイト単位)
wchar_t
(ワイド単位)
入力 std::cin
cin | MSDN
std::wcin
wcin | MSDN
出力 std::cout
cout | MSDN
std::wcout
wcout | MSDN
エラー出力 (バッファリングなし) std::cerr std::wcerr
エラー出力 (バッファリング付き) std::clog std::wclog
<iostream> | MSDN
std::istream std::cin;

std::ostream std::cout;
std::ostream std::cerr;
std::ostream std::clog;
include\iostream

coutは、既定でcinに結合されています。

std::ostream* os1 = std::cin.tie();
std::ostream* os2 = &std::cout;

(os1 == os2); // true

文字

istream (入力)

typedef basic_istream<char, char_traits<char>> istream;
istream | MSDN

ostream (出力)

typedef basic_ostream<char, char_traits<char>> ostream;
ostream | MSDN

ostreamは、以下の定義済みストリームオブジェクトをサポートします。

  • cout … 標準出力
  • cerr … バッファリングなし標準エラー出力
  • clog … バッファリング付き標準エラー出力
#include <iostream>

int main()
{
    char* str = "abc";
    int num = 123;

    std::cout << str << num << std::endl; // abc123
    std::cout << 1.0 / 6.0 << std::endl;  // 0.166667
}

出力に予期しない修正が加えられる場合には、書式設定を確認します。

write()

ストリームに文字列を出力できます。

basic_ostream<_Elem, _Tr>& write(
    const char_type* str,
    streamsize count
);
basic_ostream::write - basic_ostream クラス
const char str[] = "12345";
std::streamsize count = 3;
std::cout.write(str, count); // 123

wostream

wchar_tを対象としたostreamです。

typedef basic_ostream<wchar_t, char_traits<wchar_t>> wostream;
wostream | MSDN

正しく出力されない場合には、imbue()でロケールを設定します。

これはwchar_t型の文字を出力するためのストリームであり、ワイド文字であってもcharに格納されているならばostreamで出力できます。

char *s1 = "あ";
std::cout << s1;  // あ
std::wcout << s1; // あ

wchar_t *s2 = L"あ";
std::cout.imbue(std::locale(".932"));
std::wcout.imbue(std::locale(".932"));
std::cout << s2;  // *,***,***,***,***,*** (s2のアドレス)
std::wcout << s2; // あ

ファイル

ifstream (入力)

ファイルストリーム。ファイルから1バイトのデータを順番に読み取れます。ifstream | MSDN

std::ifstream stream("sample.txt");

if (!stream.bad())
{
    std::cout << stream.rdbuf();
    stream.close(); // ファイルのクローズ。ただしデストラクタによって暗黙的に実行されるため、通常は不要
}

このifstreamは、

typedef basic_ifstream<char, char_traits<char>> ifstream;

と宣言されているため、

std::basic_ifstream<char, std::char_traits<char>> stream("sample.txt");

としても同じです。

rdbuf

ストリーム バッファのアドレスを取得できます。

basic_filebuf<Elem, Tr> *rdbuf( ) const
basic_ifstream::rdbuf | MSDN

ofstream (出力)

typedef basic_ofstream<char, char_traits<char>> ofstream;
ofstream | MSDN
#include <fstream>

int main()
{
    std::ofstream stream("sample.txt");
    // fstreamではなくiostreamだけをインクルードしていると、Visual Studioは「不完全な型は使用できません」と通知します。

    if (!stream.bad())
    {
        stream << "ABC" << std::endl;
        stream.close();
    }
}

ストリームを開くときに、引数でモードなどを指定できます。

explicit basic_ofstream(
    const char *_Filename,
    ios_base::openmode _Mode = ios_base::out, // 通信方法
    int _Prot = (int)ios_base::_Openprot      // 保護方法 (PROTection)
);
basic_ofstream::basic_ofstream | MSDN

_Modeには下表の値を組み合わせて渡せます。

 
std::ios::app 挿入前にストリームの末尾へ移動
std::ios::ate 作成するときにストリームの末尾へ移動
std::ios::binary バイナリとして読み込む
std::ios::in ストリームからの抽出を許可 (読み込み用)
std::ios::out ストリームへの挿入を許可 (書き込み用)
std::ios::trunc 既存のファイルを削除
ios_base::openmode | MSDN

ストリームに対してstd::endlを出力すると、改行記号 (\n または \r\n) が出力されフラッシュされます。endl | MSDN

stream << std::endl;

wofstream

wofstreamで正しく出力されないときには、imbue()でロケールを明示します。

std::wofstream stream("sample.txt");
stream.imbue(std::locale("", LC_CTYPE));

if (!stream.bad())
{
    std::wstring str = L"あいう";

    stream << str;
    stream.close();
}

同一ファイルへの書き込み

fstreamにはファイルをロックする機能が無いため、同一のファイルへ書き込むと予期せぬ結果をもたらします。

char* filename = "sample.txt";
std::ofstream stream1(filename, std::ios::out | std::ios::trunc);
std::ofstream stream2(filename, std::ios::out | std::ios::trunc);

stream1 << "A";
stream2 << "B";
stream1 << "C";

stream1.flush();
stream2.flush();

stream1.close();
stream2.close();

// ファイルには"BC"と書き込まれる。

一方で、外部でロックされているファイルに書き込んでも失敗します。そのときエラーは発生しませんが、書き込み用にストリームを開いた時点でstream.good()がfalseを返すため、それで異常を検知できます。

文字列

文字列ストリーム

istringstream (入力)

typedef basic_istringstream<char> istringstream;
istringstream - <sstream> typedefs | Microsoft Learn

ostringstream (出力)

typedef basic_ostringstream<char> ostringstream;
ostringstream - <sstream> typedefs | Microsoft Learn
std::ostringstream stream;
stream << "ABC";

エラーの検出

メンバ関数 trueを返す条件 等価な表現
basic_ios::good() ストリームが良い状態 basic_ios::good | MSDN if(rdstate == goodbit)
basic_ios::bad() ストリーム バッファの健全性が失われている basic_ios::bad | MSDN if(rdstate & badbit)
basic_ios::eof() ストリームの末尾に到達している basic_ios::eof | MSDN if(rdstate & eofbit)
basic_ios::fail() 有効なフィールドの読み込に失敗している basic_ios::fail | MSDN if(rdstate & (badbit|failbit))
basic_ofstream::is_open() ファイルが開かれている basic_ofstream::is_open | MSDN rdbuf->is_open()

例外

異常な状態となったときに、例外を投げるように指示できます。

iostate exceptions( ) const;
void exceptions(
    iostate _Newexcept
);
basic_ios::exceptions | MSDN
発生要因
std::ios::badbit バッファの健全性の欠如
std::ios::eofbit ファイル末尾からの読み込み
std::ios::failbit 無効なフィールドの読み込み
ios_base::iostate | MSDN
std::ifstream stream;
stream.exceptions(std::ios::badbit | std::ios::eofbit | std::ios::failbit);

投入される例外はexception型で捕捉でき、その内容はwhat()で確認できます。exception クラス | MSDN

std::cout.exceptions(std::ios::eofbit);
try
{
    std::cout.clear(std::ios::eofbit);
}
catch (std::exception &e)
{
    std::cerr << e.what();
}

wchar_t

wchar_t型の文字が正しく処理されないときには、imbue()でロケールを指定します。

wchar_t s1 = L'a';
std::cout << s1; // 97 ('a'のASCIIコード)
std::wcout << s1; // a

wchar_t *s2 = L"a";
std::cout << s2; // **************** (s2のアドレス)
std::wcout << s2; // a

wchar_t *s3 = L"あ";
std::wcout.imbue(std::locale(".932", LC_CTYPE));
std::wcout << s3; // あ (ロケールを指定しないと、出力されないことがある)

imbue()

ロケールを変更できます。これはCランタイムのsetlocale()に相当します。Differences between the C Locale and the C++ Locales

locale imbue(
   const locale& _Loc
);
basic_ios::imbue - basic_ios クラス | Microsoft Learn

たとえば環境の既定値に設定するには、引数の_Locに次のように指定します。

std::wcout.imbue(std::locale("", LC_CTYPE));

ここで指定するlocaleクラスは、次のように作成できます。

explicit locale(
    const char* _Locname, // ロケールの名前
    category _Cat = all   // ロケールのカテゴリ
);
locale::locale - locale Class | Microsoft Learn

_Locnameは次のいずれかの形式で指定します。Locale Names, Languages, and Country-Region Strings | Microsoft Learn

_Catlocale::categoryにある値を指定することで、適用範囲を制限できます。

ロケール 適用範囲 コード
英語-米国 すべての関数 std::locale("en-US")
日本語-日本 すべての関数 std::locale("ja-JP")
日本語 すべての関数 std::locale("Japanese")
コードページ 932 (Shift-JIS) すべての関数 std::locale(".932")
コードページ 932 (Shift-JIS) 文字列処理関数だけ std::locale(".932", LC_CTYPE)

getloc()

ストリームに格納されているlocaleオブジェクトを得られるため、そこから現在のロケールを確認できます。

std::locale l1 = std::cout.getloc();
std::locale l2 = std::locale(); // global localeに一致したlocaleオブジェクトを作成する

std::string str1 = l1.name(); // "C"
std::string str2 = l2.name(); // "C"

std::cout.imbue(std::locale(".932", LC_CTYPE)); // ロケールを設定する
std::string str3 = std::cout.getloc().name(); // ".932"

UTF-8での出力

codecvt_utf8を用います。 codecvt_utf8 | MSDN c++ - What is the Windows equivalent for en_US.UTF-8 locale? - Stack Overflow

std::wcout.imbue(
    std::locale(
        std::wcout.getloc(),
        new std::codecvt_utf8<wchar_t>)
    );

このときFacet型のクラス テンプレートを引数に取る、localeのコンストラクタが呼び出されます。

template<class Facet>
    locale(
        const locale& _Loc,
        const Facet* _Fac
    );
locale::locale | MSDN

さらにBOMを付けて出力するには、Modeにgenerate_headerを指定します。

std::wcout.imbue(
    std::locale(
        std::wcout.getloc(),
        new std::codecvt_utf8<wchar_t, 0x10ffff, std::codecvt_mode::generate_header>)
    );
codecvt_mode  
std::codecvt_mode::consume_header 最初のヘッダをエンディアンの決定のために利用する
std::codecvt_mode::generate_header 最初にヘッダを生成する
std::codecvt_mode::little_endian リトルエンディアンとして生成する
codecvt_mode | MSDN
ロケールの指定と、L"あ"の出力結果
imbue()の引数 出力
imbue()の呼び出しなし なし
std::locale("", LC_CTYPE) 82 A0 (Shift_JISにおける「あ」のコード)
std::locale(std::locale(), new std::codecvt_utf8<wchar_t>) E3 81 82 (UTF-8における「あ」のコード)
std::locale(std::locale(), new std::codecvt_utf8<wchar_t, 0x10ffff, std::codecvt_mode::generate_header>) EF BB BF E3 81 82 (UTF-8におけるBOM+「あ」のコード)

参考

参考書

バッファ

pubsetbuf

setbufを呼び出し、バッファのサイズを設定できます。

basic_streambuf<Elem, Tr> *pubsetbuf(
    char_type *_Buffer, // バッファへのポインタ
    streamsize _Count   // バッファのサイズ
);
basic_streambuf::pubsetbuf | MSDN

basic_filebuf

template <class Elem, class Tr = char_traits<Elem>>
class basic_filebuf : public basic_streambuf<Elem, Tr>
basic_filebuf クラス | MSDN

書式 (formatting)

flags()で書式を設定できます。

fmtflags flags(
   fmtflags fmtfl // 新しく設定するフラグ
);
ios_base::flags | MSDN

fmtflに指定できる値はios_base::fmtflagsにあります。

フラグの値 作用
boolalpha to insert or extract objects of type bool as names (such as true and false) rather than as numeric values.
dec to insert or extract integer values in decimal format.
fixed to insert floating-point values in fixed-point format (with no exponent field).
hex to insert or extract integer values in hexadecimal format.
internal to pad to a field width as needed by inserting fill characters at a point internal to a generated numeric field.
left to pad to a field width as needed by inserting fill characters at the end of a generated field (left justification).
oct to insert or extract integer values in octal format.
right to pad to a field width as needed by inserting fill characters at the beginning of a generated field (right justification).
scientific to insert floating-point values in scientific format (with an exponent field).
showbase to insert a prefix that reveals the base of a generated integer field.
showpoint to insert a decimal point unconditionally in a generated floating-point field.
showpos to insert a plus sign in a non-negative generated numeric field.
skipws to skip leading white space before certain extractions.
unitbuf to flush output after each insertion.
uppercase to insert uppercase equivalents of lowercase letters in certain insertions.
ios_base::fmtflags | MSDN

フラグを簡単に記述できる、下表の速記もあります。

フラグの値 実際の定義
adjustfield internal | left | right
basefield dec | hex | oct
floatfield fixed | scientific
std::cout.flags(std::ios::dec | std::ios::boolalpha);

このとき指定しなかったフラグは、すべて既定値に初期化されます。よって、

std::cout.flags(std::cout.flags() | std::ios::dec);

のように現在の値と重ねて指定するか、setf()で個別に指定します。この関数では、指定のフラグのみを有効/無効にできます。

fmtflags setf(
    fmtflags _Mask // 有効にするフラグ
);
fmtflags setf(
    fmtflags _Mask, // 有効にするフラグ
    fmtflags _Unset // 無効にするフラグ
);
ios_base::setf | MSDN
std::cout << 10 << std::endl; // 10

std::cout.setf(std::ios::hex, std::ios::basefield);
std::cout << 10 << std::endl; // a

std::cout.setf(std::ios::dec, std::ios::basefield);
std::cout << 10 << std::endl; // 10
double n = 1.0 / 6.0;
std::cout << n << std::endl; // 0.166667

std::cout.flags(std::ios::fixed);
std::cout << n << std::endl; // 0.166667

std::cout.flags(std::ios::scientific);
std::cout << n << std::endl; // 1.666667e-01

std::cout.flags(std::ios::floatfield);
std::cout << n << std::endl; // 0x1.555555p-3

または、次のようにも指定できます。

std::cout << 10;             // 10
std::cout << std::hex << 10; // a
std::cout << 10;             // a

バイナリ モード

既定ではテキスト モードで出力され、改行コード (\n) をstd::cout << (char)0xa;と出力すると、Windows環境では0xd、0xa (\r\n) に変換されて出力されます。これを変換させないようにするには

_setmode(_fileno(stdout), _O_BINARY);

でバイナリ モードとします。 c - What is the simplest way to write to stdout in binary mode? - Stack Overflow _setmode | Microsoft Learn

参考

参考書

参考

参考書

Microsoft Learnから検索