我在尝试用C ++读取文件时遇到了很多麻烦。 我遇到的主要问题是正确读取流的第一行,因为它与所有其他行不同。
示例文件为:
#Newbie 101|Exam 1|3
Person One|10
Person Two|20
Person Three|30
第一行以#开头,并声明类名,assignmanet名和学生总数。
void Grading::loadData()
{
string filename;
cout << "Enter a filename with records to open: ";
cin >> filename;
std::ifstream file;
file.open(filename.c_str(), std::ios::app);
if (!file) {
cout << "Unable to open the specified file" << endl;
return;
}
string buffer;
vector<Student> students;
vector<Student>::iterator it;
while (!getline(file, buffer, '|').eof()) {
Student stud;
string name;
string tmpgrade;
string course;
string assignment;
int totalstudents;
// read first line
if (buffer.find("#") == 0) {
getline(file, course, '|');
cout << "Course Name : " << course << endl;
cout << "Grading Item : " << assignment << endl;
cout << "Total Students : " << totalstudents << endl;
cout << endl;
continue;
}
getline(file, name, '|');
getline(file, tmpgrade, '|');
double grade = strtod(tmpgrade.c_str(), NULL);
stud.name = name;
stud.grade = grade;
cout << "Name: " << stud.name << endl;
cout << "Grade: " << stud.grade << endl;
students.push_back(stud);
}
我非常感谢有关如何修复此代码以正确读取文件的任何建议。 非常感谢提前!
答案 0 :(得分:3)
听起来第一行的读取/解析应该在你的循环之外(上方)。然后,您不必担心在主循环体中解析2种不同类型的线。
答案 1 :(得分:0)
您只需要将第一行作为特殊情况单独处理。您可以通过读取主循环外的第一行(当然检查有第一行)或使用布尔值或行计数处理特殊情况的循环内部来完成此操作。
答案 2 :(得分:0)
从我的观点来看,你做错了,你做错了。
LoadData()
每次读取“|”时都会读取令牌停止分隔符。
当找到“#Newbie 101”令牌时,它将以#字符开头丢弃它。
它的循环中的下一次迭代它将处理“Exam 1”令牌(下一个......在第一个行!!)。好的。
然后在下一次迭代中,它会读取下一个 “3 \ nPerson one” 。请注意字符串中间的行尾字符!
考虑到输出,我不确定它是你想要的,呵呵?
AFAI明白,您想要的行为是您的程序跳过注释行(以#字符开头)。
作为解决方案,您最好在第一个循环中使用getline(file_handle, line)
读取整行。不要指定任何“|”调用getline()时,字符作为第三个参数,'\ n'必须作为分隔符才能获得整个行。
在第一个循环中,添加第一个检查以查看“#”字符是否从该行开始。如果是这样,请调用continue语句。否则输入第二个嵌套循环来解释你的行中的所有标记,这次使用find_first_of()
字符串的方法来查找'|'字符。循环,直到你读完整行。
您可以考虑使用BOOST tokeniser lib。虽然我从来没有使用它(或很久以前我曾经使用它),但我记得以一种非常简单的方式完成那种工作是非常合适的! 我相信还有很好的库可以读取文件并丢弃注释行。也许在BOOST ......(这真是一个耻辱我真的需要深入了解这个lib ...)