在C 中解析期间的象征性文本,新手的磨难
Tokenizing text during parsing in C++, a newbies ordeal
我有一个文本文件,其中包含一些我需要解析的信息,然后放入适当的数组般的结构(我猜这些是向量,在C 中)。
我要解析的文本文件包含我想忽略的双打,int和Whiteves。
我在Python方面有一定的经验,而Python将使用split()方法。
在C 中,我可以使用Boost令牌或许多其他集合工具。我尝试了许多此类方法,但是根据我的最佳尝试,我最终得到了这样的数字" -97.653632.431542",我什至不知道C 如何允许两个小数点。(我知道问题是我的经验不足,而不是C !)
所以现在就好东西了。首先,让我们定义文本文件的内容,其中包含可变数量的Whitespaces,因此我将在开始时放上几行以进行插图,并在开始时包含X数字(我知道我可以摆脱使用boost::trim_left()
,但是为了示例完整性,我想在此处包括它们)。
注意:我可以使用我想要的任何库,但是如果可能使用C 常见的任何其他库的实用解决方案,因此我也可以学习如何以更实际的方式进行操作。
文本文件内容:
FILE_DESCRIPTION
523459 45267393
1 -91.1960210000 30.4248000000 6.9067078000
2 -91.1936990000 30.4238730000 0.2607690100
3 -91.1983420000 30.4257270000 11.4345030000
4 -91.2006640000 30.4266540000 8.2591810000
5 -91.2029850000 30.4275810000 2.2204340000
6 -91.2043510000 30.4258950000 3.0012660000
7 -91.1962610000 30.4231880000 13.4529710000
8 -91.1941710000 30.4215120000 7.8915730000
现在解析文件的代码:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
class myParserClass{
public:
std::string path;
std::vector<int> NODE_INDEX;
std::vector<double> X, Y, Z;
std::string DESCRIPTION;
int NE, NP;
myParserClass(){};
myParserClass(std::string path){
parse_file(path)};
void parse_fort14(std::string path){
std::ifstream filei(path.c_str());
std::string DESCRIPTION;
getline(filei, DESCRITION);
this->DESCRIPTION=DESCRIPTION;
int NP, NE;
stream >> NE >> NP;
this->NE=NE;
this->NP=NP;
stream.str("");
stream.clear();
for(int x=0, x=NP, x++){
// I'm having trouble here....
this->NODE_INDEX=NODE_INDEX.push_back(node_index);
this->X=X.push_back(x);
this->Y=Y.push_back(y);
this->Z=Z.push_back(z);};
};
int main (){myParserClass myInfo("/path/to/myInfo.txt");}
编码样式评论也受到欢迎,因为我在C 上是如此新,并且一切都很粗糙。请注意,我已经从示例中脱掉了文件打开检查语句,而while {} eof语句为简单起见。
编辑1:因此,看起来之前发生的事情是相关的。我已经编辑了上面的问题,以反映同一问题的更准确版本。
您已经拥有"典范C "方法。这是使用Boost Spirit Qi的演示:
活在coliru
#include <fstream>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
struct Fort14 {
std::string description;
int n_edges, n_points;
struct Point { double x,y,z; };
std::vector<Point> points;
};
BOOST_FUSION_ADAPT_STRUCT(Fort14::Point, x, y, z)
BOOST_FUSION_ADAPT_STRUCT(Fort14, description, n_edges, n_points, points)
Fort14 parse_fort14(std::istream& is) {
using It = boost::spirit::istream_iterator;
using namespace boost::spirit::qi;
rule<It, std::string()> description = *(char_ - eol);
It f(is >> std::noskipws), l;
Fort14 data;
if (phrase_parse(f, l,
description >> eol >>
int_ >> int_ >> eol >> // NE, NP
(omit[int_] >> auto_) % eol, // point data
blank, data))
{
return data;
}
auto frag = f;
for (int i = 10; i>0 && frag!=l; --i)
++frag;
throw std::runtime_error("Parse error at " + std::string(f, frag) + "...");
}
int main() {
std::ifstream ifs("input.txt");
auto parsed = parse_fort14(ifs);
std::cout << "Description: '" << parsed.description << "'n";
std::cout << "n_edges: " << parsed.n_edges << "n";
std::cout << "n_points: " << parsed.n_points << "n";
for (auto& p : parsed.points)
std::cout << " - point { " << p.x << ", " << p.y << ", " << p.z << " }n";
}
打印
Description: 'FILE_DESCRIPTION'
n_edges: 523459
n_points: 45267393
- point { -91.196, 30.4248, 6.90671 }
- point { -91.1937, 30.4239, 0.260769 }
- point { -91.1983, 30.4257, 11.4345 }
- point { -91.2007, 30.4267, 8.25918 }
- point { -91.203, 30.4276, 2.22043 }
- point { -91.2044, 30.4259, 3.00127 }
- point { -91.1963, 30.4232, 13.453 }
- point { -91.1942, 30.4215, 7.89157 }
我做了一些假设,但不是太多(您没有解释任何输入格式...)。NE/NP可能是"边缘数,点数"的缩写(实际上没有线索)。
请注意
如果要验证点的索引依次增加,则可以:
(omit[int_(boost::phoenix::ref(counter)++)] >> auto_) % eol,
如果您想完全接受 n 点(例如
n_points
或您的'np'),请写repeat(n_points) [omit[int_] >> auto_ >> eol],
请参阅两个组合 live live live coliru (在其中仅读取6个点,因为 n_points
是6)。
如果文件内容在每一行中具有相同的格式(int,double,double,double),则可以将流操作员使用:
int no;
double d1, d2, d3;
filei >> no >> d1 >> d2 >> d3;
和读取整个文件,一个简单的循环就足够了:
int main()
{
std::ifstream filei("/path/to/myInfo.txt");
int no;
double d1, d2, d3;
while (filei >> no >> d1 >> d2 >> d3) {
// do something with data
}
}
不需要花哨的解析。
将行数据合并在一起,您可以使用结构并使用这些结构的向量:
struct row {
int no;
double x, y, z;
};
std::vector<row> rows;
// ...
row r;
while (filei >> r.no >> r.d1 >> r.d2 >> r.d3) {
rows.push_back(r);
}
下一步可能是为行结构实现流操作员:
std::istream &operator>>(std::istream &f, row &r)
{
return f >> r.no >> r.d1 >> r.d2 >> r.d3;
}
并在循环中使用它:
row r;
while (filei >> r) {
rows.push_back(r);
}
当您想读取给定数量的行时,例如NP
行:
for (int i = 0; i < NP; ++i) {
// read and process line
}
尽管这是C 101,您应该从书或在线资源中学习。
- 文本文件中的单词链表
- 从命令行c++发送文本文件名
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 2D数组来自文本输入,中间有空格
- 如何将内容数组写入文本文件?
- 无法通过空白将文本文件行分隔为矢量
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- C++将文本文件中的数据读取到结构数组中
- 在指针的帮助下,文本文件中单词的频率
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 将值从二维数组输出到文本文件
- 如何在c++中从文本文件中逐行读取整数
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 从文本文件中读取时钟时间和事件时间并进行处理
- 如何从文本文件中读取值和数组
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何根据单词在文本中出现的概率输出单词
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- C++试图读取一个文件并输出到另一个文本文件
- 在C 中解析期间的象征性文本,新手的磨难