#はじめに
FORTRANは、ファイルopen文を書かずに、機番という番号で管理されたファイルに出力することができます。これはデバッグなどで複数のファイルを急いで出力したい時に重宝します。一方、C++の標準ライブラリでは、ファイル名決めてオープンする必要があり、ちょっと不便です。
そこで、C++でも同様にopen文が不要なクラスを作りました。
(Boost.Logでも十分便利な気がしますが)
#FORTRANのファイル出力
FORTRANでテキストファイル「hoge.txt」に「hoge」を出力する時、次のようにします。
open(911,file="hoge.txt",status='replace',action='write') ! ファイルオープン
write(911,*)"hoge" ! hogeを出力
close(911) !ファイルを閉じる
open文の911は機番というファイル番号です。機番は、5が標準入力、6が標準出力、それ以外はユーザが自由に使えます。
ところで、FORTRANは、open文を書かずに、write文だけを書くことも出来ます。
write(911,*)"hoge" ! hogeを出力
こうすると、ファイル名未指定ですが自動的に「fort.911」というファイルが開かれて、「hoge」が出力されます。
急いでデバグしたいときや、テンポラリファイルを作りたいときはこれは便利です。これがC++にもあったら良いなと思った次第です。
#要件
というほどでもないですが、下記が要件です。
・機番を指定してwriteした時に、その機番に対応するファイルが存在すればそのファイルに出力し、存在しなければ、ファイルを新規作成して出力する。
911番に出力する場合は下記のように記述したい。
fortran_textfile::write(911,"hoge"); // 911にファイル書き込み
これで言うべきことは言ってしまった気がします。
#実装(ヘッダー)
ヘッダー、及び機番に対応するファイルを取得する関数get_fileのソースを記載いたしました。
ヘッダーの実装
//*****************************************************************************
//! @class fortran_textfile
//! @brief FORTRAN式ファイル書込クラス
//*****************************************************************************
class fortran_textfile
{
// シングルトンクラス
private:
static fortran_textfile* s_ptmStamp; //!< シングルトンの実体へのポインタ
public:
// シングルトンオブジェクトの構築/消滅
static fortran_textfile* create_obj();
static void delete_obj();
// 指定した機番に書込
static bool write( int unit_number_of_file , char* line );
private:
// コンストラクタ/デストラクタ
fortran_textfile();
~fortran_textfile();
// 機番ー>ファイルオブジェクトのマップ
std::unordered_map< int, std::ofstream* > m_fout_map;
private:
// シングルトンオブジェクトの取得
static fortran_textfile* get_obj();
// ファイルチェック
static bool validate( std::ofstream* pfile );
// 機番に対応するファイル取得
static std::ofstream* get_file( int unit_number_of_file );
};
get_file関数の実装
//*****************************************************************************
//! @brief ファイル取得
//! @date 2018/01/08 Created by zmtx_pp
//*****************************************************************************
inline std::ofstream* fortran_textfile::get_file( int unit_number_of_file )
{
assert( s_ptmStamp != nullptr );
// ファイル生成済みなら取得、未生成なら生成して返す
if( s_ptmStamp->m_fout_map.find( unit_number_of_file ) != s_ptmStamp->m_fout_map.end() ){
std::ofstream* pfile = s_ptmStamp->m_fout_map[ unit_number_of_file ];
if( !validate( pfile ) ) return false;
return pfile;
}
else{
char chBuf[10];
sprintf_s( chBuf, "fort.%d", unit_number_of_file );
std::ofstream* pfile = new std::ofstream( chBuf );
s_ptmStamp->m_fout_map[ unit_number_of_file ] = pfile;
if( !validate( pfile ) ) return false;
return pfile;
}
return nullptr;
}
#使い方
こんな感じに使ってます。シングルトンオブジェクトの生成消滅を呼ぶくらいならファイルオープンしろ、と思いますが、まあそれはそれで。下記は、3つの機番111,311,511に出力を行っております。fort.111,fort.311,fort.511が生成され、それぞれに、hoge,hoger,hogestが出力されます。
fortran_textfile::create_obj(); // シングルトンオブジェクトの生成
fortran_textfile::write(111,"hoge"); // 111にファイル書き込み
fortran_textfile::write(311,"hoger"); // 311ファイル書き込み
fortran_textfile::write(511,"hogest"); // 511ファイル書き込み
fortran_textfile::delete_obj(); // シングルトンオブジェクトの消滅
#終わり
私はC++はブランクがかなりあるようなので、ご意見、ご教示頂けるとうれしいです。
更新履歴
2018/01/13
get_fileのソースファイルを追加いたしました。