These search terms have been highlighted:[c++]
2009-07-22
gnuplot のようなプログラムには,パイプを使ってほかのプログラムからデータを送ることができる.std::cout などのストリームクラスのように,パイプストリームクラスを作成すると便利そうなので,実装してみた.
パイプストリームクラス (pstream.h) †
#ifndef pstream_h
#define pstream_h
//-------------------------------------------------------------------------------------------
#include <cstdio>
#include <iostream>
#include <sstream>
//-------------------------------------------------------------------------------------------
namespace hogehoge
{
//-------------------------------------------------------------------------------------------
namespace ps
{
//-------------------------------------------------------------------------------------------
struct __pendl {char dummy;} endl;
struct __pflush {char dummy;} flush;
class pipestream
{
private:
FILE *p;
public:
pipestream (void) : p(NULL) {};
pipestream (const char *name) : p(NULL) {open(name);};
~pipestream (void) {close();}
bool open (const char *name)
{
if (is_open()) close();
p = popen(name, "w");
if (p == NULL)
{
std::cerr<<"failed to open "<<name<<std::endl;
return false;
}
return true;
};
void close (void)
{
if(is_open()) {pclose(p); p=NULL;}
};
bool is_open (void) const {return p!=NULL;};
template <typename T>
pipestream& operator<< (const T &rhs)
{
std::stringstream ss;
ss<<rhs;
fputs(ss.str().c_str(), p);
return *this;
};
pipestream& operator<< (const char *rhs)
{
fputs(rhs, p);
return *this;
};
pipestream& operator<< (const __pendl &rhs)
{
fputs("\n", p);
fflush(p);
return *this;
};
pipestream& operator<< (const __pflush &rhs)
{
fflush(p);
return *this;
};
};
//-------------------------------------------------------------------------------------------
} // end of namespace ps
//-------------------------------------------------------------------------------------------
} // end of namespace hogehoge
//-------------------------------------------------------------------------------------------
#endif // pstream_h
サンプルプログラム †
gnuplot でリサージュカーブを描かせるサンプル.
#include "pstream.h"
#include <fstream>
#include <cmath>
using namespace std;
using namespace hogehoge;
const double step_size (0.1);
void generate_lissajous (const char *filename, const double &time)
{
ofstream ofs(filename);
for (double t(time); t<time+1.0; t+=step_size)
ofs<< cos(1.5*t) <<" "<< sin(t) <<endl;
ofs.close();
}
int main()
{
const char *filename= "data.dat";
double time=0.0;
generate_lissajous (filename, time);
ps::pipestream gnuplot ("gnuplot");
gnuplot<<"set grid"<<ps::endl;
gnuplot<<"set nokey"<<ps::endl;
gnuplot<<"set xlabel 'X'"<<ps::endl;
gnuplot<<"set ylabel 'Y'"<<ps::endl;
gnuplot<<"set xrange[-1.2:1.2]"<<ps::endl;
gnuplot<<"set yrange[-1.2:1.2]"<<ps::endl;
gnuplot<<"plot '"<<filename<<"' w l lt 3"<<ps::endl;
for (time+=step_size; time<20.0; time+=step_size)
{
generate_lissajous (filename, time);
gnuplot<<"replot"<<ps::endl;
usleep(50000);
}
}
gnuplot のプロンプトでタイプするように,ストリーム演算子でコマンドを送れるので,コマンドを覚えている人は使いやすいかも.これをさらにラップしたグラフプロットクラスを作っても,そのクラスの使い方を覚える手間が掛かるし,凝ったことができないかもしれないし.このプログラムだと一石二鳥では.