【问题标题】:Reading data from file and filling in STL vector从文件中读取数据并填充 STL 向量
【发布时间】:2012-06-26 05:33:19
【问题描述】:
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

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

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

感谢您的时间和帮助。

【问题讨论】:

  • 有重复,但主要的想法是(在我脑海中):std::vector&lt;std::string&gt; anotherDataValues (std::ostream_iterator&lt;std::string&gt;(fileObject, " "), std::ostream_iterator&lt;std::string&gt;());
  • 在填充向量时,我不必检查是否重复,只需从文件中读取数据并读取到向量中,您能详细说明一下吗?
  • 我的意思是重复的问题;我最近看到了一些。该代码使用ostream_iterator 作为开始和结束位置粗略地初始化一个向量,以有效地将文件读入字符串向量。简而言之,它是一个单线,不像做同样事情的短循环那么容易理解。
  • std::string 没有成员函数Format()
  • 如何读取上面的字符串向量并填充我的数据类型“DataValues”的向量?你能显示示例代码吗?

标签: c++ stl


【解决方案1】:

显而易见的方法是为 班上。插入运算符非常简单:

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" ) );

&lt;&lt; 运算符有点棘手,因为你必须处理 可能的格式错误。鉴于数据格式包含 空格,我会强加一个 `\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 的类是有道理的;这堂课当然会, 提供自己的&gt;&gt;&lt;&lt;,然后您可以在上面使用它们。

一旦你这样做了,阅读也变得微不足道:

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

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

【讨论】:

    【解决方案2】:

    您应该首先弄清楚您将如何读取一个 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);
    

    【讨论】:

      【解决方案3】:

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

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

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

      你也可以从ifstream的getline函数中获取数据

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

      【讨论】:

      • 我不应该在同一个地方 push_back。我正在另一个应用程序中读取文件。
      猜你喜欢
      • 2013-09-16
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多