【问题标题】:Reading multiple data types on one line using C++使用 C++ 在一行上读取多种数据类型
【发布时间】:2014-01-15 05:03:33
【问题描述】:

我试图从一个 dat 文件中提取一个由整数以及一个字符和一个浮点值组成的日期。

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,最后一位需要是浮点数。

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

【问题讨论】:

  • 您的行 vector&lt;int&gt; dates; 需要为 vector&lt;long long&gt; dates; 以确保其足够大以容纳这些数字。
  • 另外,您似乎没有在任何地方管理矢量的大小。您可以读入局部变量,然后使用push_back() 将值添加到您的向量中,这样就可以解决这个问题。

标签: c++ file io fstream istream


【解决方案1】:

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

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&lt;long long&gt;::max() &lt;= SOME_MAX_EXPECTED_VALUE, "long longs are too small"); 进行检查

【讨论】:

  • 我认为 32 位 int 不会保存初始数字。因为(unsigned even)int 上限为 40 亿左右,而他显示的数字是 2000 亿以上。所以很长很长或者更适合这个。
  • @BWG 好点,我没注意到大小。我切换到 std::string .. 不过我会添加一个注释
【解决方案2】:

在典型情况下,每一行代表一个逻辑记录,您希望首先定义一个结构(或类)来表示其中一个记录。在这种情况下,通常最简单的方法是定义一个operator&gt;&gt; 来从文件中读取一条(并且只有一条)记录:

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&gt;&gt; 以单独读取每个字段(读取四个字符,将它们转换为年份的 int,再读两个并转换为月份,等等。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-02
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多