NinjaDeveloper NinjaDeveloper - 19 days ago 11
C++ Question

How to use input stream overloading to insert item to map member in class?

I have C++ class

Question
to hold data from a file
questions.txt
of multiple choice questions and answers:

update:
I have updated the &operator>> operator overload I have a couple of issue:

not read the first choice of the first Question "1.C"

Data in file questions.txt:

A programming language is used in this Course? 3

1. C
2. Pascal
3. C++
4. Assembly


I'm trying to insert the multiple answers into a map. I just want to ask how to overload
operator>>
to iterate over multiple answers to insert them into a map:

#include <string>
#include <iostream>
#include <sstream>
#include <map>
using namespace std;
class Question
{
string question;
int correctIndex;
map<int,string> answers;


friend std::istream &operator>>(std::istream &is, Question &q) {
getline(is, q.question, '?'); // stops at '?'
is>> q.correctIndex;
string line;
while (getline(is, line) && line.empty()) // skip leading blank lines
;
while (getline(is,line) && !line.empty()) // read until blank line
{
int id;
string ans;
char pt;
stringstream sst(line); // parse the line;
sst>>id>>pt; // take number and the following point
if (!sst || id==0 || pt!='.')
cout << "parsing error on: "<<line<<endl;
else {
getline (sst, ans);
q.answers[id] = ans;
}
}
return is;
}
};

int main()
{
ifstream readFile("questions.txt");//file stream
vector<Question> questions((istream_iterator<Question>(readFile)), istream_iterator<Question>());
}

Answer

The operator>> used for a string stops at the first blank separator. So for reading correctly the question you should consider:

friend std::istream &operator>>(std::istream &is, Question &q) {
    getline(is, q.question, '?');   // stops at '?'
    return is>> q.correctIndex;
    ... // to do:  for the answers (see below)
}

You could consider a similar approach, for reading each question, starting with its id. Unfortunatelyn , using operator>> on int will not allow us to detect the last answer: the reading attempt would fail with the start of a non-numeric text for the next question.

So you should consider reading line by line and parsing each line separately:

    ...    
    string line; 
    while (getline(is, line) && line.empty())  // skip leading blank lines
       ;  
    while (is && !line.empty())  // read until blank line 
    {
        int id;
        string ans; 
        char pt; 
        streamstring sst(line);    // parse the line;
        sst>>id>>pt;               // take number and the following point
        if (!sst  || id==0 || pt!='.') 
           cout << "parsing error on: "<<line<<endl; 
        else {
           getline (sst, ans); 
           q.answers[id] = ans; 
        }
        getline(is,line);
    }
Comments