0

I have included both my definition of the Question class and its implementation, the first is a header file and the second a cpp file.

I put comments in to show where the problem is. For some reason under the constructor I can cout the questionText just fine but when I try to do this under the getQuestionText function it just outputs an empty string? Any help would be most appreciated!! Thanks!

#include <string>
#include <vector>
#include <iostream>

using namespace std;

#ifndef QUESTION_H
#define QUESTION_H

class Question{
public:
    Question(int thePointValue, int theChapterNumber, \
        string theQuestionText);
    int getPointValue() const;
    int getChapterNumber() const;
    string getQuestionText() const;
    virtual void writeQuestion(ostream& outfile) const;
    virtual void writeKey(ostream& outfile) const;

private:
    int pointValue;
    int chapterNumber;
    string questionText;

    void writePointValue(ostream& outfile) const;
};




#endif





#include "Question.h"

Question::Question(int thePointValue, int theChapterNumber, \
        string theQuestionText)
{
    pointValue = thePointValue;
    chapterNumber = theChapterNumber;
    questionText = theQuestionText;

        //HERE THIS WORKS PERFECTLY
        cout << questionText << endl;
}

int Question::getPointValue() const
{
    return pointValue;
}

int Question::getChapterNumber() const
{
    return chapterNumber;
}

string Question::getQuestionText() const
{
        //THIS IS THE PROBLEM. HERE IT OUPUTS AN EMPTY STRING NO MATTER WHAT!
        cout << questionText << endl;
    return questionText;
}

void Question::writeQuestion(ostream& outfile) const
{
    writePointValue(outfile);
    outfile << questionText << endl;
}

void Question::writeKey(ostream& outfile) const
{
    writePointValue(outfile);
    outfile << endl;
}

void Question::writePointValue(ostream& outfile) const
{
    string pt_noun;

    if (pointValue == 1)
        pt_noun = "point";
    else
        pt_noun = "points";

    outfile << "(" << pointValue << " " << pt_noun << ") ";
}

vector<Question *> QuestionsList(string filename, int min, int max)
{
vector<Question *> QuestionList;

string line;
vector<string> text;
ifstream in_file;
in_file.open(filename.c_str());
while (getline(in_file, line))
{
    text.push_back(line);
}

string type;
for(int i = 0; i < text.size(); i ++)
{
    int num = text[i].find('@');
    type = text[i].substr(0, num);
    if (type == "multiple")
    {
        MultipleChoiceQuestion myq = matchup(text[i]);
        MultipleChoiceQuestion* myptr = &myq;
        if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
        {
            QuestionList.push_back(myptr);
        }
    }
    if (type == "short")
    {
        ShortAnswerQuestion myq = SAmatchup(text[i]);
        ShortAnswerQuestion* myptr = &myq;
        if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
        {
            QuestionList.push_back(myptr);
        }
    }
    if (type == "long")
    {
        LongAnswerQuestion myq = LAmatchup(text[i]);
        LongAnswerQuestion* myptr = &myq;
        if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
        {
            QuestionList.push_back(myptr);
        }
    }
    if (type == "code")
    {
        CodeQuestion myq = CODEmatchup(text[i]);
        CodeQuestion* myptr = &myq;
        if (myq.getChapterNumber() >= min && myq.getChapterNumber() <= max)
        {
            QuestionList.push_back(myptr);
        }
    }
    cout << QuestionList[QuestionList.size()-1]->getQuestionText() << endl;
}
for (int i = 0; i < QuestionList.size(); i ++)
{
    int numm = QuestionList.size();
    cout << QuestionList[numm-1]->getQuestionText() << endl;
}
return QuestionList;

}

then when i call this in main the code breaks

vector<Question *> list = QuestionsList(pool_filename, min_chapter, max_chapter);
cout << list[0]->getQuestionText() << endl;
Shoe
  • 70,092
  • 30
  • 150
  • 251
  • You are initializing something to string at some point in your main right? – RyPope Mar 27 '13 at 01:37
  • Show how the `Question` object is initialized at the point it's being used. You are calling the constructor that takes arguments, not a the default (empty) one, right? – Christian Garbin Mar 27 '13 at 01:39
  • May we see a [sscce](http://sscce.org)? – chris Mar 27 '13 at 01:39
  • This program [compiles and executes correctly](http://coliru.stacked-crooked.com/view?id=82cb72807cc7e1b9c1d9bf63460224cf-50d9cfc8a1d350e7409e81e87c2653ba). – Shoe Mar 27 '13 at 01:43
  • In the main `Question q(1, 1, "TestString"); q.getQuestionText();` prints `TestString TestString`. – Shoe Mar 27 '13 at 01:44
  • The program has no problem compiling the problem is when i am in the main function and call: vector list = QuestionsList(pool_filename, min_chapter, max_chapter); cout << list[0]->getQuestionText() << endl; you get an error on the cout part and it crashes – user1852078 Mar 27 '13 at 01:54
  • 1
    What is a `QuestionsList`? Please produce ALL the relevant code. – JBentley Mar 27 '13 at 02:00
  • 1
    Are you sure you need a vector of pointers, and not just actual objects? Vectors of raw pointers always make me cringe. – chris Mar 27 '13 at 02:00

1 Answers1

1

You are declaring, multiple times in your code, local objects and storing their pointer into the QuestionList vector (returned by the function) which, at the end of the function block, will contains dangling pointers.

MultipleChoiceQuestion myq = matchup(text[i]); // < local object
MultipleChoiceQuestion* myptr = &myq; // < pointer to local object

QuestionList.push_back(myptr); // < push back into vector

At this point you can either use dynamic memory allocation (I suggest you not to do that unless you are absolutely forced, and even in that case use one of the smart pointers provided by the standard library) or store the objects directly inside the vector.

Community
  • 1
  • 1
Shoe
  • 70,092
  • 30
  • 150
  • 251