读取文件:处理行的方式不同

时间:2021-10-14 21:54:39

I am having lots of troubles trying to read a file in C++. The main problem I'm having is reading properly the first line of the stream since it is different from all the other lines.

我在尝试用C ++读取文件时遇到了很多麻烦。我遇到的主要问题是正确读取流的第一行,因为它与所有其他行不同。

A sample file would be:

示例文件将是:

#Newbie 101|Exam 1|3
Person One|10
Person Two|20
Person Three|30

the first line starts with a # and declares the class name, assignmanet name and total students.

第一行以#开头,并声明类名,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);

    }

I really appreciate any suggestions on how to fix this code to read properly the file. Thanks a lot in advance!

我非常感谢有关如何修复此代码以正确读取文件的任何建议。非常感谢提前!

3 个解决方案

#1


Sounds like the reading / parsing of the first line should be outside (above) your loop. Then you will not have to worry about parsing 2 different types of lines in your main loop body.

听起来第一行的读取/解析应该在你的循环之外(上方)。然后,您不必担心在主循环体​​中解析2种不同类型的线。

#2


You just need to handle the first line separately as a special case. You could do this by reading in the first line (of course checking that there is a first line) outside the main loop or handling inside the loop for the special case, using a boolean or a line count.

您只需要将第一行作为特殊情况单独处理。您可以通过读取主循环外的第一行(当然检查有第一行)或使用布尔值或行计数来处理特殊情况的循环内部来完成此操作。

#3


From my point of view you are in the wrong way to do what you want.

从我的角度来看,你做错了什么就做你想做的事。

LoadData() will read token stopping each time it reads the '|' delimiter. When finding the "#Newbie 101" token it will discard it as it begins with # character. The next iteration in its loop it will handle "Exam 1" token (next one .. on the first line!!).Well ok. And then the next iteration, it reads the next one which is "3 \nPerson one". Please note the end of line character in the middle of the string! Considering the output, I am not sure it is what you want, huh?

每次读取“|”时,LoadData()都会读取令牌停止分隔符。当找到“#Newbie 101”标记时,它将以#字符开头丢弃它。在它的循环中的下一次迭代它将处理“检查1”令牌(下一个......在第一行!!)。好的。然后在下一次迭代中,它读取下一个“3 \ nPerson one”。请注意字符串中间的行尾字符!考虑到输出,我不确定它是你想要的,对吧?

AFAI understand, the behavior you want is your program to skip commented lines (begining with # character). As a solution, you'd better read a whole line instead with getline(file_handle, line) in a first loop. Do not specify any '|' character as the third parameter when calling getline(), '\n' must be taken as the delimiter to get the whole line.

AFAI明白,你想要的行为是你的程序跳过注释行(以#字符开头)。作为解决方案,您最好在第一个循环中使用getline(file_handle,line)读取整行。不要指定任何“|”调用getline()时,字符作为第三个参数,'\ n'必须作为分隔符才能获得整行。

In this first loop, add a first check to see whether a "#" character begins the line. If so , call the continue statement. Otherwise enter in a second nested loop to interpret all tokens in your line, this time using find_first_of() string's method to find the '|' character. Loop until you read the whole line.

在第一个循环中,添加第一个检查以查看“#”字符是否从该行开始。如果是,请调用continue语句。否则输入第二个嵌套循环来解释你的行中的所有标记,这次使用find_first_of()字符串的方法来查找'|'字符。循环,直到你读完整行。

You could either considering BOOST tokeniser lib. While I've never used it (or a very long time ago when I was sudent), I remember it was quite appropriated to do that kind of job in a very simple way! I believe there are also good libs to read a file and discard commented lines. Maybe in BOOST ... (That's a shame I really have to get a deeper look in this lib ...)

您可以考虑使用BOOST tokeniser lib。虽然我从来没有使用它(或者很久以前我曾经使用它),但我记得以非常简单的方式完成那种工作是非常合适的!我相信还有很好的库可以读取文件并丢弃注释行。也许在BOOST ...(这真是一个耻辱我真的需要深入了解这个lib ......)

#1


Sounds like the reading / parsing of the first line should be outside (above) your loop. Then you will not have to worry about parsing 2 different types of lines in your main loop body.

听起来第一行的读取/解析应该在你的循环之外(上方)。然后,您不必担心在主循环体​​中解析2种不同类型的线。

#2


You just need to handle the first line separately as a special case. You could do this by reading in the first line (of course checking that there is a first line) outside the main loop or handling inside the loop for the special case, using a boolean or a line count.

您只需要将第一行作为特殊情况单独处理。您可以通过读取主循环外的第一行(当然检查有第一行)或使用布尔值或行计数来处理特殊情况的循环内部来完成此操作。

#3


From my point of view you are in the wrong way to do what you want.

从我的角度来看,你做错了什么就做你想做的事。

LoadData() will read token stopping each time it reads the '|' delimiter. When finding the "#Newbie 101" token it will discard it as it begins with # character. The next iteration in its loop it will handle "Exam 1" token (next one .. on the first line!!).Well ok. And then the next iteration, it reads the next one which is "3 \nPerson one". Please note the end of line character in the middle of the string! Considering the output, I am not sure it is what you want, huh?

每次读取“|”时,LoadData()都会读取令牌停止分隔符。当找到“#Newbie 101”标记时,它将以#字符开头丢弃它。在它的循环中的下一次迭代它将处理“检查1”令牌(下一个......在第一行!!)。好的。然后在下一次迭代中,它读取下一个“3 \ nPerson one”。请注意字符串中间的行尾字符!考虑到输出,我不确定它是你想要的,对吧?

AFAI understand, the behavior you want is your program to skip commented lines (begining with # character). As a solution, you'd better read a whole line instead with getline(file_handle, line) in a first loop. Do not specify any '|' character as the third parameter when calling getline(), '\n' must be taken as the delimiter to get the whole line.

AFAI明白,你想要的行为是你的程序跳过注释行(以#字符开头)。作为解决方案,您最好在第一个循环中使用getline(file_handle,line)读取整行。不要指定任何“|”调用getline()时,字符作为第三个参数,'\ n'必须作为分隔符才能获得整行。

In this first loop, add a first check to see whether a "#" character begins the line. If so , call the continue statement. Otherwise enter in a second nested loop to interpret all tokens in your line, this time using find_first_of() string's method to find the '|' character. Loop until you read the whole line.

在第一个循环中,添加第一个检查以查看“#”字符是否从该行开始。如果是,请调用continue语句。否则输入第二个嵌套循环来解释你的行中的所有标记,这次使用find_first_of()字符串的方法来查找'|'字符。循环,直到你读完整行。

You could either considering BOOST tokeniser lib. While I've never used it (or a very long time ago when I was sudent), I remember it was quite appropriated to do that kind of job in a very simple way! I believe there are also good libs to read a file and discard commented lines. Maybe in BOOST ... (That's a shame I really have to get a deeper look in this lib ...)

您可以考虑使用BOOST tokeniser lib。虽然我从来没有使用它(或者很久以前我曾经使用它),但我记得以非常简单的方式完成那种工作是非常合适的!我相信还有很好的库可以读取文件并丢弃注释行。也许在BOOST ...(这真是一个耻辱我真的需要深入了解这个lib ......)