ifstream

时间:2017-11-15 17:29:43

标签: c++ copy-constructor ifstream

我想从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()方法吗?

1 个答案:

答案 0 :(得分:0)

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

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