[英]Extracting data from a CSV file in C++
我的測試 csv 文件的內容如下所示:
*test.csv*
name;age;weight;height;test
Bla;32;1.2;4.3;True
Foo;43;2.2;5.3;False
Bar;None;3.8;2.4;True
Ufo;32;1.5;5.4;True
我使用以下在屏幕上打印文件內容的 C++ 程序加載test.csv
文件:
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
#include <sstream>
void readCSV(std::vector<std::vector<std::string> > &data, std::string filename);
void printCSV(const std::vector<std::vector<std::string>> &data);
int main(int argc, char** argv) {
std::string file_path = "./test.csv";
std::vector<std::vector<std::string> > data;
readCSV(data, file_path);
printCSV(data);
return 0;
}
void readCSV(std::vector<std::vector<std::string> > &data, std::string filename) {
char delimiter = ';';
std::string line;
std::string item;
std::ifstream file(filename);
while (std::getline(file, line)) {
std::vector<std::string> row;
std::stringstream string_stream(line);
while (std::getline(string_stream, item, delimiter)) {
row.push_back(item);
}
data.push_back(row);
}
file.close();
}
void printCSV(const std::vector<std::vector<std::string> > &data) {
for (std::vector<std::string> row: data) {
for (std::string item: row) {
std::cout << item << ' ';
}
std::cout << std::endl;
}
}
我有以下問題:
age == 32
?name
、 weight
列?None
行?加載整個 csv 文件后提取所需信息是否更有意義(如果內存不成問題)? 如果可能,我只想使用 STL。
您能提供的任何幫助將不勝感激
你可以嘗試一些 csv 庫,但如果你想用自定義代碼來做到這一點,那么
在printCSV
您要求cin
輸入列名
將其保存在變量中
在此代碼for (std::vector<std::string> row: data)
當第一次循環運行時,再次檢查每個輸入的item
然后在第二個循環中保留一個索引,因此您可以跳過列號
僅打印兩列的示例代碼
void printCSV(const std::vector<std::vector<std::string> > &data) {
int col = 0;
std::vector<std::string> column_filter;
std::vector<int> column_index;
column_filter.push_back("name");
column_filter.push_back("weight");
int row1 =0;
for (std::vector<std::string> row: data) {
col = 0;
if(row1==0) {
int col1 = 0;
for (std::string item: row) {
for (std::string colname: column_filter){
if(item.compare(colname)==0) {
column_index.push_back(col1);
}
}
col1++;
}
}
for (std::string item: row) {
int found =0;
for (int index: column_index) {
if(index==col) found = 1;
}
if(found==1)
std::cout << item << ' ';
col++;
}
std::cout << std::endl;
row1++;
}
}
輸出
name weight
Bla 1.2
Foo 2.2
Bar 3.8
Ufo 1.5
在你關閉之前。 這里所有答案都在一個文件中。 但我會在你的單個問題中解釋,然后稍后。
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
#include <regex>
#include <algorithm>
#include <iterator>
// Save typing Work
using Rec = std::vector<std::string>;
std::regex delimiter{ ";" };
// Proxy class for easier input and output
struct Record {
// Our data for one record
Rec data{};
// Overwrite extractor operator
friend std::istream& operator >> (std::istream& is, Record& r) {
// Read on complete line from the input stream, and check, if the read was successfull
if (std::string line{}; std::getline(is, line)) {
// If there is something in our data vector already, delete it
r.data.clear();
// Now, in one statement, split the string into tokens and copy the result into our data vector
std::copy(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}, std::back_inserter(r.data));
}
return is;
}
// Overwrite inserter for easier output
friend std::ostream& operator << (std::ostream& os, const Record& r) {
std::copy(r.data.begin(), r.data.end(), std::ostream_iterator<std::string>(os,"\t"));
return os;
}
};
// Proxy for the complete CSV file
struct Roster {
// The header
Rec header{};
// All records of the CSV file
std::vector<Record> records{};
friend std::istream& operator >> (std::istream& is, Roster& r) {
// Read on complete line from the input stream, and check, if the read was successfull
if (std::string line{}; std::getline(is, line)) {
// So, we just have read the header
// Now, in one statement, split the string into tokens and copy the result into the header
r.header.clear();
std::copy(std::sregex_token_iterator(line.begin(), line.end(), delimiter, -1), {}, std::back_inserter(r.header));
// Now, in one statement, read all lines, split the string into tokens and copy the result into our record vector
r.records.clear();
std::copy(std::istream_iterator<Record>(is), {}, std::back_inserter(r.records));
}
return is;
}
// Overwrite inserter for easier output
friend std::ostream& operator << (std::ostream& os, const Roster& r) {
std::copy(r.records.begin(), r.records.end(), std::ostream_iterator<Record>(os, "\n"));
return os;
}
};
int main() {
// Open CSV file and check, if it could be opened
if (std::ifstream csvFileStream("r:\\test.csv"); csvFileStream) {
Roster roster{};
// Read the complete CSV file
csvFileStream >> roster;
// Show all read data on std::cout
std::cout << roster;
// All records with age ==32
std::cout << "\n\nAge 32\n";
std::vector<Record> age32{};
std::copy_if(roster.records.begin(), roster.records.end(), std::back_inserter(age32), [](const Record& r) { return r.data[1] == "32"; });
for (const Record& r : age32) std::cout << r << "\n";
// Or
std::cout << "\n\nAge 32 Option 2\n";
csvFileStream.clear(); csvFileStream.seekg(std::ios::beg); age32.clear();
std::copy_if(std::istream_iterator<Record>(csvFileStream), {}, std::back_inserter(age32), [](const Record& r) { return r.data[1] == "32"; });
for (const Record& r : age32) std::cout << r << "\n";
// Get Name and weight columns
std::cout << "\n\nweight and columns\n";
std::vector<std::vector<std::string>> nameAndWeight{};
std::transform(roster.records.begin(), roster.records.end(), std::back_inserter(nameAndWeight),
[](const Record& r) { std::vector<std::string>rec{ r.data[0], r.data[2] } ; return rec; });
for (const std::vector<std::string>& r : nameAndWeight) std::cout << r[0] << "\t" << r[1] << "\n";
// Everything but none
std::cout << "\n\nEverything but none\n";
std::vector<Record> notNone{};
std::copy_if(roster.records.begin(), roster.records.end(), std::back_inserter(notNone), [](const Record& r) { return r.data[1] != "None"; });
for (const Record& r : notNone) std::cout << r << "\n";
}
else {
std::cerr << "\n*** Error: Could not open source file\n";
}
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.