簡體   English   中英

如何讀取 CSV 數據集,其中每一行都有不同的長度。 C++

[英]How to read a CSV dataset in which each row has a distinct length. C++

我是 C++ 的新手,正在研究如何從 csv 文件中讀取數據。 我想將以下 csv 數據讀入向量。 每行是一個向量。 文件名為path.csv:

0 

0 1 

0 2 4

0 3 6 7

我使用以下 function:

vector<vector<int>> read_multi_int(string path) {
    vector<vector<int>> user_vec;
    ifstream fp(path); 
    string line;
    getline(fp, line); 
    while (getline(fp, line)) { 
        vector<int> data_line;
        string number;
        istringstream readstr(line); 
        
        while (getline(readstr, number, ',')) { 
            //getline(readstr, number, ','); 
            data_line.push_back(atoi(number.c_str())); 
        }
        user_vec.push_back(data_line); 
    }
    return user_vec;
}

vector<vector<int>> path = read_multi_int("C:/Users/data/paths.csv");

打印功能:

template <typename T>
void print_multi(T u)
{
    for (int i = 0; i < u.size(); ++i) {
        if (u[i].size() > 1) {
            for (int j = 0; j < u[i].size(); ++j) {
                //printf("%d ", u[i][j]);
                cout << u[i][j] << " ";
            }
            printf("\n");
        }
    }
    printf("\n");
}

然后我得到

0 0 0 

0 1 0

0 2 4

0 3 6 7

在行的末尾添加零。 是否可以只從 csv 文件中讀取數據而不添加那些額外的零? 謝謝!

根據您看到的 output 和帶有“,”逗號的代碼,我相信您的實際輸入數據確實如下所示:

A,B,C,D
0,,,
0,1,,
0,2,4,
0,3,6,7

所以主要的變化是用strtol替換atoi ,因為atoi在解析數字失敗時總是返回0 ,但是使用strtol我們可以檢查解析是否成功。

這意味着解決方案如下:

vector<vector<int>> read_multi_int(string path) {
    vector<vector<int>> user_vec;
    ifstream fp(path);
    string line;
    getline(fp, line);
    while (getline(fp, line)) {
        vector<int> data_line;
        string number;
        istringstream readstr(line);

        while (getline(readstr, number, ',')) {
            char* temp;
            char numberA[30];
            int numberI = strtol(number.c_str(), &temp, 10);
            if (temp == number || *temp != '\0' ||
                ((numberI == LONG_MIN || numberI == LONG_MAX) && errno == ERANGE))
            {
                // Could not convert
            }else{
                data_line.emplace_back(numberI);
            }
        }
        user_vec.emplace_back(data_line);
    }
    return user_vec;
}

然后顯示您的結果:

vector<vector<int>> path = read_multi_int("C:/Users/data/paths.csv");

for (const auto& row : path)
{
    for (const auto& s : row) std::cout << s << ' ';
    std::cout << std::endl;
}

給出預期的 output:

0
0 1
0 2 4
0 3 6 7

已經很好了,但是有一個明顯的錯誤和另一個錯誤在你的打印 function 中。請看,我是如何使用基於 for 循環的簡單范圍的 output 值的。

如果您的源文件不包含逗號( ',' ),但包含不同的分隔符,那么您需要使用此不同的分隔符調用std::getline ,在您的情況下為空白( ' ' )。 在此處閱讀有關std::getline的信息。

如果我們然后使用以下輸入

Header
0
0 1
0 2 4
0 3 6 7

使用更正后的程序。

#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

vector<vector<int>> read_multi_int(string path) {
    vector<vector<int>> user_vec;
    ifstream fp(path);
    string line;
    getline(fp, line);
    while (getline(fp, line)) {
        vector<int> data_line;
        string number;
        istringstream readstr(line);

        while (getline(readstr, number, ' ')) {
            //getline(readstr, number, ','); 
            data_line.push_back(atoi(number.c_str()));
        }
        user_vec.push_back(data_line);
    }
    return user_vec;
}

int main() {
    vector<vector<int>> path = read_multi_int("C:/Users/data/paths.csv");
    for (vector<int>& v : path) {
        for (int i : v) std::cout << i << ' ';
        std::cout << '\n';
    }
}

然后我們收到這個 output:

0
0 1
0 2 4
0 3 6 7

這是正確的,但不幸的是與您顯示的 output 不同。

因此,您的 output 例程或其他一些代碼也可能有問題。

除了。 如果沒有逗號,那么您可以使用提取運算符>>來利用格式化輸入函數。 這將讀取您的輸入直到下一個空格並將其自動轉換為數字。

此外,強烈建議在定義期間初始化所有變量。 你應該總是這樣做。

修改您的代碼以使用格式化輸入、初始化,也許還有更好的變量名,那么它可能如下所示。

#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

vector<vector<int>> multipleLinesWithIntegers(const string& path) {

    // Here we will store the resulting 2d vector
    vector<vector<int>> result{};

    // Open the file
    ifstream fp{ path };

    // Read header line
    string line{};
    getline(fp, line);

    // Now read all lines with numbers in the file
    while (getline(fp, line)) {

        // Here we will store all numbers of one line
        vector<int> numbers{};

        // Put the line into an istringstream for easier extraction
        istringstream sline{ line };

        int number{};
        while (sline >> number) {
            numbers.push_back(number);
        }
        result.push_back(numbers);
    }
    return result;
}

int main() {
    vector<vector<int>> values = multipleLinesWithIntegers("C:/Users/data/paths.csv");
    for (const vector<int>& v : values) {
        for (const int i : v) std::cout << i << ' ';
        std::cout << '\n';
    }
}

而且,下一步將是使用一些更高級的樣式:

#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>

auto multipleLinesWithIntegers(const std::string& path) {

    // Here we will store the resulting 2d vector
    std::vector<std::vector<int>> result{};

    // Open the file and check, if it could be opened
    if (std::ifstream fp{ path }; fp) {

        // Read header line
        if (std::string line{}; getline(fp, line)) {

            // Now read all lines with numbers in the file
            while (getline(fp, line)) {

                // Put the line into an istringstream for easier extraction
                std::istringstream sline{ line };
                // Get the numbers and add them to the result
                result.emplace_back(std::vector(std::istream_iterator<int>(sline), {}));
            }
        }
        else std::cerr << "\n\nError: Could not read header line '" << line << "'\n\n";
    }
    else std::cerr << "\n\nError: Could not open file '" << path << "'\n\n'";
    return result;
}

int main() {
    const std::vector<std::vector<int>> values{ multipleLinesWithIntegers("C:/Users/data/paths.csv") };
    for (const std::vector<int>& v : values) {
        for (const int i : v) std::cout << i << ' ';
        std::cout << '\n';
    }
}

編輯


您已經展示了您的 output 例程。 那應該改為:

void printMulti(const std::vector<std::vector<int>>& u)
{
    for (int i = 0; i < u.size(); ++i) {
        if (u[i].size() > 0) {
            for (int j = 0; j < u[i].size(); ++j) {
                std::cout << u[i][j] << ' ';
            }
            std::cout << '\n';
        }
    }
    std::cout << '\n';
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM