gpt4 book ai didi

c++ - 如何在C++中读取带有逗号分隔值的流?

转载 作者:行者123 更新时间:2023-12-02 10:19:44 25 4
gpt4 key购买 nike

我想强调以下一个基本问题:

假设您有一个CSV文件,并用输入标题填充了单元格

代码应从.csv文件读取此内容并将结果写入.csv文件。还可以对输出的案例总数和案例的平均值进行编码。这是SO的样本,我想看看如何有效地采用它来完成此基本示例。

   void create() 
{
// file pointer
fstream fout;

// opens an existing csv file or creates a new file.
fout.open("reportcard.csv", ios::out | ios::app);

cout << "Enter the details of 5 students:"
<< " roll name maths phy chem bio";
<< endl;

int i, roll, phy, chem, math, bio;
string name;

// Read the input
for (i = 0; i < 5; i++) {

cin >> roll
>> name
>> math
>> phy
>> chem
>> bio;

// Insert the data to file
fout << roll << ", "
<< name << ", "
<< math << ", "
<< phy << ", "
<< chem << ", "
<< bio
<< "\n";
}
}

另外,阅读特定记录
void read_record() 
{

// File pointer
fstream fin;

// Open an existing file
fin.open("reportcard.csv", ios::in);

// Get the roll number
// of which the data is required
int rollnum, roll2, count = 0;
cout << "Enter the roll number "
<< "of the student to display details: ";
cin >> rollnum;

// Read the Data from the file
// as String Vector
vector<string> row;
string line, word, temp;

while (fin >> temp) {

row.clear();

// read an entire row and
// store it in a string variable 'line'
getline(fin, line);

// used for breaking words
stringstream s(line);

// read every column data of a row and
// store it in a string variable, 'word'
while (getline(s, word, ', ')) {

// add all the column data
// of a row to a vector
row.push_back(word);
}

// convert string to integer for comparision
roll2 = stoi(row[0]);

// Compare the roll number
if (roll2 == rollnum) {

// Print the found data
count = 1;
cout << "Details of Roll " << row[0] << " : \n";
cout << "Name: " << row[1] << "\n";
cout << "Maths: " << row[2] << "\n";
cout << "Physics: " << row[3] << "\n";
cout << "Chemistry: " << row[4] << "\n";
cout << "Biology: " << row[5] << "\n";
break;
}
}
if (count == 0)
cout << "Record not found\n";
}


[1]: /image/q6VfZ.png

最佳答案

我主要集中于为operator<<operator>>添加重载,因为您早先对它们表现出了兴趣,并在代码的注释中描述了它们的作用。

由于您要混合使用逗号分隔的流和其他流的输入和输出,因此我添加了一个适配器,用于CSV流以及向/从用户流的重载。

首先,创建一个class以将所有在一起的数据保留在一个数据记录中。我在这里做了一个简单的struct,这是一个class,默认情况下对其成员具有public访问权限。

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

// your student record
struct student {
std::string name; // It's usually good to have larger types first so name goes first
int roll;
int math;
int phy;
int chem;
int bio;
};

// read a student from an istream (like std::cin) - whitespace separated
std::istream& operator>>(std::istream& is, student& s) {
return is >> s.roll >> s.name >> s.math >> s.phy >> s.chem >> s.bio;
}

// write a student to an ostream (like std::cout)
std::ostream& operator<<(std::ostream& os, const student& s) {
return os << "Details of Roll " << s.roll << ":\n"
<< "Name: " << s.name << '\n'
<< "Maths: " << s.math << '\n'
<< "Physics: " << s.phy << '\n'
<< "Chemistry: " << s.chem << '\n'
<< "Biology: " << s.bio << '\n';
}
//--------------------------------------------------------------------------------------
// An adapter for comma separated streaming
struct CSVStudent {
CSVStudent(student& s) : stud(s) {}
CSVStudent(const CSVStudent&) = delete;

// The CSVStudent holds a reference to a "student"
student& stud;
};

// read a record from an istream - comma separated
std::istream& operator>>(std::istream& is, CSVStudent& csvstud) {
std::string line;

student& s = csvstud.stud; // an alias to the student to have to type less

if(std::getline(is, line)) { // read a complete line
// put the line in an istringstream for extraction:
std::istringstream ss(line);

char delim; // a dummy for reading commas

// Extract the comma separated values. "delim" is not checked so it could be
// any char breaking up the int:s.
//
// The below does things in the following order:
// 1. "ss >> s.roll >> delim"
// This extracts roll and a comma and returns
// a reference to ss, which is used in 2.
// 2. std::getline(ss, s.name, ',')
// Extracts a string until a comma is encountered.
// 3. Normal extraction for the rest of the int:s with the
// dummy variable "delim" where the commas are supposed to be.

if(not(std::getline(ss >> s.roll >> delim, s.name, ',') >> s.math >> delim >>
s.phy >> delim >> s.chem >> delim >> s.bio)) {
// If we get here, the extraction from the istringstream failed, so set
// the failstate on the istream too. Note the "not" on the line above.
is.setstate(std::ios::failbit);
}
}
return is;
}

// write a record to an ostream - comma separated
std::ostream& operator<<(std::ostream& os, const CSVStudent& csvstud) {
const student& s = csvstud.stud;
os << s.roll << ',' << s.name << ',' << s.math << ',' << s.phy << ',' << s.chem
<< ',' << s.bio << '\n';
return os;
}
//--------------------------------------------------------------------------------------
// get all students in the file as a std::vector<student>
std::vector<student> read_student_file(const std::string& filename) {
std::vector<student> retval;
std::ifstream fin(filename);
if(fin) { // file opened successfully
student stud;
CSVStudent csvstud{stud}; // holds a reference to stud

// loop for as long as student records can be read successfully
while(fin >> csvstud) // use the csv sdapter
retval.push_back(stud); // and put the stud in the vector
}
return retval;
}
//--------------------------------------------------------------------------------------
void create(const std::string& filename) {
// open an existing csv file or creates a new file.
std::ofstream fout(filename, std::ios::out | std::ios::app);
if(fout) {
std::cout << "Enter the details of 5 students:"
" roll name maths phy chem bio\n";

// Read the input
for(int i = 0; i < 5; i++) {
student stud;
std::cout << (i + 1) << ": ";
if(std::cin >> stud) {
// Insert the data to file if one was entered successfully
fout << CSVStudent(stud); // uses the adapters operator<<
} else {
std::cerr << "You failed to enter data for student " << (i + 1) << '\n';
break;
}
}
}
}
//--------------------------------------------------------------------------------------
int main() {
std::string filename = "reportcard.csv";

std::vector<student> students = read_student_file(filename);

std::cout << "There are " << students.size() << " students in the file.\n";
if(not students.empty()) {
// show the last record if there are any records in the file
std::cout << "Record " << students.size() << " is:\n\n";
std::cout << students.back() << '\n';
}

// create 5 new records
create(filename);
}

如果 reportcard.csv包含以下内容:
1,Ted,1,2,3,4
2,Foo,2,3,4,5
3,Bar,3,4,5,6
4,Baz,4,5,6,7
5,Bork,5,6,7,8

该程序应如下启动:
There are 5 students in the file.
Record 5 is:

Details of Roll 5:
Name: Bork
Maths: 5
Physics: 6
Chemistry: 7
Biology: 8

Enter the details of 5 students: roll name maths phy chem bio
1: <and here is where you're supposed to enter the first of 5 new students>

关于c++ - 如何在C++中读取带有逗号分隔值的流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60726552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com