ifstream的已删除副本构建器的替代方法

Alternative for deleted copy constrctor of ifstream

本文关键字:方法 副本 删除 ifstream 构建      更新时间:2023-10-16

我想从csv文件中提取数据,但我必须首先获取表的行数和列数。

到目前为止,我拥有以下内容:

        std::ifstream myfile(filename); // filename is a string and passed in by the constructor
        if (myfile.is_open())
        {
            // First step: Get number of rows and columns of the matrix to initialize it.
            // We have to close and re-open the file each time we want to work with it.
            int rows = getRows(myfile);
            std::ifstream myfile1(filename);
            int columns = getColumns(myfile1);
            if (rows == columns) // Matrix has to be quadratic.
            {
                std::ifstream myfile2(filename);
                abwicklungsdreieck.set_Matrix(QuantLib::Matrix(rows, columns, 0)); // abwicklungsdreieck is initialised before
                //...
            }
            else
            {
                std::cout << "nNumber of rows has to equal number of columns.";
            }
        }
    // [...]
    int getRows(std::ifstream &myfile)
    {
        std::string line;
        int rows = 0;
        while (std::getline(myfile, line)) // While-loop simply counts rows.
        {
            rows++;
        }
        myfile.close();
        return rows - 1;
    }
    int getColumns(std::ifstream &myfile)
    {
        std::string line;
        char delimiter = ';';
        size_t pos = 0;
        int columns = 0;
        while (std::getline(myfile, line) && columns == 0) // Consider first line in the .csv file.
        {
            line = line + ";";
            while ((pos = line.find(delimiter)) != std::string::npos) // Counts columns.
            {
                line.erase(0, pos + 1);
                columns++;
            }
        }
        myfile.close();
        return columns - 1;
    }

此代码有效。但是,我必须打开文件三次,我不喜欢。有没有办法逃避这一点?

我正在考虑在getRows((和getColumns((中使用临时文件,但是复制流是不可能的,因为我最近学到的它没有意义。

那么,有没有另一种方法呢?或者我可以逃避getline((和line.erase((方法吗?

您可以逐行读取文件,将每行转换为流,然后读取流上的列:

std::ifstream myfile(filename);
if(!myfile) return 0;
std::string line;
while(std::getline(myfile, line))
{
    std::stringstream ss(line);
    std::string column;
    while(std::getline(ss, column, ';'))
    {
        cout << column;
    }
    cout << "n";
}

getline(myfile, line)会将每一行复制到line 中。

将线路转换为ss流。

getline(ss, column, ';')会将行分成列。

使用 std::stoi 将字符串转换为整数。

如果你的矩阵是基于std::vector的,你可以一次增长一行的向量,所以你不需要提前知道大小。

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
void readfile(const std::string &filename)
{
    std::vector<std::vector<int>> matrix;
    std::ifstream myfile(filename);
    if(!myfile) return;
    std::string buf;
    while(std::getline(myfile, buf))
    {
        int maxrow = matrix.size();
        std::stringstream ss(buf);
        matrix.resize(maxrow + 1);
        cout << "break in to columns:" << buf << "n";
        while(std::getline(ss, buf, ';'))
        {
            try {
                int num = std::stoi(buf);
                matrix[maxrow].push_back(num);
            }
            catch(...) { }
        }
    }
    for(auto &row : matrix) {
        for(auto col : row)
            cout << col << "|";
        cout << "n";
    }
}