在 C++ 中传递多维数组对于 Fortran 程序员
我习惯用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];
}
}
I am used to writing programs in Fortran (this is f90), but I need to write a program in C++. I am very confused on how to pass a multidimensional array from a C++ function. To give an example, I want to read a list of atomic coordinates in XYZ format in a subroutine and then pass the coordinates to the main program.
Here it is in 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
The test file read here is a very simple CO2 molecule:
3
C 0.0 0.0 0.0
O -1.4 0.0 0.0
O 1.4 0.0 0.0
So I need to do this same procedure in C++ and the part that seems
most confusing is reading the coordinates into a multidimensional
array and then passing the array back to the main program.
Here's the C++ (this has errors) -- Any help would be greatly appreciated!
#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];
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请注意,
charatoms[MAXATOM][2];
,但在循环中写入atoms
时,您没有给出足够的索引:stream>>>原子[i] //...
Note that
char atoms[MAXATOM][2];
but you're not giving enough indices when writing intoatoms
in your loop:stream >> atoms[i] //...
目的是从文件中读取数组的实际长度吗?我从 Fortran 中猜测:
如果是这样,最好使数组长度可变,而不是猜测最大长度(1000)。如果你的猜测太小会发生什么?这在 Fortran >=90 或 C++ 中都很容易做到。在 Fortran 中,使数组“可分配”,并在从文件中读取大小 atomcount 后分配它们。也没有必要在各个过程之间显式传递数组维度......
Is the intent to read the actual length of the array from the file? I'm guessing from the Fortran:
If so it would be better to make the array variable length instead of guessing a maximum length (1000). What happens if your guess is too small? Which is easy to do in either Fortran >=90 or C++. In Fortran make the arrays "allocatable" and allocate them after reading the size atomcount from the file. Nor is it necessary to explicitly pass the array dimensions between the various procedures...
双& coord[][3]
是一个二维引用数组,如果可以编译的话,有一个固定维度和一个未定义维度。可能不是你想要的。被调用的函数将无法在运行时确定未知维度的大小。当您在 C++ 中传递多维数组时,在幕后传递的只是指向第一个元素的指针。因此,要在任意尺寸的任何地方工作,您可以传递指针和任何尺寸作为额外参数:
您还没有详细说明在阅读信息后将如何处理该信息,所以我不知道如果数据必须存储为多维数组以供进一步处理。就我个人而言,我会将其存储为
Atom
对象的向量,并且只使用 C++ I/O 而不是混合 C(以f
开头的函数)和 C++(以withstream
):这不会处理输入文件中损坏的数据,但它是一个起点。
double& coord[][3]
is a two-dimensional array of references, with one fixed dimension and one undefined dimension, if it even compiles. Might not be what you want. The called function will not be able to determine the unknown dimension's size at runtime.When you pass a multi-dimensional array in C++, under the hood all that is passed is a pointer to the first element. So, to work everywhere with arbitrary dimensions, you pass the pointer, and any dimensions as extra parameters:
You haven't gone into detail as to what you'll do with the information after you've read it, so I have no idea if the data must be stored as a multi-dimensional array for further processing. Personally, I would store this as a vector of
Atom
objects, and would just use C++ I/O instead of mixing C (functions starting withf
) and C++ (classes ending withstream
):This doesn't handle corrupt data in the input file, but it's a starting point.