将文本文件存储到类中

时间:2013-12-17 00:06:34

标签: c++ algorithm parsing vector istringstream

我目前正在尝试将字符读入类似

的类中
 struct data {
    string segment; string name;
    double length; double radius; double wall_thickness;
    double young_modulus; double compliance;

};

我还有一个包含以下元素的向量:

  2A
  Aorta_Ascendens
  2
  1.47
  .164
  4
  53.4
  2B
  Aorta_Ascendens
  2
  1.44
  .161
  4
  51.0
  3A

我想在文本文件中读入每个部分,目前这是我的算法,可以连续读取文本文件并分别添加每个部分。

int place = 0;

        while (place != temp_data.size()){
            int counter = 0;
            for (counter; counter <= 7; ++counter){
                istringstream is(temp_data[place + counter]);

                if (counter == 0){ is >> a.segment; }
                if (counter == 1){ is >> a.name; }
                if (counter == 2){ is >> a.length; }
                if (counter == 3){ is >> a.radius; }
                if (counter == 4){ is >> a.wall_thickness; }
                if (counter == 5){ is >> a.young_modulus; }
                if (counter == 6){ is >> a.compliance; }

            }
            counter = counter - 1;     //since the next segment is at    temp_data[7], must subtract one to have place = 7.
            place = counter + place;

            v.push_back(a);
        }

我遇到的问题是试图找到一种方法来确保文本的正确部分进入对象的正确部分。对于前七行文本,对象应该是这样的:

segment: 2A
name: Aorta_Ascendens
length: 2
radius: 1.47
wall_thickness: .164
young modulus: 4
compliance: 53.4

这应该对整个文本文件重复相同的方式。 temp_data是一个包含需要添加到对象中的元素的向量,但我找不到一个好的方法来连续循环向量并将元素放到正确的位置。

我制作的算法有一个计数器和一个占位符,计数器将循环通过矢量点,占位符将保留第一个对象的数据成员的点,在这种情况下是段。在算法结束时,place应该等于temp_data的大小并离开循环。但是在编译和运行时遇到问题,似乎是将错误的元素放入错误的对象成员中。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

一种简单,干净的方法是编写自定义流媒体操作符:

struct data {
    string segment; string name;
    double length; double radius; double wall_thickness;
    double young_modulus; double compliance;

    friend std::istream& operator>>(std::istream& is, data& d)
    {
        return is >> d.segment >> d.name >> d.length >> d.radius >> d.wall_thickness
                  >> d.young_modulus >> d.compliance;
    }
};

temp_dataistringstreamcounter

要使用它:

data d;
while (input_stream >> d)
    v.push_back(d);
if (input_stream.fail())
    ...print error / exit or whatver...
else
    ...use v...

(有更多声明性的方法可以使用标准算法和back_inserter迭代器从流复制到向量,但恕我直言简单明了很好)

答案 1 :(得分:0)

  • 手动方法

您可以使用更经典的方法在文件格式中使用映射(即,如果您可以访问文件的规范(内容))。

您已经提供了文本应该是什么样子的完美示例:

segment: 2A
name: Aorta_Ascendens
length: 2
radius: 1.47
wall_thickness: .164
young modulus: 4
compliance: 53.4

该格式有什么问题? 因此,它可以提供更好的灵活性(安全性),因为您可以确定某个成员是您希望阅读的内容。 您可以使用分隔符分隔对象:

segment: 2A
name: Aorta_Ascendens
length: 2
radius: 1.47
wall_thickness: .164
young modulus: 4
compliance: 53.4
**@**
segment: 2B
name: Aorta_Ascendens
length: 3
radius: 1.00
wall_thickness: .164
young modulus: 4
compliance: 53.4

使用ifstream.readlines()获取C ++样式字符串数组,这将帮助您使用find()函数进行解析(如果未找到则返回string::npos。)
在Parse()函数中,它涉及迭代文件的行, 首先,使用find查找:字符,使用substr取左部分来检查分配值的成员(以及如何解析,整数,枚举?...)和另一个substr进行一些计算(例如size - posfound)以取得正确的部分,然后将其放入您选择的lexical_cast中。 boost::lexial_caststd::istringstream

  • 提升方式

否则,您可以选择使用boost::serialization,这样您只能编写一个超级简单函数来读取这种格式。 (参见附件)

  • 数据绑定(对xml,jason,ini ...)

或更复杂的数据绑定框架,如Code Synthesis XSD(Xerces?):
http://www.codesynthesis.com/products/xsd/

  • Python!

更简单,使用python。你只需做eval()

PS:附件(boost::serialization)取自doc:

class gps_position
{
private:
    friend class boost::serialization::access;
    // When the class Archive corresponds to an output archive, the
    // & operator is defined similar to <<.  Likewise, when the class Archive
    // is a type of input archive the & operator is defined similar to >>.
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;
public:
    gps_position(){};
    gps_position(int d, int m, float s) :
        degrees(d), minutes(m), seconds(s)
    {}
};
是不是简单愚蠢?并保证工作。 (只要您使用相同的序列化程序编写文件) 参考http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html

相关问题