使用 getline 解析文本文件并将每行的一部分分配给数组中的不同变量
Parsing text file using getline and assigning parts of each line to different variables in an array
我正在用 C++ 编写一个程序,我想用它读取和解析 (.pdb) 文本文件中的行。
这些行看起来像这样:
ATOM # CHAR 0 FLOAT1 FLOAT2 FLOAT3 1.00 0.00 CHAR
其中 # 是整数(原子编号),CHAR 是原子符号(在本例中为 O 或 Si)。 FLOATs分别是x、y、z坐标。
前三行是:
ATOM 1 O 0 0.024 8.489 10.490 1.00 0.00 O
ATOM 2 O 0 10.069 1.380 9.223 1.00 0.00 O
ATOM 3 O 0 20.066 11.249 2.652 1.00 0.00 O
到目前为止,我已经设法逐行阅读文本并使用 sscanf
扫描内容。但是,我无法将数据存储到我创建的 Atom class
数组中。这是包含在我的 header 文件中的 class 的样子:
class Atom {
public:
Atom()
{};'
int atom_num;
char atom_sym[2];
float atom_x, atom_y, atom_z;
};
这是我解析行的程序部分:
int main()
{
int i;
int Linecount = 0;
char ign_a, ign_t, ign_o, ign_m; // I use these to store the ATOM of each line
int ign1; // I use this to store the 0 that appears before the coordinates of each line
std::string filename = "textfile.pdb"
std::ifstream file;
file.open (filename.c_str());
if (file.is_open()) {
std::string line;
while (getline(file, line))
++Linecount;
}
file.close();
Atom atomList[Linecount];
file.open (filename.c_str());
if (file.is_open()) {
std::string line;
int atom_num;
char atom_sym[2];
float atom_x, atom_y, atom_z;
for (i = 1; i < Linecount; ++i) { // I have tried this for loop in different sections of the program but nothing seems to work
while (getline(file, line)) {
if (line.find("ATOM") == 0) {
sscanf(line.c_str(), "%c%c%c%c %d %s %d %f %f %f", &ign_a, &ign_t, &ign_o, &ign_m,
&atom_num, atom_sym, &ign1, &atom_x, &atom_y, &atom_z); //
atomList[i].atom_num = atom_num; // This is where I attempt to store the data into the array
strcpy(atomList[i].atom_sym, atom_sym);
atomList[i].atom_x = atom_x;
atomList[i].atom_y = atom_y;
atomList[i].atom_z = atom_z;
}
printf("%d %s %.3f %.3f %.3f\n", atomList[i].atom_num, atomList[i].atom_sym,
atomList[i].atom_x, atomList[i].atom_y, atomList[i].atom_z); // Test parsing of lines
}
}
file.close();
int j = 10;
printf("TEST: %d %s %.3f %.3f %.3f\n", atomList[j].atom_num, atomList[j].atom_sym,
atomList[j].atom_x, atomList[j].atom_y, atomList[j].atom_z); // Print function to test storing into array
return 0;
}
尽管使用了 if (line.find("ATOM") == 0)
语句,但第一个打印函数似乎可以正常工作,尽管它打印了三行 "garbage" 行,我认为这是由于文本文件的 header 造成的。这是直到第三行的输出:
0 0.000 0.000 0.000
0 0.000 0.000 0.000
0 0.000 0.000 0.000
1 O 0.024 8.489 10.490
2 O 10.069 1.380 9.223
3 O 20.066 11.249 2.652
但是,第二个打印函数仅打印零值,这表明数据未正确存储到数组中。我也尝试过使用 std::cin
和 std::cout
来分配和打印数据,但这似乎没有帮助。这是第二个打印函数的输出:
TEST: 0 0.000 0.000 0.000
我的主要问题是我无法将输入文件中的数据存储到 class Atom 的数组 atomList[i] 中。我试过移动 for 循环以及直接扫描到 atomList[i] 变量等,但我被困在了这一点上。我需要更改什么才能逐行读取并将正确的信息存储到数组中?
如有任何帮助,我将不胜感激。谢谢!
不确定这是否会回答您的任何问题,但这里有一种方法可以做到。它不使用任何旧的 C 类型习语,如 scanf
和原始数组。
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
// Overloaded extraction operator
std::istream& operator>>(std::istream& i, Atom& a)
{
std::string temp;
int temp2;
if (i >> temp
>> a.atom_num
>> a.atom_sym
>> temp2
>> a.atom_x
>> a.atom_y
>> a.atom_z) {
i.ignore(256, '\n'); // Discard rest
}
return i;
}
// Overloaded insertion operator
std::ostream& operator<<(std::ostream& o, const Atom& a)
{
o << a.atom_num << " "
<< a.atom_sym << " "
<< std::setprecision(3) << a.atom_x << " "
<< std::setprecision(3) << a.atom_y << " "
<< std::setprecision(3) << a.atom_z;
return o;
}
int main()
{
std::string filename = "textfile.pdb";
std::ifstream file(filename);
std::vector<Atom> atomList;
if (file) {
std::string line;
while (std::getline(file, line)) {
if (line.find("ATOM") == 0) {
std::stringstream ss(line);
Atom temp;
if (ss >> temp) {
atomList.push_back(temp);
}
}
}
}
if (atomList.size() > 10) {
std::cout << atomList[10] << '\n';
}
return 0;
}
我正在用 C++ 编写一个程序,我想用它读取和解析 (.pdb) 文本文件中的行。 这些行看起来像这样:
ATOM # CHAR 0 FLOAT1 FLOAT2 FLOAT3 1.00 0.00 CHAR
其中 # 是整数(原子编号),CHAR 是原子符号(在本例中为 O 或 Si)。 FLOATs分别是x、y、z坐标。
前三行是:
ATOM 1 O 0 0.024 8.489 10.490 1.00 0.00 O
ATOM 2 O 0 10.069 1.380 9.223 1.00 0.00 O
ATOM 3 O 0 20.066 11.249 2.652 1.00 0.00 O
到目前为止,我已经设法逐行阅读文本并使用 sscanf
扫描内容。但是,我无法将数据存储到我创建的 Atom class
数组中。这是包含在我的 header 文件中的 class 的样子:
class Atom {
public:
Atom()
{};'
int atom_num;
char atom_sym[2];
float atom_x, atom_y, atom_z;
};
这是我解析行的程序部分:
int main()
{
int i;
int Linecount = 0;
char ign_a, ign_t, ign_o, ign_m; // I use these to store the ATOM of each line
int ign1; // I use this to store the 0 that appears before the coordinates of each line
std::string filename = "textfile.pdb"
std::ifstream file;
file.open (filename.c_str());
if (file.is_open()) {
std::string line;
while (getline(file, line))
++Linecount;
}
file.close();
Atom atomList[Linecount];
file.open (filename.c_str());
if (file.is_open()) {
std::string line;
int atom_num;
char atom_sym[2];
float atom_x, atom_y, atom_z;
for (i = 1; i < Linecount; ++i) { // I have tried this for loop in different sections of the program but nothing seems to work
while (getline(file, line)) {
if (line.find("ATOM") == 0) {
sscanf(line.c_str(), "%c%c%c%c %d %s %d %f %f %f", &ign_a, &ign_t, &ign_o, &ign_m,
&atom_num, atom_sym, &ign1, &atom_x, &atom_y, &atom_z); //
atomList[i].atom_num = atom_num; // This is where I attempt to store the data into the array
strcpy(atomList[i].atom_sym, atom_sym);
atomList[i].atom_x = atom_x;
atomList[i].atom_y = atom_y;
atomList[i].atom_z = atom_z;
}
printf("%d %s %.3f %.3f %.3f\n", atomList[i].atom_num, atomList[i].atom_sym,
atomList[i].atom_x, atomList[i].atom_y, atomList[i].atom_z); // Test parsing of lines
}
}
file.close();
int j = 10;
printf("TEST: %d %s %.3f %.3f %.3f\n", atomList[j].atom_num, atomList[j].atom_sym,
atomList[j].atom_x, atomList[j].atom_y, atomList[j].atom_z); // Print function to test storing into array
return 0;
}
尽管使用了 if (line.find("ATOM") == 0)
语句,但第一个打印函数似乎可以正常工作,尽管它打印了三行 "garbage" 行,我认为这是由于文本文件的 header 造成的。这是直到第三行的输出:
0 0.000 0.000 0.000
0 0.000 0.000 0.000
0 0.000 0.000 0.000
1 O 0.024 8.489 10.490
2 O 10.069 1.380 9.223
3 O 20.066 11.249 2.652
但是,第二个打印函数仅打印零值,这表明数据未正确存储到数组中。我也尝试过使用 std::cin
和 std::cout
来分配和打印数据,但这似乎没有帮助。这是第二个打印函数的输出:
TEST: 0 0.000 0.000 0.000
我的主要问题是我无法将输入文件中的数据存储到 class Atom 的数组 atomList[i] 中。我试过移动 for 循环以及直接扫描到 atomList[i] 变量等,但我被困在了这一点上。我需要更改什么才能逐行读取并将正确的信息存储到数组中?
如有任何帮助,我将不胜感激。谢谢!
不确定这是否会回答您的任何问题,但这里有一种方法可以做到。它不使用任何旧的 C 类型习语,如 scanf
和原始数组。
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
// Overloaded extraction operator
std::istream& operator>>(std::istream& i, Atom& a)
{
std::string temp;
int temp2;
if (i >> temp
>> a.atom_num
>> a.atom_sym
>> temp2
>> a.atom_x
>> a.atom_y
>> a.atom_z) {
i.ignore(256, '\n'); // Discard rest
}
return i;
}
// Overloaded insertion operator
std::ostream& operator<<(std::ostream& o, const Atom& a)
{
o << a.atom_num << " "
<< a.atom_sym << " "
<< std::setprecision(3) << a.atom_x << " "
<< std::setprecision(3) << a.atom_y << " "
<< std::setprecision(3) << a.atom_z;
return o;
}
int main()
{
std::string filename = "textfile.pdb";
std::ifstream file(filename);
std::vector<Atom> atomList;
if (file) {
std::string line;
while (std::getline(file, line)) {
if (line.find("ATOM") == 0) {
std::stringstream ss(line);
Atom temp;
if (ss >> temp) {
atomList.push_back(temp);
}
}
}
}
if (atomList.size() > 10) {
std::cout << atomList[10] << '\n';
}
return 0;
}