为fortran程序员在c++中传递多维数组
pass multidimensional array in C++ for a fortran programmer
我习惯用Fortran写程序(这是f90),但我需要用c++写一个程序。我对如何从c++函数传递多维数组感到非常困惑。举个例子,我想在子例程中以XYZ格式读取原子坐标列表,然后将坐标传递给主程序。
下面是用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];
}
}
注意char atoms[MAXATOM][2];
,但在循环中写入atoms
时没有给出足够的索引:stream >> atoms[i] //...
是否打算从文件中读取数组的实际长度?我是从Fortran中猜出来的:
read(1,*) atomcount
do i=1,atomcount
read(1,*) element(i),(coord(i,j),j=1,3)
enddo
如果是这样,最好将数组设置为可变长度,而不是猜测最大长度(1000)。如果你的猜测太小会发生什么?这在Fortran>=90或c++中很容易做到。在Fortran中,将数组设置为"可分配的",并在从文件中读取size atomcount后分配它们。也没有必要显式地在各个过程之间传递数组的维度…
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;
}
这并不处理输入文件中的损坏数据,但它是一个起点。
- 将指向 1D Fortran 数组的指针传递给使用 C_LOC() 进行C++会导致垃圾值
- 将分配给C++数组传递给 Fortran 子例程
- 通过矢量下标访问 Fortran 数组,相当于 cpp
- 将数组从 Fortran 传递到C++时未定义的引用
- 将字符串数组从fortran传递到C/C DLL,并获取具有更改值的数组
- 将fortran生成的二进制文件读取到C++中的带符号整数数组中
- 如何将字符串数组从C和Fortran传递到Fortran
- 在C++和Fortran代码之间传递复数数组
- 为什么值放置在 fortran 函数的数组中,而在调用 c++ 函数中不存在
- C++是否有类似于 Fortran 冒号 A[2][:] 的数组占位符?
- 将 char 数组从 C++ 传递到 Fortran
- 将数组从C/C++传递给Fortran,并返回一个计算的数组
- 将C++数组传递给Fortran子例程会导致nan值出现在结果中
- C++中Fortran风格的多维数组
- 为fortran程序员在c++中传递多维数组
- 将数组从fortran传递给c++函数
- 从传入的FORTRAN数组生成CUSP coo_matrix
- 将C++字符数组传递给Fortran
- 如何使用SWIG将Fortran有序的2d numpy数组传递到c ++中
- Fortran 将字符*81 数组传递给 C/C++ 代码