我正在尝试读取一个CSV文件,该文件包含3人/患者的行,其中col 1是userid,col 2是fname,col 3是lname,col 4是保险,col 5是看起来是的版本像下面这样。
编辑:抱歉,我只是在此处复制/粘贴了CSV电子表格,因此以前没有显示逗号。它看起来不像下面吗?下面的John还指出,该版本之后没有逗号,这似乎可以解决该问题!非常感谢约翰! (试图弄清楚我如何接受您的回答:))
nm92,Nate,Matthews,Aetna,1
sc91,Steve,Combs,Cigna,2
ml94,Morgan,Lands,BCBS,3
我正在尝试在循环内使用getline()读取所有内容,并且在第一次迭代中工作正常,但是getline()似乎导致它在下一次迭代中跳过了一个值。知道我该如何解决吗?
我也不确定为什么输出如下图所示,因为我看不到代码中有w /“ sc91”和“ ml94”的行。这就是当前代码的输出。
userid is: nm92
fname is: Nate
lname is: Matthews
insurance is: Aetna
version is: 1
sc91
userid is: Steve
fname is: Combs
lname is: Cigna
insurance is: 2
ml94
version is: Morgan
userid is: Lands
fname is: BCBS
lname is: 3
insurance is:
version is:
我已经对getline()和>>流运算符之间的差异进行了大量研究,但是大多数getline()材料似乎都是围绕从cin获取输入而不是从像这样的文件中读取,所以我在想w / getline()上正在发生什么,以及它如何读取我不理解的文件。不幸的是,当我尝试>>运算符时,这迫使我使用strtok()函数,并且我在使用c字符串并将其分配给C ++字符串数组方面工作很多。
#include <iostream>
#include <string> // for strings
#include <cstring> // for strtok()
#include <fstream> // for file streams
using namespace std;
struct enrollee
{
string userid = "";
string fname = "";
string lname = "";
string insurance = "";
string version = "";
};
int main()
{
const int ENROLL_SIZE = 1000; // used const instead of #define since the performance diff is negligible,
const int numCols = 5; // while const allows for greater utility/debugging bc it is known to the compiler ,
// while #define is a preprocessor directive
ifstream inputFile; // create input file stream for reading only
struct enrollee enrollArray[ENROLL_SIZE]; // array of structs to store each enrollee and their respective data
int arrayPos = 0;
// open the input file to read
inputFile.open("input.csv");
// read the file until we reach the end
while(!inputFile.eof())
{
//string inputBuffer; // buffer to store input, which will hold an entire excel row w/ cells delimited by commas
// must be a c string since strtok() only takes c string as input
string tokensArray[numCols];
string userid = "";
string fname = "";
string lname = "";
string insurance = "";
string sversion = "";
//int version = -1;
//getline(inputFile,inputBuffer,',');
//cout << inputBuffer << endl;
getline(inputFile,userid,',');
getline(inputFile,fname,',');
getline(inputFile,lname,',');
getline(inputFile,insurance,',');
getline(inputFile,sversion,',');
enrollArray[0].userid = userid;
enrollArray[0].fname = fname;
enrollArray[0].lname = lname;
enrollArray[0].insurance = insurance;
enrollArray[0].version = sversion;
cout << "userid is: " << enrollArray[0].userid << endl;
cout << "fname is: " << enrollArray[0].fname << endl;
cout << "lname is: " << enrollArray[0].lname << endl;
cout << "insurance is: " << enrollArray[0].insurance << endl;
cout << "version is: " << enrollArray[0].version << endl;
}
}
答案 0 :(得分:1)
这只是一个主意,但可以为您提供帮助。这是我正在从事的一个项目的代码:
std::vector<std::string> ARDatabase::split(const std::string& line, char delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(line);
while (std::getline(tokenStream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
}
void ARDatabase::read_csv_map(std::string root_csv_map)
{
qDebug() << "Starting to read the people database...";
std::ifstream file(root_csv_map);
std::string str;
while (std::getline(file, str))
{
std::vector<std::string> tokens = split(str, ' ');
std::vector<std::string> splitnames = split(tokens.at(1), '_');
std::string name_w_spaces;
for(auto i: splitnames) name_w_spaces = name_w_spaces + i + " ";
people_names.insert(std::make_pair(stoi(tokens.at(0)), name_w_spaces));
people_images.insert(std::make_pair(stoi(tokens.at(0)), std::string("database/images/" + tokens.at(2))));
}
}
您可能希望使用其他更适合您的情况的容器来代替std :: vector。最后一个示例针对我的案例的输入格式。您可以轻松地对其进行修改,以使其适应您的代码。
答案 1 :(得分:1)
您的问题是每行最后一个数据项后面没有逗号,所以
getline(inputFile,sversion,',');
是不正确的,因为它会读取下一个逗号,该逗号实际上位于下一位患者的用户ID之后的下一行。这说明了您看到的输出,在该输出中,下一个专利的用户ID在哪里获得了该版本的输出。
要解决此问题,只需将上面的代码替换为
getline(inputFile,sversion);
将根据需要读取到行尾。
答案 2 :(得分:1)
关于您的功能。如果查看源文件的结构,则将看到它包含5个字符串,以“,”分隔。因此是典型的CSV文件。
调用std::getline
将读取包含5个字符串的完整行。在您的代码中,您尝试为每个单个字符串调用std::getline
,后跟一个逗号。最后一个字符串后不存在Commaa。这是行不通的。您还应该使用getline获取完整行。
您需要阅读整行,然后将其标记化。
我将向您展示如何使用std::sregex_token_iterator
进行操作的示例。那很简单。此外,我们将覆盖插入程序和Extracot运算符。这样一来,您就可以轻松读写Enrollee e{}; std::cout << e;
此外,我使用C ++算法。这使生活非常轻松。输入和输出主要是一线的。
请参阅:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <regex>
struct Enrollee
{
// Data
std::string userid{};
std::string fname{};
std::string lname{};
std::string insurance{};
std::string version{};
// Overload Extractor Operator to read data from somewhere
friend std::istream& operator >> (std::istream &is, Enrollee& e) {
std::vector<std::string> wordsInLine{}; // Here we will store all words that we read in onle line;
std::string wholeLine; // Temporary storage for the complete line that we will get by getline
std::regex separator("[ \\;\\,]"); ; // Separator for a CSV file
std::getline(is, wholeLine); // Read one complete line and split it into parts
std::copy(std::sregex_token_iterator(wholeLine.begin(), wholeLine.end(), separator, -1), std::sregex_token_iterator(), std::back_inserter(wordsInLine));
// If we have read all expted strings, then store them in our struct
if (wordsInLine.size() == 5) {
e.userid = wordsInLine[0];
e.fname = wordsInLine[1];
e.lname = wordsInLine[2];
e.insurance = wordsInLine[3];
e.version = wordsInLine[4];
}
return is;
}
// Overload Inserter operator. Insert data into output stream
friend std::ostream& operator << (std::ostream& os, const Enrollee& e) {
return os << "userid is: " << e.userid << "\nfname is: " << e.fname << "\nlname is: " << e.lname << "\ninsurance is: " << e.insurance << "\nversion is: " << e.version << '\n';
}
};
int main()
{
// Her we will store all Enrollee data in a dynamic growing vector
std::vector<Enrollee> enrollmentData{};
// Define inputFileStream and open the csv
std::ifstream inputFileStream("r:\\input.csv");
// If we could open the file
if (inputFileStream) {
// Then read all csv data
std::copy(std::istream_iterator<Enrollee>(inputFileStream), std::istream_iterator<Enrollee>(), std::back_inserter(enrollmentData));
// For Debug Purposes: Print all data to cout
std::copy(enrollmentData.begin(), enrollmentData.end(), std::ostream_iterator<Enrollee>(std::cout, "\n"));
}
else {
std::cerr << "Could not open file 'input.csv'\n";
}
}
这将读取包含以下内容的输入文件“ input.csv”
nm92,Nate,Matthews,Aetna,1
sc91,Steve,Combs,Cigna,2
ml94,Morgan,Lands,BCBS,3
并显示为输出:
userid is: nm92
fname is: Nate
lname is: Matthews
insurance is: Aetna
version is: 1
userid is: sc91
fname is: Steve
lname is: Combs
insurance is: Cigna
version is: 2
userid is: ml94
fname is: Morgan
lname is: Lands
insurance is: BCBS
version is: 3