i'm doing an online c++ learning course with quiz. The last output line of this snippet is to be determined (comments added by me). Correct answer: 10. My question: why 10 and not 11?
Calling a(b) swaps the two variables, so why is the last a.a.b 0 and not 1? / Why does the a.b() in cout not affect the a.a.b?
#include <iostream>
using namespace std;
class classA {
public:
classA() { st.f = st.p = 1; }
struct { int f, p; } st;
int bfunc(void);
};
int classA::bfunc(void) { int x = st.f; st.f = st.p; st.p = x; return x; };
int main()
{
classA a;
a.st.f = 0;
cout << a.st.f << a.st.p << endl; //01
a.bfunc();
cout << a.st.f << a.st.p << endl; //10
a.bfunc();
cout << a.st.f << a.st.p << endl; //01
a.bfunc();
cout << a.st.f << a.st.p << endl; //10
cout << a.bfunc() << a.st.p << endl; //10
return 0;
}
I'm trying to create a simple quiz with struct. But my program here is very repetitive. How can I modify it and make it more efficient? Especially to check if the answers are correct I do not want to declare a separate variable and store it as int correct. Thank You.
#include <iostream>
using namespace std;
struct Quiz{
string question;
string answers[3];
};
struct Quiz2{
string question2;
string answers2[3];
};
int correct;
int main()
{
Quiz Question;
Question.question = "What is the smallest county?";
cout << Question.question << endl;
Question.answers[0] = "1. USA";
cout << Question.answers[0] << endl;
Question.answers[1] = "2. India";
cout << Question.answers[1] << endl;
Question.answers[2] = "3. Vatican City";
cout << Question.answers[2] << endl;
cout << endl;
cout << "Choose 1-3: ";
cin >> correct;
if(correct == 3)
cout << "Correct!";
else
cout << "Incorrect!";
cout << endl;
cout << endl;
// Question 2
Quiz2 Question2;
Question2.question2 = "What is the biggest animal in the world?";
cout << Question2.question2 << endl;
Question2.answers2[0] = "1. Elephant";
cout << Question2.answers2[0] << endl;
Question2.answers2[1] = "2. Blue Whale";
cout << Question2.answers2[1] << endl;
Question2.answers2[2] = "3. Great white shark";
cout << Question2.answers2[2] << endl;
cout << endl;
cout << "Choose 1-3: ";
cin >> correct;
if(correct == 2)
cout << "Correct!";
else
cout << "Incorrect!";
return 0;
}
That's as much as non-repetitive as I can imagine after a few minutes of thinking. Maybe it can become smaller, but for my taste this looks alright.
You basically rely on std::vector class, instead of a typical array, because vectors can be of dynamic size. This allows us to use only one struct, but make as many answers as we want (3, 5, 10, whatever). We then create the whole quiz as another vector of questions. We're only left with printing to the console - for that we use loops, as our quiz structure is very simple and self-repetitive.
#include <iostream>
#include <vector>
using namespace std;
struct Question{
string question;
int correct_idx;
vector<string> answers;
Question(string question, int correct_idx, vector<string> answers)
:question(question), correct_idx(correct_idx), answers(answers)
{}
};
int main()
{
vector<Question> whole_quiz = {
Question{
"What is the smallest country?",
2, // indexes start from 0, e.g. 0, 1, 2. So 2 is correct
{"USA", "India", "Vatican City"}
},
Question{
"What is the biggest animal in the world?",
1,
{"Elephant", "Blue Whale", "Great white shark"}
},
};
for(auto question : whole_quiz) {
cout << question.question << endl;
for(int i = 0; i < question.answers.size(); ++i) {
cout << i+1 << ". " << question.answers[i] << endl;
}
cout << "Choose 1-" << question.answers.size() << endl << endl;
int guess;
cin >> guess;
if (guess-1 == question.correct_idx) {
cout << "Correct!" << endl << endl;
} else {
cout << "Incorrect!" << endl << endl;
}
}
return 0;
}
I would propose a more complicated, but also a more fun solution. Have a huge list of answers, like 100, or 1000, or as many as you like. Then in your struct have a std::string question, and std::vector<int> possible answers that are indexes in the huge list. First answer in the list is the correct one. So when you ask a question you pick first index, and three more indexes at random, and you shuffle them up, and present this to the user. The quiz will be different every time.
struct acts as a template, not a single variable. so there's no need to create 2 different struct. Also, a correct variable can be added to the struct for ease of checking.
Code (I split it into different functions for clearer understanding):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct quiz
{
int correct;
string question;
vector<string> answers;
};
vector<quiz> questionsToAsk;
void addNewQuestion(string ques, vector<string>ans, int cor)
{
quiz q1;
q1.question = ques;
q1.answers = ans;
q1.correct = cor;
questionsToAsk.push_back(q1);
}
void displayQuestion(int idx)
{
quiz cur = questionsToAsk[idx];
cout << cur.question << '\n';
for (int i = 0; i < cur.answers.size(); i++)
{
cout << cur.answers[i] << '\n';
}
cout << "Choose 1-3: "; int inp; cin >> inp;
if (inp == cur.correct) {cout << "Correct";} else {cout << "Incorrect";} cout << '\n';
}
int main()
{
vector<string> ans1({"1. USA", "2. India", "3. Vatican City"});
vector<string> ans2({"1. Elephant", "2. Blue Whale", "3. Great white shark"});
addNewQuestion("What is the smallest county?", ans1, 3);
addNewQuestion("What is the biggest animal in the world?", ans2, 2);
for (int i = 0; i < questionsToAsk.size(); i++)
{
displayQuestion(i);
}
}
Result:
What is the smallest county?
1. USA
2. India
3. Vatican City
Choose 1-3: 1
Incorrect
What is the biggest animal in the world?
1. Elephant
2. Blue Whale
3. Great white shark
Choose 1-3: 2
Correct
You can use a template like
<typename T = int>
T get_answer(std::istream& in) {
T res;
in >> res;
return res;
}
...
if(get_answer(std::cin) == 3)
cout << "Correct!";
else
cout << "Incorrect!";
You can also overload operator<<.
#include <iostream>
#include <string>
template<typename T = int>
T get_answer(std::istream& in) {
T res;
in >> res;
return res;
}
class Quiz{
public:
Quiz(const std::string& q, const std::string& a1, const std::string& a2, const std::string& a3, unsigned correct)
: question(q), answers{a1, a2, a3}{
CheckAnswer(correct);
}
friend std::ostream& operator<<(std::ostream& os, const Quiz& quiz) {
os << quiz.question << "\n";
unsigned i = 1;
for (const auto & answer : quiz.answers) {
os << i++ << ". " << answer << "\n";
}
os << "\n";
return os;
}
void CheckAnswer(unsigned correct) {
std::cout << *this << "Choose 1-3: ";
if(get_answer(std::cin) == correct)
std::cout << "Correct!";
else
std::cout << "Incorrect!";
std::cout << std::endl;
std::cout << std::endl;
}
private:
std::string question;
std::string answers[3];
};
int main()
{
Quiz Question("What is the smallest county?", "USA", "India", "Vatican City", 3);
// Question 2
Quiz Question2("What is the biggest animal in the world?", "Elephant", "Blue Whale", "Great white shark", 2);
return 0;
}
The only thing you can do is define the correct variable in the struct itself. You can use a loop for decreasing the repetitiveness but obviously the question and the answers will have to be stored, it cannot be simplified further.
hello all i am working on a school prject called inventory inquisitor. the specifications are as follows:
enter image description here
so far i have created a class in which contains a struct and a vector of this struct.
all im trying to do so far is get the class to display the struct just to know it works but when i compile it and run it nothing happens. here is the code. excuse whatever rookie mistakes i have made i am very new with classes, and vectors. thanks you in advance!
//Inventory Inquisitor.cpp
#include <iostream>
#include <string>
#include <cctype> //for toupper
#include <fstream>
#include <vector>
using namespace std;
class Inventory
{
private:
struct item
{
string Description = " ";
double Quantity = 0;
double Wholesalescost = 0;
double Retailcost = 0;
string Dateadded = " ";
};
vector<item> Inv;
public:
void Display();
};
void Inventory::Display()
{
Inv[0].Description = "english";
Inv[0].Quantity = 1;
Inv[0].Wholesalescost = 100;
Inv[0].Retailcost = 200;
Inv[0].Dateadded = "3/8/2018";
cout << Inv[0].Description << endl;
cout << Inv[0].Quantity << endl;
cout << Inv[0].Wholesalescost << endl;
cout << Inv[0].Retailcost << endl;
cout << Inv[0].Dateadded << endl;
}
int main()
{
Inventory inst1;
inst1.Display();
}
You have to put something into the vector before accessing it:
// Create an item
item i;
i.Description = "english";
i.Quantity = 1;
i.Wholesalescost = 100;
i.Retailcost = 200;
i.Dateadded = 3/8/2018;
// The vector is empty, size() == 0
// Add it to the vector
Inv.push_back(i);
// Now the vector has 1 item, size() == 1
// Now you can print it
cout << Inv.at(0).Description << endl;
cout << Inv.at(0).Quantity << endl;
cout << Inv.at(0).Wholesalescost << endl;
cout << Inv.at(0).Retailcost << endl;
cout << Inv.at(0).Dateadded << endl;
According to your assignment, you will most likely change to function to print an existing item. You will have another function to add items to the vector.
void Inventory::Display(int index)
{
// Print an item already in the vector
if (index >= 0 && index < Inv.size()) {
cout << Inv.at(index).Description << endl;
cout << Inv.at(index).Quantity << endl;
cout << Inv.at(index).Wholesalescost << endl;
cout << Inv.at(index).Retailcost << endl;
cout << Inv.at(index).Dateadded << endl;
}
}
I am working a a text adventure and have come across an error when I try to call a method from another method. The method returns the private int player_health and private int player_attack this work when I call it in main but when I call it in my combat_handler class it just give me a random number. I call it the exact same way in both class. Here is my code
Main.cpp
#include <iostream>
#include "player_handler.h"
#include "enemy_handler.h"
#include "combat_handler.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
player_handler phobj;
enemy_handler ehobj;
combat_handler cbobj;
phobj.test_player_systems();
ehobj.test_enemy_stats();
cbobj.player_turn();
phobj.get_player_stats();
return 0;
}
player_handler header
#ifndef PLAYER_HANDLER_H
#define PLAYER_HANDLER_H
class player_handler
{
public:
player_handler();
int get_player_health();
int get_player_attack();
void get_player_stats();
void add_player_health(int x);
void remove_player_health(int x);
void add_player_attack(int y);
void set_player_stats(int x, int y);
int test_player_systems();
private:
int player_health;
int player_attack;
};
#endif // PLAYER_HANDLER_H
player_handler.cpp
#include "player_handler.h"
#include <iostream>
using namespace std;
player_handler::player_handler()
{
//cout << "working"<< endl;
}
//Getting the players stats
int player_handler::get_player_health()
{
return player_health;
}
int player_handler::get_player_attack()
{
return player_attack;
}
void player_handler::get_player_stats()
{
cout << "the players health is " << get_player_health()<<endl;
cout << "The players attack is " << get_player_attack() <<endl;
}
//setting the player stats
void player_handler::set_player_stats(int x, int y)
{
player_handler::player_health = x;
player_attack = y;
//cout << "player health is " << player_health << endl;
//cout << "player attack is " << player_attack << endl;
}
//Player health control
void player_handler::add_player_health(int x)
{
//cout << "The old player health was " << player_health << endl;
player_health = player_health + x;
//cout << "Your health is now " << player_health << endl;
}
void player_handler::remove_player_health(int x)
{
//cout << "you lost " << x << " health" << endl;
player_health = player_health - x;
//cout << "Your new health is " << player_health << endl;
}
//player attack control
void player_handler::add_player_attack(int y)
{
//cout << "Your attack has been upgraded by " << y << " points" << endl;
player_attack = player_attack+y;
//cout << "You attack is now " << player_attack <<endl;
}
//test all player systems
int player_handler::test_player_systems()
{
set_player_stats(10,10);
cout <<"The player health is " << get_player_health()<<endl;
cout <<"the player attack is " << get_player_attack() << endl;
add_player_health(5);
remove_player_health(5);
add_player_attack(5);
get_player_stats();
return 0;
}
Now keep in mind that all this works it returns the right value for player_health and player_attack. now here is my problem it just gives me a random number
combat_handler header
#ifndef COMBAT_HANDLER_H
#define COMBAT_HANDLER_H
class combat_handler
{
public:
combat_handler();
int player_turn();
int enemy_turn();
private:
int player_input;
int player_dmg_given;
int enemy_dmg_given;
};
#endif // COMBAT_HANDLER_H
combat_handler.cpp
#include "combat_handler.h"
#include <iostream>
#include "player_handler.h"
using namespace std;
combat_handler::combat_handler()
{
cout << "combat handler on-line\n";
}
int combat_handler::player_turn()
{
player_handler phobj;
cout << "Would you like to (1)check stats (2) Enter the room?\n";
cin >> player_input;
switch(player_input){
case 1:
cout << "one"<<endl;
phobj.get_player_stats();
break;
default:
cout << "entering the room.\n";
break;
}
return 0;
}
The error happens when I call get_player_stats from the phobj in the combat handler class.
player_handler phobj;
This would call default constructor for player_handler( from your code it seems you are doing nothing in default constructor). And then you are calling get_player_stats() without setting the values. So, it would surely give you random values.
Earlier in main,
phobj.test_player_systems(); <<<< This is setting values.
phobj.get_player_stats(); <<<< Then you are querying on values already set.
I'm having problems with my program's output. It keeps spitting out 12345.
Here's the details:
It's split in three files: program8.cpp (the part that runs tests), myRandom.cpp (implementation of the class), and myRandom.h (specification of the class).
myRandom.h:
#ifndef MYRANDOM_H_
#define MYRANDOM_H_
class myRandom
{
public:
myRandom(); //Constructor
~myRandom(); //Destructor
void seed(unsigned long theSeed); //Mutator for current
unsigned long next(); //Mutator or Accessor for current
int randInt(int start, int end); //Scales result to a range
double randNormal(); //Future expansion
private:
unsigned long current; //Current random #
static const unsigned long a = 1103515245; //Multiplier for LGC
static const unsigned long c = 12345; //Increment for LGC
static const unsigned long m = 2147483648; //Modulus for LGC
};
#endif /* MYRANDOM_H_ */
myRandom.cpp:
#include <iostream>
#include <cstdlib>
#include "myRandom.h"
using namespace std;
myRandom::myRandom() //Constructor
{
current = 0;
}
myRandom::~myRandom() //Destructor
{
}
void myRandom::seed(unsigned long theSeed) //Mutator for current
{
if (theSeed < 0 || theSeed > m-1)
{
// ERROR
return;
}
else
current = theSeed;
}
unsigned long myRandom::next() //Mutator or Accessor for current
{
if (current < 0)
{
cout << "Error: cannot set seed to a negative number" << endl;
return 0;
}
else
{
current = (m*current+c)%m; //Formula
return current;
}
}
int myRandom::randInt(int start, int end) //Scales result to a range
{
if (start >= end)
{
cout << "Error: cannot set start greater than or equal to end" << endl;
return 0;
}
else
{
return ((this->next() % (end - start)) + start);
}
}
double myRandom::randNormal() //Future expansion
{
cout << "Warning: randNormal not implemented" << endl;
return 0;
}
program8.cpp:
#include <iostream>
#include <cstdlib>
#include "myRandom.h"
using namespace std;
int main()
{
myRandom theRand;
unsigned long theSeed;
cout << "Verify that the sequence generated by next() is the same on each run" << endl;
for (int i = 0; i < 5; i++)
{
cout << theRand.next() << endl;
}
cout << "Verify that you can set the seed to 0 and 1" << endl;
theSeed = 0;
cout << theRand.next() << endl;
theSeed = 1;
cout << theRand.next() << endl;
cout << "Verify that attempting to set the seed to -1 generates an error" << endl;
theSeed = -1;
cout << theRand.next() << endl;
cout << "Verify that you can set the seed to m-2 and m-1" << endl;
theSeed = 2147483648-2;
cout << theRand.next() << endl;
theSeed = 2147483648-1;
cout << theRand.next() << endl;
cout << "Verify that attempting to set the seed to m generates and error" << endl;
theSeed = 2147483648;
cout << theRand.next() << endl;
cout << "Verify that next() produces a sequence predicted by hand/calc for the chosen seed" << endl;
cout << "Please enter a seed: ";
cin >> theSeed;
cout << theRand.next() << endl;
cout << "Verify that using start == end generates and error. Set both to 10." << endl;
theRand.randInt(10,10);
cout << theRand.next() << endl;
cout << "Verify that using start > end generates and error. Set start to 10 and end to 5." << endl;
theRand.randInt(10,5);
cout << theRand.next() << endl;
theRand.seed(theSeed);
cout << "Testing randInt for start=0 end=1,000" << endl;
for (int i = 0; i < 5; i++)
{
cout << theRand.randInt(0 , 1000) << endl;
}
return 0;
}
I think the problem lies in the next() function, since that's what gets called all those times in program8.cpp cout statements. I could understand getting 12345 once, but it should be updated once that function runs successive times. I apologize if it's a dumb question. Thank you for your time and patience.
Your problem isn't a code specific one - it is Math-related from here:
current = (m*current+c)%m;
This always returns the value of c if c < m, otherwise (or more generally) it returns c % m. Why? From this theorem:
(m*n + a)%m = a
Example:
m = 10
n = 3
a = 7
(10*3 + 7)%10 = 7
See this for more:
http://en.wikipedia.org/wiki/Modulo_operation