GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 03-Feb-2008, 13:37
gfellows gfellows is offline
New Member
 
Join Date: Feb 2008
Posts: 2
gfellows is on a distinguished road

Run-time Error


Hi im pretty new to c++. I'm writing a small program to get myself familiar with pointers and dynamic memory allocation, but ican't figure out whats wrong with my code. get this error at run-time "Unhandled exception at 0x698fe138 (msvcr80d.dll) in CMultQuizDMA.exe: 0xC0000005: Access violation reading location 0xccccccc0."
CPP / C++ / C Code:
#include <iostream>
#include <cctype>
using namespace std;

//structure for a question
class CQuestion			
{
private:
	
	//private class properties
	char* Question;
	char* Answers[4];
	char CorrectAnswer;
	char GivenAnswer;
	
	//private function prototype as only used by other public functions
	bool isValid();

public:
	//constructor and deconstuctor prototypes
	CQuestion();
	CQuestion(char* , char* , char* , char* , char* , char );
	~CQuestion();
	
	//function prototypes
	void displayQuestion();
	void displayAnswers();
	void setAnswer();
	bool isCorrect();

	//static function for final display of score
	static void displayScore(int score)
	{
		switch (score)			
		{
			case 0:
			cout << "\nYou Scored 0 out of 5, Hang your head in shame.\n";
			break;
			case 1:
			cout << "\nYou Scored 1 out of 5, The worlds a complicated place isn't it.\n";
			break;
			case 2:
			cout << "\nYou Scored 2 out of 5, You almost impressed me.\n";
			break;
			case 3:
			cout << "\nYou Scored 3 out of 5, Not bad for a C student.\n";
			break;
			case 4:
			cout << "\nYou Scored 4 out of 5, You've got the minerals.\n";
			break;
			case 5:
			cout << "\nYou Scored 5 out of 5, Well Done! Now go cure cancer.\n";
			break;
			default:
			cout << "\nYou Scored " << score << " out of 5, which makes me a poor programmer.\n";
			break;
		};
	};

	
};

CQuestion::CQuestion()
{
	
	Question = NULL;

	for(int i = 0; i < 4; i++)
	{
			Answers[i] = NULL;
	};
	
	CorrectAnswer = NULL;

	GivenAnswer = NULL;
}

CQuestion::CQuestion(char* myQuestion, char* myAnswerA, char* myAnswerB, char* myAnswerC, char* myAnswerD, char myCorrectAnswer) 
{
	
	if (Question != NULL)
	{
		delete [] Question;
	};

	Question = new char[strlen(myQuestion) + 1]; 
	strcpy(Question, myQuestion);

	for (int i = 0; i < 4; i++)
	{
		if (Answers[i] != NULL)
		{
			delete [] Answers[i];
		};
	};

	Answers[0] = new char[strlen(myAnswerA) + 1];
	strcpy(Answers[0], myAnswerA);

	Answers[1] = new char[strlen(myAnswerB) + 1];
	strcpy(Answers[1], myAnswerB);

	Answers[2] = new char[strlen(myAnswerC) + 1];
	strcpy(Answers[2], myAnswerC);

	Answers[3] = new char[strlen(myAnswerD) + 1];
	strcpy(Answers[3], myAnswerD);
	

	CorrectAnswer = myCorrectAnswer;
	GivenAnswer = NULL;
}

CQuestion::~CQuestion()
{
	delete [] Question;
	for (int i = 0; i < 4; i++)
	{
		delete [] Answers[i];
	};
}

void CQuestion::displayQuestion()
{
	cout << "The question is...\n\n" << Question << "\n\n";
}

void CQuestion::displayAnswers()
{
	char Letter = 'A';
	
	for(int i = 0; i < 4; i++)			
		{
			cout << Letter++ << ": " << Answers[i] << "\n"; //note post-increment on letter char
		};
}

void CQuestion::setAnswer()
{
	cout << "\nPlease Answer A, B, C or D\n\n";
	cin >> GivenAnswer;
	
	while (!isValid())
	{
		cin >> GivenAnswer;
	};
}

bool CQuestion::isCorrect()
{
	//checks uppercase of users answer against correct answer and adjusts score
	if(toupper(GivenAnswer) == CorrectAnswer)	
	{
		cout << "\nThat was the correct answer.\n\n";
		return true;
	}
	else
	{
		cout << "\nThat was the incorrect answer.\n\n"
			 << "The correct answer was " << CorrectAnswer << "\n\n";
		return false;
	};
}

bool CQuestion::isValid()
{
	if (toupper(GivenAnswer) < 'A' || toupper(GivenAnswer) > 'D')		
	{
		cout << "\nInvalid Answer, Please Re-enter\n\n";
		return false;
	}
	else
	{
		return true;
	};
}



void main(void)
{
	int TotalRightAnswers = 0;	//keeps track of the users score
	
	CQuestion One("What is the capital of Belarus?", "Minsk", "Tirana", "Sarajevo", "Bratislava", 'A');
	CQuestion Two("Who was the first man in space?", "Neil Armstrong", "Yuri Gagarin", "Buzz Aldrin", "Noam Chomsky", 'B');
	CQuestion Three("What is the maximum speed limit on a single carriageway?", "70mph", "65mph", "80mph", "60mph", 'D');
	CQuestion Four("Who was the 21st President of America?", "Grover Cleveland", "Chester A. Arthur", "Benjamin Harrison", "James Garfield", 'B');
	CQuestion Five("What is 4 to the power of 3", "68", "62", "64", "58", 'C');

	CQuestion* TheQuestions[5];

	TheQuestions[0] = &One;
	TheQuestions[1] = &Two;
	TheQuestions[2] = &Three;
	TheQuestions[3] = &Four;
	TheQuestions[4] = &Five;

	for (int i = 0; i < 5; i++)
	{
		TheQuestions[i]->displayQuestion();
		TheQuestions[i]->displayAnswers();
		TheQuestions[i]->setAnswer();
		if (TheQuestions[i]->isCorrect())
		{
			TotalRightAnswers++;
		};
	}

	CQuestion::displayScore(TotalRightAnswers);

};

any help will be appreciated
  #2  
Old 04-Feb-2008, 06:27
davis
 
Posts: n/a

Re: Run-time error


You have quite a few problems with your code. First, and most immediately obvious is that main must return an int in C++.

Your problem is in how you are declaring your private Question and Answers members and how you are using then in your overloaded (args) constructor.

You seem to be "protecting" yourself from the possibility that Question and/or Answer may come to you "already used" in some previous manner. Think about it, when is the only time that your ctor can be used? The member pointers are uninitialized but not NULL and they were not dynamically allocated so they will immediately blow up.

Another thing, but much less obvious is that you are "grading on a curve." 3 out of 5 is not too bad for a C student? When is a '60' a passing grade? One has to achieve 4 out of 5 to obtain a "low B."

I think that what you need to do is to step through your code with a debugger and check the values of each variable that you have in your code as you step. See what your code does to each of these--particularly the pointer types--and then see what happens as you step. As you step, the "next line" that you get to will "blow up" in various places. That is a clue as to what you're doing wrong.

Here are some changes that may help you:

CPP / C++ / C Code:
#include <iostream>
#include <cctype>
using namespace std;

//structure for a question
class CQuestion         
{
private:

    //private class properties
    char* Question;
    char* Answers[4];
    char CorrectAnswer;
    char GivenAnswer;

    //private function prototype as only used by other public functions
    bool isValid();

public:
    //constructor and deconstuctor prototypes
    CQuestion();
    CQuestion(char* , char* , char* , char* , char* , char );
    ~CQuestion();

    //function prototypes
    void displayQuestion();
    void displayAnswers();
    void setAnswer();
    bool isCorrect();

    //static function for final display of score
    static void displayScore(int score)
    {
        switch( score )
        {
        case 0:
            cout << "\nYou Scored 0 out of 5, Hang your head in shame.\n";
            break;
        case 1:
            cout << "\nYou Scored 1 out of 5, The worlds a complicated place isn't it.\n";
            break;
        case 2:
            cout << "\nYou Scored 2 out of 5, You almost impressed me.\n";
            break;
        case 3:
            cout << "\nYou Scored 3 out of 5, Not bad for a C student.\n";
            break;
        case 4:
            cout << "\nYou Scored 4 out of 5, You've got the minerals.\n";
            break;
        case 5:
            cout << "\nYou Scored 5 out of 5, Well Done! Now go cure cancer.\n";
            break;
        default:
            cout << "\nYou Scored " << score << " out of 5, which makes me a poor programmer.\n";
            break;
        }
    }


};

CQuestion::CQuestion()
{

    Question = NULL;

    for( int i = 0; i < 4; i++ )
    {
        Answers[i] = NULL;
    }

    CorrectAnswer = 0;

    GivenAnswer = 0;
}

CQuestion::CQuestion(char* myQuestion, char* myAnswerA, char* myAnswerB, char* myAnswerC, char* myAnswerD, char myCorrectAnswer) 
{
    /*
    if (Question != NULL)
    {
        delete [] Question;
    };
    */
    Question = new char[strlen(myQuestion) + 1]; 
    strcpy(Question, myQuestion);
    /*
    for (int i = 0; i < 4; i++)
    {
        if (Answers[i] != NULL)
        {
            delete [] Answers[i];
        }
    }
    */
    Answers[0] = new char[strlen(myAnswerA) + 1];
    strcpy(Answers[0], myAnswerA);

    Answers[1] = new char[strlen(myAnswerB) + 1];
    strcpy(Answers[1], myAnswerB);

    Answers[2] = new char[strlen(myAnswerC) + 1];
    strcpy(Answers[2], myAnswerC);

    Answers[3] = new char[strlen(myAnswerD) + 1];
    strcpy(Answers[3], myAnswerD);


    CorrectAnswer = myCorrectAnswer;
    GivenAnswer = 0;
}

CQuestion::~CQuestion()
{
    delete [] Question;
    for( int i = 0; i < 4; i++ )
    {
        delete [] Answers[i];
    }
}

void CQuestion::displayQuestion()
{
    cout << "The question is...\n\n" << Question << "\n\n";
}

void CQuestion::displayAnswers()
{
    char Letter = 'A';

    for( int i = 0; i < 4; i++ )
    {
        cout << Letter++ << ": " << Answers[i] << "\n"; //note post-increment on letter char
    }
}

void CQuestion::setAnswer()
{
    cout << "\nPlease Answer A, B, C or D\n\n";
    cin >> GivenAnswer;

    while( !isValid() )
    {
        cin >> GivenAnswer;
    }
}

bool CQuestion::isCorrect()
{
    //checks uppercase of users answer against correct answer and adjusts score
    if( toupper(GivenAnswer) == CorrectAnswer )
    {
        cout << "\nThat was the correct answer.\n\n";
        return true;
    }
    else
    {
        cout << "\nThat was the incorrect answer.\n\n"
        << "The correct answer was " << CorrectAnswer << "\n\n";
        return false;
    }
}

bool CQuestion::isValid()
{
    if( toupper(GivenAnswer) < 'A' || toupper(GivenAnswer) > 'D' )
    {
        cout << "\nInvalid Answer, Please Re-enter\n\n";
        return false;
    }
    else
    {
        return true;
    }
}



int main(void)
{
    int TotalRightAnswers = 0;  //keeps track of the users score

    CQuestion One("What is the capital of Belarus?", "Minsk", "Tirana", "Sarajevo", "Bratislava", 'A');
    CQuestion Two("Who was the first man in space?", "Neil Armstrong", "Yuri Gagarin", "Buzz Aldrin", "Noam Chomsky", 'B');
    CQuestion Three("What is the maximum speed limit on a single carriageway?", "70mph", "65mph", "80mph", "60mph", 'D');
    CQuestion Four("Who was the 21st President of America?", "Grover Cleveland", "Chester A. Arthur", "Benjamin Harrison", "James Garfield", 'B');
    CQuestion Five("What is 4 to the power of 3", "68", "62", "64", "58", 'C');

    CQuestion* TheQuestions[5];

    TheQuestions[0] = &One;
    TheQuestions[1] = &Two;
    TheQuestions[2] = &Three;
    TheQuestions[3] = &Four;
    TheQuestions[4] = &Five;

    for( int i = 0; i < 5; i++ )
    {
        TheQuestions[i]->displayQuestion();
        TheQuestions[i]->displayAnswers();
        TheQuestions[i]->setAnswer();
        if( TheQuestions[i]->isCorrect() )
        {
            TotalRightAnswers++;
        }
    }

    CQuestion::displayScore(TotalRightAnswers);

}


There are some other "finer points" to C++ design and object architecture that you are (expectedly) missing. For example, your code tightly integrates user I/O with the CQuestion class. In using good object-oriented practices, we would expect that Question would represent everything that ISA question. The answer could arguably be said to have NOTHING to do with the implementation of a "Question" class. Also, but probably not something you're ready yet to consider is that in OOP, we would want our Question class to be able to be used ANYWHERE a Question was needed...even is situations such as a "rhetorical" question. Once you better understand the basics, you'll be ready to move on to some of the finer points of quality class design. However, between now and then, you may want to consider ways that you can separate user I/O from those classes that "naturally" are "holders" of data. It wouldn't be unrealistic to think that perhaps your class would be better implemented as a Q&A class, with a legal name. Something like a 1:1 Q:A in the class as members.

You see, it is "kinda funny" when we ask ourselves WHAT IS A CQuestion and part of how it is implemented in this case is having 3 wrong answers. What about all of the other possible wrong answers? Aren't they somehow related to CQuestion in someway too?

Hopefully I haven't done more to confuse you than help clarify...


:davis:
  #3  
Old 04-Feb-2008, 08:02
gfellows gfellows is offline
New Member
 
Join Date: Feb 2008
Posts: 2
gfellows is on a distinguished road

Re: Run-time error


Thanks davis the problem was where you said when i removed the checking in the constructor that my pointers were already pointing to allocated memory it ran with no errors.

I see what your saying about my implementation of a question class, this is part of a college course i'm taking and is mean't to be very specific to multiple choice questions with four possible answers.

Thanks for your help, was greatly apprieciated.
  #4  
Old 04-Feb-2008, 10:16
davis
 
Posts: n/a

Re: Run-time error


Quote:
Originally Posted by gfellows
I see what your saying about my implementation of a question class, this is part of a college course I'm taking and is meant to be very specific to multiple choice questions with four possible answers.

With that, then the "name" for your class is "wrong." What the "right" name is eludes me...but something like CQnAGame might be more appropriate...

Generally speaking, junior-level college courses (their instructors?) tend toward teaching fundamental skills at the expense of good "reusable code" traits. In some ways I can understand the challenges of teaching the basics.

It is sort of like applying grease to your car brakes so that they don't squeal when the instructor is solely focused on teaching you how to depress the brake pedal. Something ain't right...but at least they taught you how to push the pedal down. ...let the "next guy" teach you about quality friction surface maintenance...too complicated for we "fundamentals" guys.

Maybe I just expect too much, as fakepoo once pointed out?

Quote:
Originally Posted by fakepoo
"perfect by davis standard"

If a 60% grade is failing, at what level of "perfection" is an 80% grade? At what standard does one confer an 'A' to a grade recipient? Is it 'A' worthy if the core of the lesson is successfully implemented at the expense of "other areas" of good coding practices?

...oh well, I've strayed a bit far from the topic on this reply.


:davis:
 
 

Recent GIDBlogFlickr uploads of IA pictures by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Major newbie problem cynack MS Visual C++ / MFC Forum 1 08-Apr-2007 11:25
Winsock error when compiling FLTK 2.0 Projects mauriciorossi FLTK Forum 3 16-Aug-2005 10:18
Help with syntax errors PeteGallo C Programming Language 7 08-Aug-2005 20:30
What is "Ambigious symbol" ??*( a compilation error) small_ticket C++ Forum 2 07-Jan-2005 21:10
Can enum have same name as class? crystalattice C++ Forum 3 08-Dec-2004 16:43

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 16:18.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.