Вы очень близки, вам просто нужно проверить свой ввод в перегруженных функциях оператора, и не использовать new
!, вместо этого просто используйте std::vector<XYZ_frame_read> frames;
Например, с вашей перегрузкойistream
для class XYZ_frame_read
все, что вам нужно:
friend std::istream& operator>>(std::istream& in, XYZ_frame_read &traj)
{
/* validate that num_particles and curr_frame read */
if (in >> traj.num_particles >> traj.curr_frame) {
int n = traj.num_particles; /* set number of particles to read */
Particle p;
while (n-- && (in >> p)) /* read that number of particles */
traj.coordinates_t.push_back(p);
}
return in;
}
Затем в main()
вместо выделения с new
для frames
, как вы делаете здесь:
XYZ_frame_read* frames = new XYZ_frame_read[3];
in >> frames[0];
std::cout << frames[0];
просто используйте std::vector<XYZ_frame_read> frames;
, а затем используйте временный class XYZ_frame_read
, чтобы проверить чтение перед добавлением его в вектор кадров, например,
std::vector<XYZ_frame_read> frames; /* vector of frames (NO new!) */
for (;;) { /* continual loop while good input */
XYZ_frame_read tmp; /* temp XYZ_frame_read for read */
if ((in >> tmp)) /* if read is good */
frames.push_back(tmp); /* add it to vector of frames */
else
break; /* otherwise -- bail */
}
Для вывода просто используйтепетля с автонастройкой for
, например
for (auto & f : frames) /* auto-ranged for loop to output frames */
std::cout << "\nframe: " << f.get_frame() <<
" particles: " << f.get_nparticles() << "\n\n" <<
f << '\n';
В целом, вы получите:
#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)
{
/* validate that num_particles and curr_frame read */
if (in >> traj.num_particles >> traj.curr_frame) {
int n = traj.num_particles; /* set number of particles to read */
Particle p;
while (n-- && (in >> p)) /* read that number of particles */
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 get_frame(void) { return curr_frame; }
int get_nparticles (void) { return num_particles; }
int getpsize(void) { return coordinates_t.size(); }
};
int main(int argc, char *argv[]) {
std::ifstream in(argv[1]);
std::vector<XYZ_frame_read> frames; /* vector of frames (NO new!) */
for (;;) { /* continual loop while good input */
XYZ_frame_read tmp; /* temp XYZ_frame_read for read */
if ((in >> tmp)) /* if read is good */
frames.push_back(tmp); /* add it to vector of frames */
else
break; /* otherwise -- bail */
}
for (auto & f : frames) /* auto-ranged for loop to output frames */
std::cout << "\nframe: " << f.get_frame() <<
" particles: " << f.get_nparticles() << "\n\n" <<
f << '\n';
return 0;
(void)argc; /* suppress -Wunused warning */
}
Существует огромное количество преимуществ использования vector
для class XYZ_frame_read
вместо выделения с new
.Автоматическое управление памятью - это только верхушка айсберга.
Пример входного файла
Использование вашего примера ввода:
$ cat particles.txt
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
Пример Использование / Вывод
Просто укажите имя файла, и ваш std::vector<XYZ_frame_read> frames
будет автоматически заполнен, независимо от того, сколько кадров присутствует в вашем файле данных (до пределов вашей виртуальной памяти)
$ ./bin/paticle particles.txt
frame: 0 particles: 5
1.23 2.33 4.56
1.23 2.33 5.56
1.23 2.33 6.56
1.23 2.33 7.56
1.23 2.33 8.56
frame: 1 particles: 5
2.23 2.33 4.56
2.23 3.33 5.56
2.23 4.33 6.56
2.23 5.33 7.56
2.23 6.33 8.56