从文件中读取数据并填写STL向量

时间:2012-06-26 05:33:20

标签: c++ stl

struct DataValue
{
    DataValue() : uiQuality(0) {} // Here 0 stands for good.
    unsigned int    uiQuality;
    std::string     timeChanged;
    float           value;
};

std::vector<DataValues> myDataValues

在我的应用程序中的某个时刻,我的向量中的数据被填充。我正在使用下面的文件写一个文件。

std::ofstream myfile("myData.txt", std::ios::app);

for (int j = 0; j < myDataValues.size(); j++)
{
    std::string quality;
    if(myDataValues[j].quality == 0) {
        quality = "good";
    }
    else {
        quality = "bad";
    }
    myfile << myDataValues[j].timeChanged.c_str() << "  " <<  myDataValues[j].value  << "  " <<  quality << std::endl; 
}

文件如下所示。

2012-06-25 12:41:56.789  55  good
2012-06-25 12:51:14.782  55  good
2012-06-25 05:25:16.456  62.6925  good
2012-06-25 05:26:11.458  63.4109  good
2012-06-25 05:27:01.459  63.0383  good
2012-06-25 05:27:56.959  61.5266  good
2012-06-25 05:29:01.959  58.5354  good
2012-06-25 05:32:06.963  47.5656  good
2012-06-25 05:33:06.964  44.9916  good
2012-06-25 05:33:11.963  44.8267  good
2012-06-25 05:34:06.965  43.6011  good
2012-06-25 05:34:56.965  43.493  good
2012-06-25 12:51:14.782  52.418  good
2012-06-25 09:49:54.112  0  good
2012-06-25 11:50:30.781  0  good

现在我必须在其他应用程序中阅读上面的文件并填充另一个向量例如。填充向量是否重复,不需要此检查。

 std::vector<DataValues> anotherDataValues

请求示例代码如何从上面的文件中读取数据并填充上面的矢量?

我该如何有效地做到这一点。

感谢您的时间和帮助。

3 个答案:

答案 0 :(得分:2)

显而易见的方法是编写>>(和<<)运算符 班级。插入操作符非常简单:

std::ostream&
operator<<( std::ostream& dest, DataValue const& data )
{
    dest << data.timeChanged << "  "
         << data.value << "  "
         << (data.uiQuality == 0 ? "good" : "bad");
    return dest;
}

完成此操作后,只需编写:

即可输出数组
std::copy( myDataValues.begin(), myDataValues.end(),
           std::ostream_iterator<DataValue>( myFile, "\n" ) );

<<运算符有点棘手,因为你必须要处理 格式中可能存在错误。鉴于数据格式包含 空格,我强加一个`\ n'作为终结符,并执行类似的操作:

std::istream&
operator>>( std::istream& source, DataValue& dest )
{
    std::string line;
    if ( std::getline( source, line ) ) {
        std::istringstream parse( line );
        std::string date;
        std::string time;
        float value;
        std::string status;
        parse >> date >> time >> value >> status >> std::ws;
        if ( ! parse || (status != "good" && status != "bad") ) {
            source.setstate( std::ios_base::failbit );
        } else {
            dest.timeChanged = date + ' ' + time;
            dest.value = value;
            dest.uiQuality = (status == "good" ? 0 : 1);
        }
    }
    return source;
}

请注意,日期格式中的空格会使事情变得复杂。如果你 有一些控制格式,我摆脱它。 (ISO使用'T' 例如,分开日期和时间。)无论如何,使用一些 DataTime的一类是有道理的;当然,这堂课 提供自己的>><<,然后您可以在上面使用它。

一旦你完成了这一点,阅读也变得微不足道了:

std::vector<DataValue> v(
    (std::istream_iterator<DataValue>( myFile )),
    (std::istream_iterator<DataValue>()) );

(注意额外的括号。至少有一个论点是必要的 避免最尴尬的解析问题。)

答案 1 :(得分:1)

您应首先弄清楚如何阅读一个 DataValue对象。然后填充它们的矢量很容易。以下是您可能会这样做的方法(尽管您应该提供更全面的错误检查)。

std::istream & operator>>(std::istream & is, DataValue & dv) {
    std::string date, time, quality;
    float value;
    if (is >> date >> time >> value >> quality) {
        if (quality == "good")
            dv.uiQuality = 0;
        else if (quality == "bad")
            dv.uiQuality = 1;
        else {
            is.setstate(std::ios::failbit);
            return is;
        }
        dv.timeChanged = date + " " + time;
        dv.value = value;
    }
    return is;
}

然后,你可以像这样填充矢量:

std::ifstream fin("myData.txt");
std::istream_iterator<DataValue> beg(fin), end;
std::vector<DataValue> v(beg,end);

答案 2 :(得分:0)

显然你可以在stl向量上push_back。但是,如果你这样做,并知道你的矢量有多长。您还可以使用reserve函数来请求存储足够的空间,以便不需要调整向量的大小。

或者,您也可以使用resize函数调用,并填写已经具有所需大小的stl向量。

http://www.cplusplus.com/reference/stl/vector/

您还可以从ifstream的getline功能

中获取数据

http://www.cplusplus.com/reference/iostream/istream/getline/