我想将一串数字解析为元素向量。该字符串由四个数字组成,由( ) : /
分隔,每个块由;
分隔。
具体来说,字符串采用以下格式:int(int):float/float;
,请参阅下面的代码示例。我想我可以使用正则表达式,但由于数据是如此结构化,我确信必须有一种更平易近人且更容易解析这种字符串的方法。我使用istringstream,但感觉有点笨拙。
std::string line = "0(0):0/0;1(2):0.01/0.02;2(4):0.02/0.04;3(6):0.03/0.06;"
struct Element {
int a;
int b;
int c;
int d;
};
std::vector<Element> = parse(line);
std::vector<Element> parse(std::string line)
{
std::vector<Element> elements;
std::istringstream iss(line);
while(iss) {
char dummy;
Element element;
iss >> element.a;
iss.read(&dummy,sizeof(dummy)); // (
iss >> element.b;
iss.read(&dummy,sizeof(dummy)); // )
iss.read(&dummy,sizeof(dummy)); // :
iss >> element.c;
iss.read(&dummy,sizeof(dummy)); // /
iss >> element.d;
iss.read(&dummy,sizeof(dummy)); // ;
if (!iss) {break;}
elements.push_back(element);
}
return elements;
}
我的问题:
std::stringstream
并按号码读取数字并且&#39;砍掉&#39;两者之间的人物?正如在代码示例中所做的那样?while(iss)
仍然为真。如何在每个{{1}之后终止此循环而不进行测试}?或者更一般地说,如何从istringstream循环提取?答案 0 :(得分:1)
您的数据结构合理,您可以轻松地重载operator>>
以从std::ifstream
中提取类成员,然后继续从istringstream
或文件流中读取它们。
这是一个可能的实现:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <iterator>
#include <stdexcept>
class Element
{
public:
Element() {}
Element(int aa, int bb, float cc, float dd) : a{aa}, b{bb}, c{cc}, d{dd} {}
friend std::istream &operator>> (std::istream &in, Element &e);
friend std::ostream &operator<< (std::ostream &out, Element const &e);
private:
int a;
int b;
float c;
float d;
};
std::istream &operator>> (std::istream &in, Element &e)
{
char delimiter;
if ( not ( in >> e.a >> delimiter and delimiter == '(' and
in >> e.b >> delimiter and delimiter == ')' and
in >> delimiter and delimiter == ':' and
in >> e.c >> delimiter and delimiter == '/' and
in >> e.d >> delimiter and delimiter == ';' )
and not in.eof() )
{
in.setstate(std::ios_base::failbit);
}
return in;
}
std::ostream &operator<< (std::ostream &out, Element const &e)
{
return out << e.a << '(' << e.b << "):" << e.c << '/' << e.d << ';';
}
std::vector<Element> read_Elements_from(std::istream &in)
{
std::vector<Element> tmp (
std::istream_iterator<Element>{in},
std::istream_iterator<Element>{}
);
if ( not in.eof() )
throw std::runtime_error("Wrong format");
return tmp;
}
int main()
{
try
{
using std::cout;
std::istringstream iss {
"0(0):0/0;1(2):0.01/0.2;2(4):0.02/0.04;3(6):0.03/0.06;"
};
auto els_s = read_Elements_from(iss);
cout << "Elements read from the string:\n";
for ( auto const &i : els_s )
{
cout << i << '\n';
}
// assuming a file which lines are similar to the string provided
std::ifstream input_file {"input_data.txt"};
if ( not input_file )
throw std::runtime_error("Can't open input file");
auto els_f = read_Elements_from(input_file);
cout << "\nElements read from the file:\n";
for ( auto const &i : els_f )
{
cout << i << '\n';
}
}
catch ( std::exception const &e )
{
std::cerr << "\nAn unexpected problem cause this application to end:\n\n"
<< e.what() << ".\n\n";
return EXIT_FAILURE;
}
}