首页 > 解决方案 > 使用 OOP 有效地处理和读取轨迹文件

问题描述

我正在编写一个代码来读取大型 .xyz 文件。这些类型的文件对于像 VMD 这样的分子动力学可视化工具很有用。所以文件格式看起来像这样

#Number of particles
#frame number
#Coordinates

举个例子:

5
0
C    1.23    2.33    4.56
C    1.23    2.33    5.56
C    1.23    2.33    6.56
C    1.23    2.33    7.56
C    1.23    2.33    8.56
5
1
C    2.23    2.33    4.56
C    2.23    3.33    5.56
C    2.23    4.33    6.56
C    2.23    5.33    7.56
C    2.23    6.33    8.56

等等。我试图在这里理解这篇文章https://codereview.stackexchange.com/questions/201743/processing-xyz-data-from-a-large-file讨论使用运算符重载方法从大型数据集中有效读取。我正在尝试编写一个可以读取如此大的轨迹文件并给我以下输出的类:1)粒子数 2)帧总数 3)每个时间步的坐标集。因此,我尝试根据这篇文章写下以下内容,以读取上述文件格式。到目前为止,下面的代码能够读取单个帧并在此之后退出。

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

struct Particle{

    long double x,y,z;
    char tab ='\t';
    char newline = '\n';
    char atom ;
    friend std::istream& operator>>(std::istream& in, Particle &xyz) {
        in >> xyz.atom >> xyz.x >> xyz.y >> xyz.z ;
        return in;
    }
    friend std::ostream& operator<<(std::ostream& out, Particle &xyz){
        out << xyz.x << xyz.tab << xyz.y << xyz.tab << xyz.z << xyz.newline;
        return out;
    }
};
class XYZ_frame_read
{

    int curr_frame;
    int num_particles;
    std::vector<Particle> coordinates_t;

    public:

    friend std::istream& operator>>(std::istream& in, XYZ_frame_read &traj ){

                in >> traj.num_particles;
                in >> traj.curr_frame;
                Particle p;
                while(in >> p){
                    traj.coordinates_t.push_back(p);
                }
            return in;
        }
    friend std::ostream& operator<<(std::ostream& out, XYZ_frame_read &traj){

            for(int i = 0; i< traj.num_particles ;i ++){
                out << traj.coordinates_t.at(i) ;
            }
            return out;
        }
};

int main(int argc, char *argv[]){

    std::ifstream in(argv[1]);
    XYZ_frame_read* frames = new XYZ_frame_read[3];
    in >> frames[0];
    std::cout << frames[0];

    return 0;
}

问题是我不明白我将如何实现此方法来读取下一帧并继续将它们附加到coordinates_t每个 object 实例的向量中XYZ_frame_read。我想我明白这是如何工作的,显然 awhile(!in.eof())是毫无疑问的,因为它只会一遍又一遍地读取第一帧。我是 C++ 的新手,正在从事与分子动力学相关的项目,欢迎提出任何更改/建议!感谢您的帮助!

编辑

我试过使用

size_t i = 0;
while(in >> frames[i]){
    std::cout << frames[i];
    if(i == 3){
        break;
    }
    i++;
}

它返回空白。它不起作用。循环甚至没有被执行。

标签: c++performanceoopifstream

解决方案


while(!in.eof())是不可能的,因为eof不像那样工作。

为什么循环条件内的 iostream::eof(即 `while (!stream.eof())`)被认为是错误的?

我不确定我看到了问题,有什么问题

size_t i = 0;
while (in >> frames[i])
    ++i;

(除了数组边界错误的可能性)。

编辑

此代码不正确

 friend std::istream& operator>>(std::istream& in, XYZ_frame_read &traj) {
     in >> traj.num_particles;
     in >> traj.curr_frame;
     Particle p;
     while(in >> p){
          traj.coordinates_t.push_back(p);
     }
     return in;
 }

这表示继续读取粒子,直到读取失败。这是不正确的,你知道有多少粒子。它应该说继续阅读粒子,直到您阅读num_particles它们(或阅读失败)。即应该说

 friend std::istream& operator>>(std::istream& in, XYZ_frame_read &traj) {
     in >> traj.num_particles;
     in >> traj.curr_frame;
     Particle p;
     for (int i = 0; i < traj.num_particles && in >> p; ++i) 
          traj.coordinates_t.push_back(p);
     }
     return in;
 }

推荐阅读