0
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

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

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

感谢您的时间和帮助。

4

3 回答 3

2

显而易见的方法是为该类编写一个>>(and <<) 运算符。插入运算符非常简单:

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 使用 a'T' 来分隔日期和时间。)无论如何,使用某种类 forDataTime是有意义的;当然,这个类会提供它自己的>>and <<,然后你可以在上面使用它。

完成此操作后,阅读也变得微不足道:

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

(注意额外的括号。至少有一个参数是必要的,以避免最令人尴尬的解析问题。)

于 2012-06-26T08:18:23.343 回答
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);
于 2012-06-26T06:00:01.880 回答
0

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

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

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

您还可以从 ifstream 的getline函数中获取数据

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

于 2012-06-26T05:38:07.757 回答