You're welcome for the help. Was that your version that worked or did you just verify that mine works?
High school huh? Nice early start for you then! I'm a little older. My son is a H.S. senior this year.
I wanted to post back once more because I finally have my newest version of this working fully. I have takeQuiz() now reading questions and answers from text files (one file for each subMenu item). This program will give a multi-question quiz and score it. Missed answers are followed by the correct answer during the quiz.
The program is simpler than the one I posted earlier in some ways. Note how all info for the menus is in one place, the INITmenus() function.
The use of structures, vectors, strings and all the file I/O makes it more complex though.
It is still a single source file program (with nothing in extra header files). The program needs to have correctly named and placed text files for it to work though. More about that following the program code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;
struct menuData
{
unsigned int Nchoices;
string title;
vector<string> topics;
vector<string> fileName;
};
// function prototypes
void INITmenus( menuData& Mdata, vector<menuData>& SubData );
void LISTfileNames(const menuData& Mdata, const vector<menuData>& SubData );
unsigned int Menu(const menuData& Mdata );// display any Menu and get topic choice as a selection #
unsigned int takeQuiz(unsigned int mChoice, unsigned int sChoice, const menuData& Mdata, const vector<menuData>& SubData );
unsigned int askQuestion( const string& Q, const string& A );
//** main function **
int main()
{
menuData mainData;
vector<menuData> subData;
INITmenus( mainData, subData );
// LISTfileNames( mainData, subData );// uncomment for a list of all required file names
// Geometry\Circles.txt
unsigned int mainChoice = Menu( mainData );
unsigned int subChoice = Menu( subData[mainChoice-1] );
unsigned int quizScore = takeQuiz( mainChoice, subChoice, mainData, subData );
cout << "You scored " << quizScore << " points." << endl;
return 0;
}// end of main()
// function definitions
unsigned int askQuestion( const string& Q, const string& A )
{
string Auser;
cout << Q << " ";
cin >> Auser;
if( Auser == A )
{
cout << "Correct!" << endl << endl;
return 1;
}
else
{
cout << "Wrong! The correct answer is: " << A << endl << endl;
return 0;
}
}// end of askQuestion()
unsigned int takeQuiz(unsigned int mChoice, unsigned int sChoice, const menuData& Mdata, const vector<menuData>& SubData )
{
string fName( Mdata.fileName[mChoice-1] );
fName.append( SubData[mChoice-1].fileName[sChoice-1] );
//** input file **
vector<string> question;
vector<string> answer;
string q_temp, a_temp;
ifstream inFile( fName.c_str() );
if( inFile )
{
cout << fName << " was opened." << endl;
while( !inFile.eof() )
{
getline( inFile, q_temp, '\n' );
question.push_back( q_temp );
getline( inFile, a_temp, '\n' );
answer.push_back( a_temp );
}
cout << "Nquestions = " << question.size() << endl;
// Done! close-up
inFile.close();
}
else
cout << fName << " was NOT opened." << endl;
// ready for quiz
unsigned int score = 0;
if( question.size() > 0 )
{
cout << "\n\n\n " << Mdata.topics[mChoice-1] << " " << SubData[mChoice-1].topics[sChoice-1] << " Quiz." << endl;
cout << "----------------------------------------" << endl;
for(unsigned int q=0; q<question.size(); q++)
score += askQuestion( question[q], answer[q] );
}
return score;
}// end of takeQuiz()
void INITmenus( menuData& Mdata, vector<menuData>& SubData )
{
menuData MD_temp;
Mdata.title = "Main";
Mdata.topics.push_back("Geometry"); Mdata.fileName.push_back("quizData\\Geometry\\");
MD_temp.topics.push_back("Circles"); MD_temp.fileName.push_back("Circles.txt" );
MD_temp.topics.push_back("Rectangles"); MD_temp.fileName.push_back("Rectangles.txt" );
MD_temp.topics.push_back("Triangles"); MD_temp.fileName.push_back("Triangles.txt" );
MD_temp.title = Mdata.topics[ Mdata.topics.size() - 1 ];
MD_temp.Nchoices = MD_temp.topics.size();
SubData.push_back(MD_temp);
MD_temp.topics.clear();
MD_temp.fileName.clear();
Mdata.topics.push_back("History"); Mdata.fileName.push_back("quizData\\History\\");
MD_temp.topics.push_back("Ancient"); MD_temp.fileName.push_back("Ancient.txt" );
MD_temp.topics.push_back("18th century"); MD_temp.fileName.push_back("century18.txt" );
MD_temp.topics.push_back("19th century"); MD_temp.fileName.push_back("century19.txt" );
MD_temp.topics.push_back("United States"); MD_temp.fileName.push_back("USA.txt" );
MD_temp.title = Mdata.topics[ Mdata.topics.size() - 1 ];
MD_temp.Nchoices = MD_temp.topics.size();
SubData.push_back(MD_temp);
MD_temp.topics.clear();
MD_temp.fileName.clear();
Mdata.topics.push_back("Geography"); Mdata.fileName.push_back("quizData\\Geography\\");
MD_temp.topics.push_back("Asia"); MD_temp.fileName.push_back("Asia.txt" );
MD_temp.topics.push_back("United States"); MD_temp.fileName.push_back("USA.txt" );
MD_temp.title = Mdata.topics[ Mdata.topics.size() - 1 ];
MD_temp.Nchoices = MD_temp.topics.size();
SubData.push_back(MD_temp);
Mdata.Nchoices = Mdata.topics.size();
return;
}// end of INITmenus()
void LISTfileNames(const menuData& Mdata, const vector<menuData>& SubData )
{
string fName;
cout << "Listing all fileNames" << endl;
for(unsigned int m=0; m<Mdata.fileName.size(); m++)
for(unsigned int s = 0; s < SubData[m].fileName.size(); s++)
{
fName = Mdata.fileName[m];
fName.append( SubData[m].fileName[s] );
cout << fName << endl;
}
return;
}// end of LISTfileNames()
unsigned int Menu(const menuData& Mdata )// this replaces all of the previous individual xyzMenu()'s
{
unsigned int choice = 0;
cout << "\n\n\n\n";
do// get choice
{
cout << " *** " << Mdata.title << " Menu ***" << endl << endl;
cout << "Please choose a topic below" << endl;
cout << "---------------------------" << endl;
for(unsigned int j=1; j<=Mdata.Nchoices; j++)
cout << " " << j << ". " << Mdata.topics[j-1] << endl;
cout << " --------------" << endl;
cout << "Your choice? (1-" << Mdata.Nchoices << "): ";
cin >> choice;
// check choice
if(choice > Mdata.Nchoices)
cout << endl << "That choice was too high. Try again." << endl;
if(choice < 1)
cout << endl << "That choice was too low. Try again." << endl;
}while( (choice > Mdata.Nchoices)||(choice < 1) );
return choice;
}// end of Menu()
|
About the text files containing the questions and answers:
Add a folder titled quizData inside the same folder as the cpp file for this program.
In the quizData folder add 3 folders: Geometry, History and Geography
In the Geometry folder place a file named Circles.txt with the following content
exactly.
What is 5 + 2 ?
7
12 + 9 =
21
2 x 3 =
6
The square root of 144 =
12
Pi to four places =
3.142
|
You can now take a 5 question quiz on Geometry > Circles ( I know they are actually arithmatic questions). Change the Q's and A's to suit but the fomat MUST be:
question1
answer1
question2
answer2
|
And so on... Hope it works for you. Try tinkering with that!!
There is a line of code in main() which calls LISTfiles(). If you uncomment that line the program will list all of the files needed to make all of the quizzes work.