2012-11-16 44 views
1

我有一個我正在研究的研究項目。我是C++和一般編程的初學者。我已經制定了一個程序,可以隨着時間的推移產生在連續空間中移動的相互作用的粒子。我的程序輸出的唯一東西是每個時間步中每個粒子的XY座標。C++:如何將數據輸出到多個.dat文件?

我想要想象我的發現,知道我的粒子是否正在移動。我的教授說我必須用gnuplot。因爲我不能在一個文件中,以便gnuplot會承認它找到一個方法來輸出我的數據,我認爲以下策略:

一)對於每個時間步生成一個文件的形式「output_#.dat與XY座標」。

b)在gnuplot中爲每個文件生成一個.png文件。

c)用所有.png文件製作運動粒子的電影。

我會擔心b和c後,但到現在爲止,使用此代碼我能夠輸出我的所有數據在一個文件中:

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.datoutput01.dat第一個包含了最初的隨機生成位置,第二個包含了我所有的結果。

我可以感覺到,在嵌套的for循環中,我正在更新XY座標的速度和位置,我可以有一個FILE*,它將存儲每個時間步的座標,然後在遞增時間之前關閉它。這樣,我不需要同時打開多個指針。至少這是我的直覺。

我不知道如何生成遞增的文件名。我向ofstream迷迷糊糊的,但我不明白它是如何工作...

我想我會喜歡我的節目在這一點上做的是:

1)生成一個新的文件名,使用基本名稱和當前循環計數器值。

2)打開該文件。

3)編寫該時間步的座標。

4)關閉文件。

5)重複。

任何幫助將不勝感激。感謝您的時間!

+5

所以你寫了一個代碼,它會產生「隨着時間的推移在連續空間上移動的相互作用的粒子」,並且仍然不知道如何使用循環? – 2012-11-16 17:15:00

+0

親愛的_aleguna_,我知道如何使用循環(我猜),但我正在學習,因爲我去,我自學成才。如果你可以回頭看看你開始編程的時候,你可能會理解我的困境,因爲我在沒有任何幫助的情況下這樣做。當然,無數其他人也這樣做了,但提出問題是唯一的學習方式。 _wjl_非常友好,可以在他的答案中提供代碼,但即使他指向我c_str()並創建一個新方法,我也會同樣高興。感謝您的理解。 – Dima1982

+1

+1,因爲即使這不是最好的問題,但這是一個有效的問題,並不值得得到太多的迴應。 – wjl

回答

2

使用ofstream而不是fopen會更好地使用C++標準庫,而現在您正在使用C標準庫調用,但本身並沒有什麼錯誤與您現在正在做的事情。

好像你真正的核心問題是如何從一個整數的文件名,所以你可以在一個循環中使用它:

這裏有一種方法:

// 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時,必須給它一個const char *而不是std :: string,所以我們使用.c_str()成員只存在於此目的中。

+0

非常感謝您的快速回復。我正在閱讀Savitch的Absolute C++,並隨時隨地搜索互聯網,但我的進度緩慢。我不知道我做錯了兩次被拒絕。你的回答是我覺得我自己找不到的東西。再次感謝您的時間和精力! – Dima1982

+1

@ Dima1982爲了避免在未來被拒絕投票,我只是建議儘量讓你的問題儘可能清晰,所以讀者不必通讀整篇文章,搞清楚你真的是什麼問。例如,你的問題不是真的*關於你的算法或循環,但它花了一些努力去看看你真正的問題是什麼(用一個整數構建字符串)。在這種情況下,我並不介意,但總的來說,問題不大可能會引起社區的憤怒。 =) – wjl

+0

非常感謝您的支持。對此,我真的非常感激。我將來會記住這一點。 – Dima1982

相關問題