2

I am reading in a file, that contains data in this format on each line. 30304 Homer Simpson I need to be able to pass this to the following constructor, the integer being the regNo, the name the rest of the string, and every student would have their own map of marks.

Student::Student (string const& name, int regNo):Person(name)
{
    regNo = regNo;
    map<string, float> marks;

} 

I then have to add each student to a collection of students, which would be best, and how do I do this?

So far all I've got is getting the file name and checking it exists.

int main()
{
    //Get file names
    string studentsFile, resultsFile, line;
    cout << "Enter the Students file: ";
    getline(cin, studentsFile);
    cout << "Enter the results file: ";
    getline(cin, resultsFile);

    //Check for students file
    ifstream students_stream(studentsFile);
    if (!students_stream) {
        cout << "Unable to open " << studentsFile << "\n";
        return 1;
    }
}

I tried using getline with 3 arguments and " " as the delimiter but that would also split the name part of the string, so I'm not sure how to do this another way.

Chaz
  • 195
  • 4
  • 17
  • 1
    Here's a hint: If you expect a "first name" and a "last name", they could be considered as two strings :-) – AndyG Jan 12 '17 at 13:18

3 Answers3

3

Replace std::cin with your input file stream of course. It would be probably sane to "trim" the name result, unless you know by 100% the input is well formatted. I added only bare-minimal error state handling to somehow "survive".

Names are read also for single/three/more variants of course, as any real world application should.

#include <iostream>
#include <string>
#include <stdexcept>

int main()
{
    std::string line, name;
    unsigned long long regNo;
    size_t nameOfs;
    while (true) {
        // Read full non-empty line from input stream
        try {
            std::getline(std::cin, line);
            if (line.empty()) break;
        }
        catch(const std::ios_base::failure & readLineException) {
            break;
        }
        // parse values:
        // 1. unsigned long long ending with single white space as "regNo"
        // 2. remaining part of string is "name"
        try {
            regNo = std::stoull(line, &nameOfs);
            name = line.substr(nameOfs + 1);
        }
        catch(const std::logic_error & regNoException) {
            // in case of invalid input format, just stop processing
            std::cout << "Invalid regNo or name in line: [" << line << "]";
            break;
        }
        // here values regNo + name are parsed -> insert them into some vector/etc.
        std::cout << "RegNo [" << regNo << "] name [" << name << "]\n";
    }
}
Ped7g
  • 16,236
  • 3
  • 26
  • 63
1

A regular expression could be used: enter image description here We can then select group 2 and 3 from the result.

std::vector<Student> students;
std::regex r{R"(((\d+) )(.+))"};
for(std::string line; getline(students_stream, line);) {
    auto it = std::sregex_iterator(line.begin(), line.end(), r);
    auto end = std::sregex_iterator();
    if(it == end || it->size() != 4)
        throw std::runtime_error("Could not parse line containing the following text: " + line);
    for(; it != end; ++it) {
        auto match = *it;
        auto regNo_text = match[2].str();
        auto regNo{std::stoi(regNo_text)};
        auto name = match[3].str();
        students.emplace_back(name, regNo);
    }
}

Live demo

wally
  • 10,717
  • 5
  • 39
  • 72
0

You can take input using getline()and read one complete line(no third argument) and then use stringstream to extract the number and the remaining string. Example of stringstream:

string s = "30304 Homer Simpson", name;
stringstream ss(s);
int num;
ss >> num;        //num = 30304
getline(ss, name);   //name = Homer Simpson
cout << num;
cout << name;
XZ6H
  • 1,779
  • 19
  • 25
  • If you go with this solution, try and improve it to handle any number of names (e.g. "Mary Ann Joseph"). In its current form, I believe it would ignore any name past the first 2. – merlinND Jan 12 '17 at 13:58
  • @merlinND Fixed it – XZ6H Jan 12 '17 at 14:09