2012-01-02 90 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