1

私は自分が取り組んでいる研究プロジェクトを持っています。私はC++とプログラミング全般の初心者です。時間の経過とともに連続空間を移動する相互作用する粒子を生成するプログラムをすでに作成しました。私のプログラムが出力するのは、各タイムステップの各パーティクルのXY座標だけです。

発見したことを視覚化して、粒子が適切に動いているかどうかを確認したいと思います。私の教授は私が使わなければならないと言ったgnuplot。データを1つのファイルに出力して認識できるようにする方法が見つからなかったためgnuplot、次の戦略を考えました。

a)タイムステップごとに、「output_#.dat」の形式のXY座標を持つ1つのファイルを生成します。

b).pngでそれぞれのファイルを生成しますgnuplot

.pngc)すべてのファイルで動く粒子のムービーを作成します。

後でbとcについて心配しますが、これまでは、次のコードを使用してすべてのデータを1つのファイルに出力できます。

    void main()
{
    int i = 0;
    int t = 0; // time
    int j = 0; 
    int ctr = 0;
    double sumX = 0;
    double sumY = 0;
    srand(time(NULL)); // give system time as seed to random generator


    Cell* particles[maxSize]; // create array of pointers of type Cell.

    for(i=0; i<maxSize; i++) 
    {
        particles[i] = new Cell(); // initialize in memory
        particles[i]->InitPos(); // give initial positions
    }

    FILE *newFile = fopen("output_00.dat","w"); // print initial positions
    for(i=0; i<maxSize; i++)
    {
        fprintf(newFile, "%f %3 ", particles[i]->getCurrX());
        fprintf(newFile, "%f %3 \n", particles[i]->getCurrY());
    }
    fclose(newFile);

    FILE *output = fopen("output_01.dat","w");
    for(t = 0; t < tMax; t++)
    {
        fprintf(output, "%d ", t);
        for(i=0; i<maxSize; i++) // for every cell
        {
            sumX = 0;
            sumY = 0;
            for(j=0; j<maxSize; j++) // for all surrounding cells
            {
                sumX += particles[i]->ForceX(particles[i], particles[j]);
                sumY += particles[i]->ForceY(particles[i], particles[j]);
            }
            particles[i]->setVelX(particles[i]->getPrevVelX() + (sumX)*dt); // update speed
            particles[i]->setVelY(particles[i]->getPrevVelY() + (sumY)*dt);
            particles[i]->setCurrX(particles[i]->getPrevX() + (particles[i]->getVelX())*dt); // update position
            particles[i]->setCurrY(particles[i]->getPrevY() + (particles[i]->getVelY())*dt);

            fprintf(output, " ");
            fprintf(output, "%f %3 ", particles[i]->getCurrX());
            fprintf(output, "%f %3 \n", particles[i]->getCurrY());
        }
    }
    fclose(output);
}

これにより、実際に2つのファイルが生成され、最初のファイルにはoutput_00.datランダムoutput01.datに生成された最初の位置が含まれ、2番目のファイルにはすべての結果が含まれます。

forXY座標の速度と位置を更新しているネストされたループでは、FILE*時間をインクリメントする前に、各タイムステップの座標を格納し、それを閉じることができると感じることができます。そうすれば、複数のポインターを同時に開く必要がなくなります。少なくともそれが私の直感です。

増分ファイル名を生成する方法がわかりません。私はつまずいたがofstream、それがどのように機能するのか理解していない...

この時点で私のプログラムに実行してほしいことは次のとおりです。

1)ベース名と現在のループカウンター値を使用して、新しいファイル名を生成します。

2)そのファイルを開きます。

3)そのタイムステップの座標を記述します。

4)ファイルを閉じます。

5)繰り返します。

どんな助けでも大歓迎です。お時間をいただきありがとうございます!

4

1 に答える 1

2

fopenの代わりにofstreamを使用すると、C ++標準ライブラリをより適切に使用できますが、現在はC標準ライブラリ呼び出しを使用していますが、現在行っていること自体に問題はありません。

あなたの本当の核心的な質問は、整数からファイル名を生成してループで使用できるようにする方法のようです。

これが1つの方法です:

// Include these somewhere
#include <string>
#include <sstream>

// Define this function
std::string make_output_filename(size_t index) {
   std::ostringstream ss;
   ss << "output_" << index << ".dat";
   return ss.str();
}

// Use that function with fopen in this way:
for (size_t output_file_number=0; /* rest of your for loop stuff */)  {
  FILE *file = fopen(make_output_filename(output_file_number).c_str(), "w");
  /* use the file */
  fclose(file);
}

これは、std :: ostringstream "を使用して、ストリーム操作を使用してファイル名を作成し、作成されたstd :: stringを返します。fopenに渡す場合は、std::stringではなくconstchar*を指定する必要があります。この目的のためだけに存在する.c_str()メンバーを使用します。

于 2012-11-16T17:17:16.507 に答える