C++
Fortran
クラス
ファイル
出力

FORTRAN的に機番で管理するファイル出力クラス

はじめに

 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のソースファイルを追加いたしました。