简体   繁体   中英

Reading all data from a file

I am writing a program to display a grade report for students from a text file. I am having a problem with listing the courses for the student correctly because the first course is skipped and replaced with the first string from the next line from the file. I'm also only able to display the results for only one student in the file instead of all the students.

I'm not sure how to address the skipped course in the data. I've tried adjusting the beginning loop a few different ways but I either get the result I currently have or a continuous loop of only one student

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main() {

    string ID, lastName, firstName;
    char midInt, sex, letterGrade;
    string phoneNum, classLevel, courseName;
    int regCourses, courseCredit;
    double numGrade, totalNumGrade;
    int credits2018, credits2019;
    double cumGPA2018, cumGPA2019;
    int i;
    ofstream out_stream;
    ifstream in_stream;

    in_stream.open("C:/Users/mss3s_000/Desktop/Stud.txt");

    if (in_stream.fail()) {
        cout << "Input file opening fail.\n";
        exit(1);
    }


    if (!in_stream.eof()) { //I think the issue with not reading all the data is with this loop, but I'm not sure.
        while (in_stream >> ID >> lastName >> firstName >> midInt >> phoneNum >> sex >> classLevel >> credits2018 >> cumGPA2018 >> regCourses >> courseName >> courseCredit >> letterGrade) {

             switch (sex) {
                case 'M':
                    /*sex = "Male";*/
                    break;
                case 'F':
                    /*sex = "Female";*/
                    break;
            }

            if (classLevel == "FR")
                classLevel = "Freshman";
            else if (classLevel == "SO")
                classLevel = "Sophomore";
            else if (classLevel == "JR")
                classLevel = "Junior";
            else if (classLevel == "SR")
                classLevel = "Senior";

            if(letterGrade == 'A')
                numGrade = 4.0;
            else if(letterGrade == 'B')
                numGrade = 3.0;
            else if(letterGrade == 'C')
                numGrade = 2.0;
            else if(letterGrade == 'D')
                numGrade = 1.0;
            else if(letterGrade == 'F')
                numGrade = 0.0;

            cout << "**************************************************" << endl;
            cout << "Student ID number: " << ID << endl;
            cout << "Name: " << lastName << ", " << firstName << " " << midInt << endl;
            cout << "Tel: " << phoneNum << endl;
            cout << "Gender: " << sex << endl;
            cout << "Class Level: " << classLevel << endl;


            if (regCourses == 0) {
                cout << "Registration of Spring 2019: " << "No" << endl;
                cout << "**************************************************" << endl;


            }

            cout << "Registration of Spring 2019: " << "Yes" << endl;
            cout << "\n Unofficial Report Card" << endl;
            cout << "COURSE     CREDITS      GRADE" << endl;
            cout << "======     =======     ======" << endl;
            credits2019 = 0;
            cumGPA2019 = 0.0;

            for (i = 1; i <= regCourses; i++) { //I thought this loop would show all the courses but it is skipping the first course
                in_stream >> courseName;
                in_stream >> courseCredit;
                in_stream >> letterGrade;


                if (letterGrade != 'W') {
                    credits2019 += courseCredit;
                    totalNumGrade += (courseCredit * numGrade);
                    cumGPA2019 = totalNumGrade / credits2019;
                }
                cout << courseName << " " << courseCredit << " " << letterGrade << endl;
                out_stream << courseName << " " << courseCredit << " " << letterGrade << endl;
            }

            cout.setf(ios::fixed);
            cout.setf(ios::showpoint);
            cout.precision(2);
            cout << "\nCredits for Spring 2019: " << credits2019 << endl;
            cout << "GPA till Fall 2018: " << cumGPA2018 << endl;
            cout << "Total Credits: " << (credits2018 + credits2019) << endl;
            cout << "New Cumulative GPA: " << ((credits2019 * cumGPA2019) + (credits2018*cumGPA2018)) / (credits2019 + credits2018) << endl;
            cout << "**************************************************\n" << endl;

        }
    }
    in_stream.close();


    return 0;
}

I expected to have all classes listed under the course heading and to display the information for all students in the file.

You can read the file line by line using getline() and check the return value to know if you have reached the end of the file or not.

I have made a simple example that read all data from the file and load them into a "list of students".

This is how you could do it:

data file

name:Bob
sex:Male
age:18
name:Alice
sex:female
age:16

C++ code

#include <iostream>
#include <fstream>
#include <vector>

struct Student
{
    std::string name;
    std::string sex;
    std::string age;

    void clear()
    {
        name.clear();
        sex.clear();
        age.clear();
    }
};

std::pair <std::string, std::string> breakdown(const std::string & line);

int main()
{
    std::string data_file("../tmp_test/data.txt");
    std::vector <Student> students;

    std::ifstream in_s(data_file);
    if(in_s)
    {
        std::string line;
        Student current;
        while(getline(in_s, line))
        {
            std::pair <std::string, std::string> pair = breakdown(line);
            if(pair.first == "name") // first field
            {
                current.name = pair.second;
            }
            else if(pair.first == "sex")
            {
                current.age = pair.second;
            }
            else if(pair.first == "age") // last field
            {
                current.sex = pair.second;
                students.push_back(current);
                current.clear(); // Not necessary
            }
            else
                std::cout << "Info: Unknown field encountered !" << std::endl;
        }

        in_s.close();
    }
    else
        std::cout << ("Error: Could not open file: " + data_file) << std::endl;

    // Do what you want with the loaded data
    for(Student s : students)
    {
        std::cout << "Name: " << s.name << "\nSex: " << s.sex << "\nAge: " << s.age << "\n";
        std::cout << std::endl;
    }

    return 0;
}

std::pair <std::string, std::string> breakdown(const std::string & line)
{
    bool found(false);
    unsigned int i;
    for(i = 0; !found && (i < line.length()); ++i)
    {
        if(line[i] == ':')
        {
            found = true;
            --i;
        }
    }
    if(found)
        return std::make_pair<std::string, std::string>(line.substr(0, i), line.substr(i+1, line.size()-i));
    else
        return std::make_pair<std::string, std::string>("", "");
}

outpout

Name: Bob
Sex: 18
Age: Male

Name: Alice
Sex: 16
Age: female

It worked well for me.
Of course, I didn't handle if the data file is corrupted, ... But it is not the point here. I tried to make it as simple as possible just to show how it could be done.

I hope it can help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM