C ++按行读取逗号分隔文件[其中一个部分为mm/dd/yyyy],安全地放入结构中
C++ reading in a comma delimited file[with one section as mm/dd/yyyy] by line, placing into a struct securely
为了扩展标题,我正在阅读一个文件 line-by-line,它显示为:
FirstName,LastName,mm/dd/yyyy,SSN,Role,Salary,Zip,Phone
我有刚刚编写的这段代码,但是由于我使用的是 std::string 而不是 char[],所以将它放入我的结构中时遇到了一些问题。我想在以后继续使用 std::string。另外,请原谅我有一段时间没有在 c/c++ 中编写任何语法错误。我也读过 the most elegant way to iterate to words of a string 但我仍然对如何使用日期格式中涉及的斜杠来做到这一点感到困惑。 SSN 和 Salary 是结构的私有成员,将被推入一个向量供以后使用。我如何使用 C++ 库执行此操作?老实说,istringstream 让我感到困惑,因为它们直接在其结构中包含某种类型的解析器。这真的是完成我想要做的事情的最佳方式吗?
char stringData[150]; //line to be read in
while(fgets(stringData, 150, infile) != NULL) {
if( currentLine == 1) {
fgets(stringData, 150, infile); //get column names | trash
}
else {
lineSize = sscanf(stringData, "%[^,],%[^,],%d/%d/%d,%d,%[^,],%lf,%[^,],%s", temp.firstName,temp.lastName,
&temp.birthMonth,&temp.birthDay,&temp.birthYear,
&tempSSN, temp.role, &tempSalary, temp.zip,
temp.phoneNum);
if(lineSize != 10) { //error message due to a row being incorrect
cerr << "/* ERROR: WRONG FORMAT OF INPUT(TOO FEW OR TOO MANY ARGUMENTS) ON LINE: */" << currentLine << '\n';
exit(1);
}
temp.setSSN(tempSSN);
temp.setSalary(tempSalary);
vector.push_back(temp);//push Employee temp into the vector and repeat loop
}
currentLine++
}
TL;DR:使用 C++ 库执行此操作的最简单方法是什么?
正如 Sam Varshavchik 已经提到的,最简单的方法是用 ,
分隔输入,然后再次用 /
分隔输入。
感谢 this famous question 我使用以下方法拆分字符串:
template<typename Out>
void split(const std::string &s, char delim, Out result)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim))
{
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim)
{
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
假设这是您的结构:
struct info
{
std::string firstName;
std::string lastName;
std::string birthMonth;
std::string birthDay;
std::string birthYear;
std::string tempSSN;
std::string role;
std::string tempSalary;
std::string zip;
std::string phoneNum;
};
我会像这样实现您需要的功能:
void parser(std::string fileName, std::vector<info> &inf)
{
std::string line;
std::ifstream infile(fileName);
int index = inf.size();
while(std::getline(infile, line))
{
inf.push_back({});
std::vector<std::string> comma_seprated_vec = split(line, ',');
inf.at(index).firstName = comma_seprated_vec.at(0);
inf.at(index).lastName = comma_seprated_vec.at(1);
inf.at(index).tempSSN = comma_seprated_vec.at(3);
inf.at(index).role = comma_seprated_vec.at(4);
inf.at(index).tempSalary = comma_seprated_vec.at(5);
inf.at(index).zip = comma_seprated_vec.at(6);
inf.at(index).phoneNum = comma_seprated_vec.at(7);
std::vector<std::string> slash_seprated_vec = split(comma_seprated_vec.at(2), '/');
inf.at(index).birthMonth = slash_seprated_vec.at(0);
inf.at(index).birthDay = slash_seprated_vec.at(1);
inf.at(index).birthYear = slash_seprated_vec.at(2);
++index;
}
}
然后你就可以这样使用了:
int main()
{
std::vector<info> information;
parser("some file", information);
return 0;
}
好了,您的信息显示在 information
变量中。
为了扩展标题,我正在阅读一个文件 line-by-line,它显示为:
FirstName,LastName,mm/dd/yyyy,SSN,Role,Salary,Zip,Phone
我有刚刚编写的这段代码,但是由于我使用的是 std::string 而不是 char[],所以将它放入我的结构中时遇到了一些问题。我想在以后继续使用 std::string。另外,请原谅我有一段时间没有在 c/c++ 中编写任何语法错误。我也读过 the most elegant way to iterate to words of a string 但我仍然对如何使用日期格式中涉及的斜杠来做到这一点感到困惑。 SSN 和 Salary 是结构的私有成员,将被推入一个向量供以后使用。我如何使用 C++ 库执行此操作?老实说,istringstream 让我感到困惑,因为它们直接在其结构中包含某种类型的解析器。这真的是完成我想要做的事情的最佳方式吗?
char stringData[150]; //line to be read in
while(fgets(stringData, 150, infile) != NULL) {
if( currentLine == 1) {
fgets(stringData, 150, infile); //get column names | trash
}
else {
lineSize = sscanf(stringData, "%[^,],%[^,],%d/%d/%d,%d,%[^,],%lf,%[^,],%s", temp.firstName,temp.lastName,
&temp.birthMonth,&temp.birthDay,&temp.birthYear,
&tempSSN, temp.role, &tempSalary, temp.zip,
temp.phoneNum);
if(lineSize != 10) { //error message due to a row being incorrect
cerr << "/* ERROR: WRONG FORMAT OF INPUT(TOO FEW OR TOO MANY ARGUMENTS) ON LINE: */" << currentLine << '\n';
exit(1);
}
temp.setSSN(tempSSN);
temp.setSalary(tempSalary);
vector.push_back(temp);//push Employee temp into the vector and repeat loop
}
currentLine++
}
TL;DR:使用 C++ 库执行此操作的最简单方法是什么?
正如 Sam Varshavchik 已经提到的,最简单的方法是用 ,
分隔输入,然后再次用 /
分隔输入。
感谢 this famous question 我使用以下方法拆分字符串:
template<typename Out>
void split(const std::string &s, char delim, Out result)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim))
{
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim)
{
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
假设这是您的结构:
struct info
{
std::string firstName;
std::string lastName;
std::string birthMonth;
std::string birthDay;
std::string birthYear;
std::string tempSSN;
std::string role;
std::string tempSalary;
std::string zip;
std::string phoneNum;
};
我会像这样实现您需要的功能:
void parser(std::string fileName, std::vector<info> &inf)
{
std::string line;
std::ifstream infile(fileName);
int index = inf.size();
while(std::getline(infile, line))
{
inf.push_back({});
std::vector<std::string> comma_seprated_vec = split(line, ',');
inf.at(index).firstName = comma_seprated_vec.at(0);
inf.at(index).lastName = comma_seprated_vec.at(1);
inf.at(index).tempSSN = comma_seprated_vec.at(3);
inf.at(index).role = comma_seprated_vec.at(4);
inf.at(index).tempSalary = comma_seprated_vec.at(5);
inf.at(index).zip = comma_seprated_vec.at(6);
inf.at(index).phoneNum = comma_seprated_vec.at(7);
std::vector<std::string> slash_seprated_vec = split(comma_seprated_vec.at(2), '/');
inf.at(index).birthMonth = slash_seprated_vec.at(0);
inf.at(index).birthDay = slash_seprated_vec.at(1);
inf.at(index).birthYear = slash_seprated_vec.at(2);
++index;
}
}
然后你就可以这样使用了:
int main()
{
std::vector<info> information;
parser("some file", information);
return 0;
}
好了,您的信息显示在 information
变量中。