C++ CSV文件中的字符串向量未正确打印出来
因此,我试图读取并创建一个500 X 2的字符串向量,并从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> >
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;
}