0

我目前正在尝试将字符读入一个看起来像这样的类

 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 的大小并退出循环。但是我在编译和运行时遇到了问题,它似乎将错误的元素放入了错误的对象成员中。

有任何想法吗?

4

2 回答 2

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迭代器从流复制到向量,但恕我直言,简单明了是好的)

于 2013-12-17T00:53:36.010 回答
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_cast要么std::istringstream

  • 升压方式

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

  • 数据绑定(到 xml、jason、ini...)

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

  • Python !

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

PS:附件(带boost::serialization)取自文档:

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

于 2013-12-17T00:36:01.630 回答