使用C ++在一行上读取多种数据类型

时间:2014-01-15 05:03:33

标签: c++ file io fstream istream

我试图从一个dat文件中提取一个由int组成的日期以及一个char和float值。

Dat文件格式如下:

201205171200 M29.65
201207041900 F30.3

等等。

我正在努力分离这些价值观。 以下是我到目前为止的情况:

    #include <iostream>
#include <fstream>
#include <vector>

using namespace std; 

int main() {
    int inCount = 0; //This variable will be used to keep track of what record is being read.
    vector<int> dates;
    vector<float> temps;
    // Open and retrieve data from text.
    ifstream inFile; 
    inFile.open("biodata.dat");//Opening Biodata file to begin going through data
    if(inFile)
    {
        char tempType;
        while(!inFile.eof())
          {
            if (inFile.eof()) break;
            inFile >> dates[inCount];
            cout << dates[inCount];
            inFile >> tempType;
            inFile >> temps[inCount];
                        if(tempType == 'F'){
                    temps[inCount] = (temps[inCount] - static_cast<float>(32)) * (5.0/9.0);
                }
            inCount++;

          }
    } else {
        cout << "The file did not load";
        return 0;
    }

}

我需要将第一部分作为时间戳分隔为int。 char'M'或'F'需要是它自己的char,最后一位需要是float。

我不知道如何将它们作为自己的变量。

2 个答案:

答案 0 :(得分:2)

声明三个变量并使用链式提取从文件中读取它们

ifstream inFile("biodata.dat");

std::string date; // since your values are so large
char mf;
double d;

while (inFile >> date >> mf >> d) {
    // use the vars here
}

你必须使用足够大的东西来存储数字。你可以使用long long,如果它足够大但可能不够大。您可以使用static_assert(std::numeric_limits<long long>::max() <= SOME_MAX_EXPECTED_VALUE, "long longs are too small");

进行检查

答案 1 :(得分:1)

在典型情况下,每一行代表一条逻辑记录,您希望首先定义一个结构(或类)来表示其中一条记录。在这种情况下,通常最容易定义operator>>来从文件中读取一条(且只有一条)记录:

struct record {
    unsigned long long timestamp;
    float temp;

    std::istream &operator>>(std::istream &is, record &r) { 
        char temp;
        is >> r.timestamp >> temp >> r.temp;
        if (temp == 'F') {
            r.temp -= 32.0f;
            r.temp *= 5.0f / 9.0f;
        }
        return is;            
    }
};

通过此定义,您可以在单个操作中读取和整个记录:

record r;

infile >> r;

或者,(看起来你可能想要这里)你可以一次阅读它们的整个载体:

std::vector<record> records {
    std::istream_iterator<record>(infile),
    std::istream_iterator<record>()
};

您可能更喜欢在阅读时将时间戳分成单个字段。如果是这样,你可以定义一个timestamp结构,并用它做同样的事情 - 定义年,月,日,小时和分钟的字段,然后定义一个operator>>来单独读取每个字段(读取四个字符,将它们转换为年份的int,再读两个并转换为月份等等。

通过这个定义,您只需将记录的时间戳成员定义为该类型的实例,并仍然使用>>流提取器读取该对象的实例,就像上面一样。