2012-01-02 217 views
1

我習慣於在Fortran中編寫程序(這是f90),但我需要用C++編寫程序。我很困惑如何從C++函數傳遞多維數組。舉個例子,我想在子程序中讀取XYZ格式的原子座標列表,然後將座標傳遞給主程序。在C++中爲Fortran程序員傳遞多維數組

這是用Fortran:

program findcenterofmass 
character*2 atm(1000) 
integer ttl 
real*8 crd(1000,3) 

call getxyz(atm,ttl,crd) 
call centerofmass(ttl,crd) 
end 

subroutine getxyz(element,atomcount,coord) 
character*2 element(1000) 
integer atomcount 
real*8 coord(1000,3) 
open(file='test.xyz',unit=1) 
read(1,*) atomcount 
read(1,*) 
do i=1,atomcount 
    read(1,*) element(i),(coord(i,j),j=1,3) 
enddo 
close(unit=1) 
end 

subroutine centerofmass(atomcount,coord) 
integer atomcount 
real*8 coord(1000,3) 
real*8 x,y,z 
do i=1,atomcount 
    x=x+coord(i,1)/atomcount 
    y=y+coord(i,2)/atomcount 
    z=z+coord(i,3)/atomcount 
enddo 
write(*,*) 'Center of mass is x: ',x,' y:',y,' z:',z 
end 

此處讀取的文件是一個非常簡單的CO2分子:

3 

C 0.0 0.0 0.0 
O -1.4 0.0 0.0 
O 1.4 0.0 0.0 

所以我需要做的在C此相同的步驟++和一部分似乎 最令人困惑的是讀取座標到多維 數組,然後將數組傳回主程序。

這裏的C++(這有錯誤) - 任何幫助將不勝感激!

#include <stdio.h> 
#include <iostream> 
#include <string> 
#include <sstream> 

void readxyz(double& x); 

int main() { 

double x[100][3]; 
readxyz(double& x); 
std::cout << " x " << x[0][0] << "\n"; 
return 0; 
} 

void readxyz(double& coord[][3]) 
{ 
    int i,j,k; 
    int ttl; 
    int MAXATOM=1000; 
    int MAXLINE=72; 
    char atoms[MAXATOM][2]; 
    long double coord[MAXATOM][3]; 
    char s[MAXLINE]; 
    const char* filename="test.xyz"; 

    using namespace std; 
    cout.precision(12); 

    FILE *fp = fopen(filename,"r"); 

    fgets(s,MAXLINE,fp); 
    std::stringstream stream(s); 
    stream >> ttl; 

    fgets(s,MAXLINE,fp); 

    for (i = 0; i < ttl; i++) { 
    fgets(s,MAXLINE,fp); 
    std::stringstream stream(s); 
    stream >> atoms[i] >> coord[i][0] >> coord[i][1] >> coord[i][2]; 
    } 
} 
+0

@Anycorn:不_really_相關,如Fortran語言在這種情況下是user11255566想重新寫在C++ ... – sarnold 2012-01-02 02:53:01

+0

節目我不好的想法,他想通過c和f90之間的數組 – Anycorn 2012-01-02 02:58:22

+0

相關[常見問題](http:// stackoverflow。com/questions/4810664 /) – fredoverflow 2012-01-02 13:07:47

回答

0

注意char atoms[MAXATOM][2];,但在循環書寫時到atoms你不給足夠的指標:stream >> atoms[i] //...

0

double& coord[][3]爲引用的二維數組,一個固定的維度和一個未定義的尺寸,如果它甚至編譯。可能不是你想要的。被調用函數而不是能夠在運行時確定未知尺寸的大小。

當您在C++中傳遞多維數組時,所有傳遞的內容都是指向第一個元素的指針。因此,與任意尺寸的工作無處不在,你通過指針,任何尺寸爲額外的參數:

void readxyz(double* coord, size_t numCoords, size_t numAxes) 
{ // ... access array data with: 
    coord[coordIndex * numAxes + axisIndex] 

    // ... or somewhat optimized in loops: 
    for(int coordIndex = 0; coordIndex < numCoords; ++coordIndex) { 
     double* thisCoord = coord + coordIndex * numAxes; 
     cout << "("; 
     for(int axisIndex = 0; axisIndex < numAxes; ++axisIndex) { 
      if(axisIndex) 
       cout << ", "; 
      cout << thisCoord[axisIndex]; 
     } 
     cout << ")" << endl; 
    } 
} 

你還沒有進入細節爲你會在你的信息做什麼我讀過它,所以我不知道數據是否必須作爲多維數組存儲以便進一步處理。就個人而言,我將存儲此作爲Atom對象的矢量,並且將只使用C++的I/O而不是混合C(功能開始f)和C++(類與stream結尾):

#include <iostream> 
#include <iomanip> 
#include <fstream> 
#include <vector> 

struct Atom 
// Defined as a `struct` to keep it as a simple "plain old data" (POD) type. 
// It doesn't have to be this way. 
{ // Store atom names as C strings; they can have up to 3 characters. 
    // Possible optimization: store the atomic number (one byte) instead 
    // and use a lookup table (or std::map) to get names. 
    char name[4]; 
    double x, y, z; 
}; 

typedef std::vector<Atom> Atoms; 

std::istream& operator >>(std::istream& is, Atom& a) 
{ // Always use setw() with char* to avoid buffer overflow. 
    is >> std::setw(4) >> a.name >> a.x >> a.y >> a.z; 
    return is; 
} 

void ReadAtoms(const char* filename, Atoms& atoms) 
{ std::ifstream ifs(filename); 
    size_t numAtoms; 
    ifs >> numAtoms; 

    for(size_t i = 0; i < numAtoms; i++) 
    { Atom atom; 
     ifs >> atom; 
     atoms.push_back(atom); 
    } 
} 

int main(int argc, char* argv[]) 
{ if(argc != 2) 
    { std::cerr << "Usage: " << argv[0] << " <filename>" << '\n'; 
     return 1; 
    } 

    Atoms atoms; 
    ReadAtoms(argv[1], atoms); 
    std::cout << " x " << atoms[0].x << '\n'; 
    return 0; 
} 

這並未」 t處理輸入文件中的損壞數據,但這是一個起點。

+0

在C++中沒有引用數組。 – fredoverflow 2012-01-02 13:08:25

0

是否有意從文件中讀取數組的實際長度?我是從Fortran的猜測:

read(1,*) atomcount 
do i=1,atomcount 
    read(1,*) element(i),(coord(i,j),j=1,3) 
enddo 

如果是的話,將是更明智的,而不是猜測的最大長度(1000)數組變量的長度。如果你的猜測太小,會發生什麼?在Fortran> = 90或C++中,這很容易實現。在Fortran中,使數組「可分配」並在從文件中讀取大小atomcount後分配它們。也不是有必要明確地傳遞各種程序之間的陣列尺寸...

+0

你是對的,它確實從文件中讀取了長度。只要atomcount小於最大大小,程序就可以正常工作。您只需手動更改較大系統的內存大小並重新編譯(舊的F77樣式!)。在我理解如何在C++中傳遞數組之前,我不想嘗試創建可變大小的數組。我只是在圍繞着C++和Fortran傳遞多維數組的過程中遇到困難。 – user1125566 2012-01-02 04:26:43