[英]read a csv file and and add its all data into vector in c++
例如添加以下 CSV 數據:
我正在嘗試將 CSV 文件添加到二維數組字符串向量中並獲取每列的總和。 以下程序無法正常工作,
vector<string> read_csv(string filename){
vector<string> result;
fstream fin;
fin.open(filename, ios::in);
if(!fin.is_open())
throw std::runtime_error("Could not open file");
std::string line, colname;
int val;
// Read the column names
if(fin.good())
{
std::getline(fin, line);
std::stringstream ss(line);
while(std::getline(ss, colname, ',')){
result.push_back(colname);
cout << colname << endl;
}
}
while(std::getline(fin, line))
{
std::stringstream ss(line);
int colIdx = 0;
while(ss >> val){
if(ss.peek() == ',') ss.ignore();
colIdx++;
}
}
fin.close();
return result;
}
當我試圖通過向量時,我沒有得到正確的結果。 它只顯示列名。
for (int i = 0; i < vectorCsv.size(); ++i)
{
cout << vectorCsv[i] << endl;
}
我找不到錯誤是在 read_csv() 函數中還是在 forloop 中。 謝謝你看這個問題。
在您的 while 循環中,您從未將任何值推送到您的向量。
看起來您擁有將 csv 讀入向量所需的一切。 唯一的問題是您停在列名處。
// Read the column names
if(fin.good())
{
std::getline(fin, line);
std::stringstream ss(line);
while(std::getline(ss, colname, ',')){
result.push_back(colname);
cout << colname << endl;
}
}
嘗試將我上面復制的代碼更改為:
// Read the column names
while(std::getline(fin, line))
{
std::getline(fin, line);
std::stringstream ss(line);
while(std::getline(ss, colname, ',')){
result.push_back(colname);
cout << colname << endl;
}
}
std::string
的向量,這可能不是很有效 - 每個字符串被分別分配和取消分配。不要自己閱讀 CSV - 你在重新發明輪子。 使用現有的庫。 這是一個關於在 Software Recommendations StackExchange 中找到一個的問題:
我不敢相信我們正在使用一個庫來完成如此簡單的事情,比如將std::string
拆分為標記。
長期以來,C++ 具有專門為此目的而設計的內置和專用功能,用於對字符串進行標記(將字符串拆分為標記)。 並且因為這樣一個專為此目的而設計的簡單專用功能可用,所以應該使用它。 不需要外部庫或復雜的結構。 只需使用std::sregex_token_iterator
。
這是一個迭代器(像許多其他迭代器一樣),它迭代字符串的標記(子字符串)。 所以,我們想要什么。
然后我們可以使用std::vector
的 range 構造函數來編寫如下簡單的內容:
std::vector tokens(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}));
因此,我們定義了一個名為“tokens”的std::vector
類型的變量(使用 CTAD 會自動推導出向量的類型)。 我們使用它的范圍構造函數並提供一個開始和一個結束迭代器。 開始迭代器是std::sregex_token_iterator
而結束迭代器是其默認初始化的對應物。
為了將這樣的向量放入二維向量中,我們使用外部向量emplace_back
函數並對內部向量進行就地構造。
所以你用 2 個語句閱讀了整個 CSV 文件
std::sregex_token_iterator
返回一個簡單的std::sregex_token_iterator
// We will read all lines of the source file with a simple for loop and std::getline
for (std::string line{}; std::getline(csvFile, line); ) {
// We will split the one big string into tokens (sub-strings) and add it to our 2D array
csvData.emplace_back(std::vector<std::string>(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}));
}
那么,為什么要使用一個庫來完成一個可以用 2 個語句完成的簡單任務呢? 我個人無法理解這一點。 因此,我發現已接受答案中的建議完全錯誤。 但是,為了避免開始宗教討論:這是我非常個人的拙見,每個人都可以為所欲為。
請查看一個完整的工作示例,它只需幾行代碼即可解決您的問題。 . .
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>
const std::string csvFileName{ "r:\\csv.csv" };
const std::regex delimiter{ "," };
int main() {
// Open the file and check, if it could be opened
if (std::ifstream csvFile(csvFileName); csvFile) {
// This is our "2D array string vector" as described in your post
std::vector<std::vector<std::string>> csvData{};
// Read the complete CSV FIle into a 2D vector ----------------------------------------------------
// We will read all lines of the source file with a simple for loop and std::getline
for (std::string line{}; std::getline(csvFile, line); ) {
// We will split the one big string into tokens (sub-strings) and add it to our 2D array
csvData.emplace_back(std::vector<std::string>(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}));
}
// -------------------------------------------------------------------------------------------------
// This is for summing up values
double DP{}, Dta{}, Dts{};
// Iterate in a simple for loop through all elements of the 2D vector, convert the vlaues to double and sum them up
for (size_t i = 1U; i < csvData.size(); ++i) {
DP += std::stod(csvData[i].at(1));
Dta += std::stod(csvData[i].at(2));
Dts += std::stod(csvData[i].at(3));
}
// Sho the result to the user
std::cout << "\nSums: DP: " << DP << " Dta: " << Dta << " Dts: " << Dts << "\n";
}
else { // In case that we could not open the source file
std::cerr << "\n*** Error. Could not open file " << csvFileName << "\n\n";
}
return 0;
}
但正如所說,每個人都可以為所欲為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.