Reading multiple data types on one line using C++

可紊 提交于 2020-01-03 06:30:07

问题


I am attempting to pull from a dat file a date composed of ints as well as a char and a float value that are together.

Dat file format looks like:

201205171200 M29.65
201207041900 F30.3

And so on.

I am struggling with separating these values. Here is what I have so far:

    #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;
    }

}

I need to separate the first part as a time stamp as an int. The char 'M' or 'F' needs to be its own char, and the the last bit needs to be a float.

I have no idea how to pull them as their own variables.


回答1:


Declare three variables and read them from the file with a chained extraction

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
}

You will have to use something large enough to store the numbers. You can use a long long if that's big enough but it may not be large enough. You could check for this with a static_assert(std::numeric_limits<long long>::max() <= SOME_MAX_EXPECTED_VALUE, "long longs are too small");




回答2:


In a typical case each line represents a logical record, and you want to start by defining a struct (or class) to represent one of those records. In such a case, it's usually easiest to define an operator>> to read one (and only one) record from the file:

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;            
    }
};

With this defined, you can read and entire record in a single operation:

record r;

infile >> r;

Or, (as looks like you'll probably want here) you can read an entire vector of them at once:

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

You might prefer to split the time stamp up into individual fields as you read them. If so, you can define a timestamp structure and do essentially the same thing with it -- define fields for year, month, day, hour, and minute, then define an operator>> to read each field individually (read four characters, convert them to an int for the year, read two more and convert to month, etc.

With this defined, you'll just define your timestamp member of the record as an instance of that type, and still read an instance of that object with the >> stream extractor, just like above.



来源:https://stackoverflow.com/questions/21129480/reading-multiple-data-types-on-one-line-using-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!