Search code examples
c++while-loopifstream

reading from text file to struct vector, but text file lines are of different length


I am trying to read from a text file of students and assign each line to a struct data member.

The text file structure is as follows:

Name,Student code, Ability,Consistency,Program name:Subject list

Two students in the file:

Average Ant,204932,50,5,Short course:1
Brilliant Bison,234543,80,3,Bachelor of Bounciness:2,5,3

I can read all of the information to a struct no problem except for the last part(subject list),that are of varying length between students. How can I write code so that if a student only has 1 subject like average ant I can push it into the subjectList vector but if they have 3 like brilliant bison I can still push them all in no problem?

My code:

struct Student
{
    string name;
    int code;
    int ability;
    int consistency;
    string programName;
    vector<int> subjectList;
};

void createStudents(string fileName)
{
    string tempSubjectId;
    int subjectId;

    //temp variable to then use to convert them to int.
    string codeTemp, abilityTemp, consistencyTemp;

    std::ifstream studentFile(fileName);

    //A new student data member is created
    Student newStudent;


    if(studentFile.is_open() && studentFile.good())
    {
        cout << " " << endl;
        cout << "---Reading from Students---" << endl;
        while(getline(studentFile,newStudent.name, ','))
        {

            //we go get each value which is delimited by a comma and one by a colon
            //getline(studentFile, newStudent.name, ',');

            //To convert the strings to an int, the string is given to a temporary variable
            //Then the temporary variable is parsed to an int using stoi and the code datamember from the struct is assign to that new int
            getline(studentFile, codeTemp, ',');
            newStudent.code = stoi(codeTemp);

            getline(studentFile, abilityTemp, ',');
            newStudent.ability = stoi(abilityTemp);

            getline(studentFile, consistencyTemp, ',');
            newStudent.consistency = stoi(consistencyTemp);

            getline(studentFile, newStudent.programName, ':');

//want to push ints into subject list here.


            //The new struct data member is added to the vector and returned for further use.
            studentList.push_back(newStudent);
        }
        //file is then closed
        studentFile.close();```

Solution

  • In your main loop, read an entire line into a std::string, then use a std::istringstream to parse each line, using an inner loop to read the subject ints, eg :

    #include <string>
    #include <sstream>
    #include <fstream>
    #include <vector>
    
    struct Student
    {
        std::string name;
        int code;
        int ability;
        int consistency;
        std::string programName;
        std::vector<int> subjectList;
    }; 
    
    std::vector<Student> studentList;
    
    void createStudents(std::string fileName)
    {
        std::string tempLine;
    
        //temp variable to then use to convert them to int.
        std::string tempStr;
    
        std::ifstream studentFile(fileName);
    
        if (studentFile.is_open())
        {
            std::cout << " " << std::endl;
            std::cout << "---Reading from Students---" << std::endl;
    
            while (std::getline(studentFile, tempLine))
            {
                std::istringstream iss(tempLine);
    
                //A new student data member is created
                Student newStudent;
    
                //we go get each value which is delimited by a comma and one by a colon
    
                std::getline(iss, newStudent.name, ',');
    
                //To convert the strings to an int, the string is given to a temporary variable
                //Then the temporary variable is parsed to an int using stoi and the code datamember from the struct is assign to that new int
                std::getline(iss, tempStr, ',');
                newStudent.code = std::stoi(tempStr);
    
                std::getline(iss, tempStr, ',');
                newStudent.ability = std::stoi(tempStr);
    
                std::getline(iss, tempStr, ',');
                newStudent.consistency = std::stoi(tempStr);
    
                std::getline(iss, newStudent.programName, ':');
    
                // push ints into subject list
                while (std::getline(iss, tempStr, ',')) {
                    newStudent.subjectList.push_back(std::stoi(tempStr));
                } 
    
                //The new struct data member is added to the vector and returned for further use.
                studentList.push_back(std::move(newStudent));
            }
    
            //file is then closed
            studentFile.close();
        }
    }