C++のiostream

標準入出力のバイナリモード

例えば K&R のプログラミング言語 C 第2版 の 1.5.2 の例題の文字数のカウントを Windows でやると <CR><LF> の対で1文字とカウント される。つまりファイルを redirect してやると、 ファイルのバイト数とカウント数が一般には一致しない。 標準出力も同様で '\n' 一文字を出力すると、<CR><LF> の対が出力される。

これは Windows では、標準入出力が default で テキストモードであるためである。これはこれで 便利なこともあるが、バイナリモードで行いたいことも ある。

ファイル入出力なら open 時に指定できるが、、

C でも C++ でもファイル入出力に関しては規格上 open 時に モードを設定することができるので、 これを使えばよいが、標準入出力はプログラムの最初から すでに open されており、ファイルとして実装されて いる保障も無い。更にモード変更の仕組みも用意されて いない。 というわけで処理系依存にならざるを得ない。

gcc と VC 共通コード

一応、gcc/g++ (mingw 3.4.5) と Visual C++ 9.0 Express Edition と共通のコードが書けたので、メモしておく。 以下は、K&R の 1.5.2 の文字数をカウントする例題を Windows バイナリ化したものである。

#include <iostream>
#include <cstdio>
#include <fcntl.h>
#include <io.h>

int main()
{
	std::ios_base::sync_with_stdio(false);
	_setmode(_fileno(stdin),_O_BINARY);
	std::ios_base::sync_with_stdio(true);

	long nc = 0;
	char c;
	while(std::cin.get(c))
		++nc;
	std::cout << nc << std::endl;
	return 0;
}

sync_with_stdio について

ここで、sync_with_stdio は ios_base の静的公開関数で あるので、これを継承している ios でも istream でも ostream でも、あるいはそのオブジェクトである cin や cout からでも呼び出せる。例えば

	std::ios::sync_with_stdio(false);
	_setmode(_fileno(stdin),_O_BINARY);
	std::ios::sync_with_stdio(true);

としてもよいし、

	std::cin.sync_with_stdio(false);
	_setmode(_fileno(stdin),_O_BINARY);
	std::cin.sync_with_stdio(true);

としてもよい。ただし、sync_with_stdio はこの関数一回の 呼び出しですべての標準入出力に影響を与えるが、 一番最後の書き方は、このことが見えにくくなるので、 あまり薦めない。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2010-05-30 (日) 09:16:41