C++ CSV文件中的字符串向量未正确打印出来

C++ CSV文件中的字符串向量未正确打印出来,c++,csv,C++,Csv,因此,我试图读取并创建一个500 X 2的字符串向量,并从CSV文件中显示它们。我最终想将这些字符串转换为双精度字符串,但我想从简单地显示并确保向量中的值是正确的开始。我认为我有这个权利,我的文件被添加到我的目录中。代码如下: int main() { std::string line; int r = 0; std::ifstream file("Aerodynamics.csv"); std::vector <std::vector<std::string> >

因此,我试图读取并创建一个500 X 2的字符串向量,并从CSV文件中显示它们。我最终想将这些字符串转换为双精度字符串,但我想从简单地显示并确保向量中的值是正确的开始。我认为我有这个权利,我的文件被添加到我的目录中。代码如下:

int main() {

std::string line;
int r = 0;

std::ifstream file("Aerodynamics.csv");
std::vector <std::vector<std::string> > data;

if (getline(file, line)) {
    while (r < 500) {
        vector<string> row;
        stringstream iss(line);
        int c = 0;
        string val;

        while (c < 2 && getline(iss, val, ','))
        {
            row.push_back(val);
        }
        data.push_back(row);
    }
}

for (int i = 0; i < data.size(); i++)
{
    for (int j = 0; j < data[i].size(); j++)
    {
        std::cout << data[i][j] << endl;
    }
} 
} //I will fix the formatting on this :)
intmain(){
std::字符串行;
int r=0;
标准::ifstream文件(“airodynamics.csv”);
std::矢量数据;
if(getline(文件,行)){
而(r<500){
向量行;
弦流iss(线);
int c=0;
字符串val;
而(c<2&&getline(iss,val,,'))
{
行。推回(val);
}
数据。推回(世界其他地区);
}
}
对于(int i=0;i
首先,我们将检查现有的代码,找到bug,消除它们,然后一步一步地重构和优化

所描述的错误只能说明您的程序无法打开文件。不幸的是,您没有检查文件是否可以打开。因此,getline将失败,程序将不会进入外部循环。另一方面,这是一种好的做法,因为您没有增加循环变量r。对于内部循环也是如此

因此,第一个解决方案如下所示:

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

int main() {

    std::string line;
    int r = 0;

    std::ifstream file("r:\\Aerodynamics.csv");
    std::vector <std::vector<std::string> > data;

    while (r++ < 500 && getline(file, line)) {
        std::vector<std::string> row;
        std::stringstream iss(line);
        int c = 0;
        std::string val;

        while (c++ < 2 && std::getline(iss, val, ','))
        {
            row.push_back(val);
        }
        data.push_back(row);
    }

    for (int i = 0; i < data.size(); i++)
    {
        for (int j = 0; j < data[i].size(); j++)
        {
            std::cout << data[i][j] << std::endl;
        }
    }
}
std::vector tokens(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}));
因此,我们定义了一个名为“tokens”的变量,类型为
std::vector
(使用CTAD会自动推断向量的类型)。我们使用其范围构造函数并提供一个开始迭代器和结束迭代器。开始迭代器是
std::sregex_token_迭代器,结束迭代器是其默认的初始化对应项

为了将这样一个向量放入2D向量中,我们使用外部向量
emplace\u back
函数,并对内部向量进行就地构造

所以你用两条语句阅读了整个CSV文件

  • 一个简单的for循环
  • 使用
    std::sregex\u令牌\u迭代器返回一个简单的位置
这很简单

此外,我们还为数据输出引入了
std::ostream\u迭代器
。这将迭代容器中的所有可用数据,并调用其插入器操作符

然后我们有:

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

const std::regex delimiter{ "," };

// Short names for containers
using Columns = std::vector<std::string>;
using CSV = std::vector<Columns>;

int main() {

    // Open file and check, if it could be opened
    if (std::ifstream csvFile{ "r:\\Aerodynamics.csv" }; csvFile) {

        // Here we will store the read data
        CSV data{};

        // Read all lines of the source CSV file
        for (std::string line{}; std::getline(csvFile, line); ) {

            // Split string into substrings and add result to our data vector
            data.emplace_back(Columns(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}));
        }

        // Show result to user
        for (const Columns& c : data) {
            std::copy(c.begin(), c.end(), std::ostream_iterator<std::string>(std::cout, " "));
            std::cout << "\n";
        }

    } // This will call the destructor of csvFile and close the file
    else {
        // Inform user that we could not open the file
        std::cerr << "\n*** Error: Could not open input file\n";
    }
}
附言

  • 对于这个问题还有许多其他可能的解决方案
  • 不,
    std::sregex\u token\u迭代器不太多。它是合适的

  • 玩得开心…

    检查您是否能成功打开文件可能是个好主意?也许看看这个问题并回答一下一旦您解决了当前的问题,这将是您的下一个问题:当(r<500)时,这个循环何时停止
    ?类似地,您有一个
    c
    ,您在某种条件下使用,但从未使用过modify@mathematician1975是的,这很奇怪,因为我没有使用file.open,只是尝试使用fstream。我尝试过用其他方式读取它,但我得到的输出是与csv中的数字无关的奇怪数字。@idclev463035818基本上我有500行和2列,所以我试图用r和c作为索引填充向量中的每个单元格。所以我认为r<500和c<2应该可以实现这一点?
    #include <iostream>
    #include <string>
    #include <vector>
    #include <fstream>
    #include <regex>
    #include <iterator>
    
    const std::regex delimiter{ "," };
    
    // Short names for containers
    using Columns = std::vector<std::string>;
    using CSV = std::vector<Columns>;
    
    int main() {
    
        // Open file and check, if it could be opened
        if (std::ifstream csvFile{ "r:\\Aerodynamics.csv" }; csvFile) {
    
            // Here we will store the read data
            CSV data{};
    
            // Read all lines of the source CSV file
            for (std::string line{}; std::getline(csvFile, line); ) {
    
                // Split string into substrings and add result to our data vector
                data.emplace_back(Columns(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}));
            }
    
            // Show result to user
            for (const Columns& c : data) {
                std::copy(c.begin(), c.end(), std::ostream_iterator<std::string>(std::cout, " "));
                std::cout << "\n";
            }
    
        } // This will call the destructor of csvFile and close the file
        else {
            // Inform user that we could not open the file
            std::cerr << "\n*** Error: Could not open input file\n";
        }
    }
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <fstream>
    #include <regex>
    #include <iterator>
    #include <algorithm>
    
    const std::regex re{ "," };
    struct AerodynamicsValues {
    
        // Our internal data for one row
        std::vector<std::string> aerodynamicsValues{};
    
        // Overwrite extractor operator
        friend std::istream& operator >> (std::istream& is, AerodynamicsValues& ad) {
    
            // Read one complete line
            if (std::string line{}; std::getline(is, line)) {
    
                // Copy data into our values
                ad.aerodynamicsValues.clear();
                std::copy(std::sregex_token_iterator(line.begin(), line.end(), re, -1), {}, std::back_inserter(ad.aerodynamicsValues));
            }
            return is;
        }
    
        // Overwrite inserter 
        friend std::ostream& operator << (std::ostream& os, const AerodynamicsValues& ad) {
            std::copy(ad.aerodynamicsValues.begin(), ad.aerodynamicsValues.end(), std::ostream_iterator<std::string>(os, " "));
            return os;
        }
    };
    
    
    struct Aerodynamics {
    
        // All Aerodynamics data
        std::vector<AerodynamicsValues> data{};
    
        // Overwrite extractor operator
        friend std::istream& operator >> (std::istream& is, Aerodynamics& ad) {
            // Read all data
            ad.data.clear();
            std::copy(std::istream_iterator<AerodynamicsValues>(is), {}, std::back_inserter(ad.data));
            return is;
        }
    
        // Overwrite inserter 
        friend std::ostream& operator << (std::ostream& os, const Aerodynamics& ad) {
            std::copy(ad.data.begin(), ad.data.end(), std::ostream_iterator<AerodynamicsValues>(os, "\n"));
            return os;
        }
    };
    
    int main() {
    
        // Open file and check, if it could be opened
        if (std::ifstream csvFile{ "r:\\Aerodynamics.csv" }; csvFile) {
    
            Aerodynamics ad{};
    
            // Read all values from CSV file
            csvFile >> ad;
    
            // Show read data to user
            std::cout << ad;
    
        }
        return 0;
    }
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <fstream>
    #include <regex>
    #include <iterator>
    #include <algorithm>
    
    // This makes sure that we read double only
    const std::regex reForDouble{ R"((([+-]?(?:[[:d:]]+\.?|[[:d:]]*\.[[:d:]]+))(?:[Ee][+-]?[[:d:]]+)?))" };
    
    constexpr size_t LinesToRead = 500U;
    
    struct AerodynamicsValues {
    
        // Our internal data 
        double adv1{};
        double adv2{};
    
        // Overwrite extractor operator
        friend std::istream& operator >> (std::istream& is, AerodynamicsValues& ad) {
    
            // Read one complete line
            if (std::string line{}; std::getline(is, line)) {
    
                // Split string
                std::vector temp(std::sregex_token_iterator(line.begin(), line.end(), reForDouble, 1), {});
    
                // if we have read at least 2 double values for this line
                if (temp.size() > 1U) {
    
                    // Convert read strings to double
                    ad.adv1 = stod(temp[0]);
                    ad.adv2 = stod(temp[1]);
                }
                else {
                    // If we could not read at leas 2 doubles, we will set the values to default 0
                    ad.adv1 = ad.adv2 = {};
                }
            }
            return is;
        }
    
        // Overwrite inserter 
        friend std::ostream& operator << (std::ostream& os, const AerodynamicsValues& ad) {
            return os << ad.adv1 << ' ' << ad.adv2;
        }
    };
    
    
    struct Aerodynamics {
    
        // All Aerodynamics data
        std::vector<AerodynamicsValues> data{};
    
        // Overwrite extractor operator
        friend std::istream& operator >> (std::istream& is, Aerodynamics& ad) {
            // Read all data
            ad.data.clear();
            std::copy_n(std::istream_iterator<AerodynamicsValues>(is), LinesToRead, std::back_inserter(ad.data));
            return is;
        }
    
        // Overwrite inserter 
        friend std::ostream& operator << (std::ostream& os, const Aerodynamics& ad) {
            std::copy(ad.data.begin(), ad.data.end(), std::ostream_iterator<AerodynamicsValues>(os, "\n"));
            return os;
        }
    };
    
    int main() {
    
        // Open file and check, if it could be opened
        if (std::ifstream csvFile{ "r:\\Aerodynamics.csv" }; csvFile) {
    
            Aerodynamics ad{};
    
            // Read all values from CSV file
            csvFile >> ad;
    
            // Show read data to user
            std::cout << ad;
    
        }
        return 0;
    }