I'm trying to take a Magic 8 Ball program that was originally using arrays and change it to a program that uses vectors instead. The task that I was given was to take the code below and do a couple of things to it.
use the push_back() function to initialize the vector
modify the signature and prototype of the getAnswer() function
modify the code in the body of the getAnswer() function
remove any unneeded code, such as your constant for the number of
answers
#include <iostream>
#include <string>
#include <iomanip>
#include <string>
#include <stdio.h>
#include <fstream>
#include <stdio.h>
using namespace std;
string getAnswer();
const string exitString = "x";
const int SIZEOF_ANSWERS = 8;
string magicEightBallAnswers[SIZEOF_ANSWERS] = { "Yes", "No", "Maybe", "It's not certain", "The outlook is good",
"The outlook is poor", "Time will tell", "Most likely" };
int main(int argc, char *argv[])
{
bool keepGoing = true;
while (keepGoing)
{
string question;
//prompt for and get the question
cout << "What is your question? (Enter 'x' to exit)" << endl;
getline(cin, question);
//this assumes that the user enters a lower case x
if (question.compare(exitString) == 0)
keepGoing = false;
else
{
cout << getAnswer() << endl;
}
}
return 0;
}
string getAnswer()
{
int index = rand() % SIZEOF_ANSWERS;
return magicEightBallAnswers[index];
}
This example might help:
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
string getAnswer(vector<string> & magicEightBallAnswers)
{
int i = rand() % magicEightBallAnswers.size();
return magicEightBallAnswers[i];
}
int main()
{
vector<string> magicEightBallAnswers {
"Yes",
"No",
"Maybe",
"It's not certain",
"The outlook is good",
"The outlook is poor",
"Time will tell",
"Most likely"
};
// Initialize rand()
srand(time(NULL));
string question;
while (true) {
// Prompt for and get the question
cout << "What is your question? (Enter 'x' to exit)" << endl;
getline(cin, question);
if (question == "x")
break;
// Ask question
cout << getAnswer(magicEightBallAnswers) << endl;
}
// Done
cout << "Bye! Let's play again soon!" << endl;
return 0;
}
Specifically:
Use C++ features to your advantage, to eliminate unnecessary code like "push_back() or initializing with "(8)".
Never use a hard-coded constant like "SIZEOF_ANSWER" if there's a dynamic alternative like "vector.size()".
Note the use of pass by reference: in string getAnswer(vector<string> & magicEightBallAnswers).
You should call "srand()" with a seed before using "rand()".
Etc.
Related
Relatively new to c++.
Having trouble understanding an issue I am having with the compare() function returning 1 instead of 0.
I have a program which reads a text file containing an arbitrary number of questions and answers for a quiz. It is formatted as such:
Q: How many days in a week?
A: seven
I have three files, main.cpp, Quiz.cpp, and Quiz.h:
main.cpp:
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include "Quiz.h"
using namespace std;
int main(int argc, char* argv[]){
srand(unsigned(time(0)));
vector<Quiz> quizVector;
ifstream inputQuiz;
inputQuiz.open(argv[1]);
string q, a;
int questionCount = 0;
if(inputQuiz.is_open()){
getline(inputQuiz, q);
getline(inputQuiz, a);
while(!inputQuiz.eof()){
Quiz *instance = new Quiz(q, a);
quizVector.push_back(*instance);
questionCount++;
getline(inputQuiz, q);
getline(inputQuiz, a);
}
}
random_shuffle(quizVector.begin(), quizVector.end());
string userInput;
for(int i = 0; i < questionCount; i++){
cout << quizVector[i].getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
if(quizVector[i].getAnswer().compare("A: " + userInput) == 0){
cout << "Correct." << endl;
}
else{
cout << "Incorrect." << endl;
}
}
return 0;
}
Quiz.cpp:
#include <string>
#include "Quiz.h"
int Quiz::score = 0;
std::string Quiz::getQuestion(){
return question;
}
std::string Quiz::getAnswer(){
return answer;
}
Quiz.h:
#ifndef QUIZ_H
#define QUIZ_H
class Quiz{
private:
std::string question {""};
std::string answer {""};
public:
Quiz() = default;
Quiz(std::string q, std::string a) : question {q}, answer {a} {}
std::string getQuestion();
std::string getAnswer();
};
#endif
My problem lies within main.cpp:
for(int i = 0; i < questionCount; i++){
cout << quizVector[i].getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
if(quizVector[i].getAnswer().compare("A: " + userInput) == 0){
cout << "Correct." << endl;
}
else{
cout << "Incorrect." << endl;
}
}
When I input the correct answer corresponding to each question, compare() does not return 0, but consistently returns 1. There are no leading or trailing spaces at the start or ends of each line in the text file. Am I misunderstanding how getline() or compare() works? Is it something else? Any help is appreciated!
I see a number of problems with this code:
std::random_shuffle() is deprecated in C++14 and removed in C++17, use std::shuffle() instead.
you are not validating that argv contains an input parameter before using it.
Your use of eof() in the while loop is wrong. For instance, if the last question/answer pair in the file is terminated by EOF instead of a line break, getline() will still return the question/answer to you, but it will also set the eofbit flag on the stream, which will cause eof() to return true and thus you will skip saving the last pair into the vector. The stream is not technically in a failed state yet in this situation (see the diagram at https://en.cppreference.com/w/cpp/io/basic_ios/eof), so you shouldn't skip the last pair if it terminates with EOF rather than a line break.
Your while loop is leaking memory.
you don't need questionCount at all, use quizVector.size() instead. Or better, a range-for loop.
you don't really need to use compare() at all, you can use operator== instead. But, if you do use compare(), you should take into account that it is case-sensitive (as is operator==). You should also take advantage of the fact that compare() lets you specify an index to start comparing from, so you can ignore the A: prefix in the stored answer (alternatively, you could just strip off the Q: and A: prefixes when storing the question/answer in Quiz's constructor). Otherwise, you can use your compiler's strcmpi() function instead (if it offers one).
Try something more like this instead:
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <random>
#include <cctype>
#include "Quiz.h"
using namespace std;
string toLowercase(string s) {
transform(s.begin(), s.end(), s.begin(),
[](unsigned char c){ return tolower(c); }
);
return s;
}
int main(int argc, char* argv[]){
if (argc < 2){
cerr << "Please specify a file to open!" << endl;
return 0;
}
ifstream inputQuiz(argv[1]);
if (!inputQuiz.is_open()) {
cerr << "Can't open the file!" << endl;
return 0;
}
vector<Quiz> quizVector;
string q, a, userInput;
while (getline(inputQuiz, q) && getline(inputQuiz, a)) {
quizVector.emplace_back(q, a);
}
random_device rd;
mt19937 g(rd());
shuffle(quizVector.begin(), quizVector.end(), g);
for(auto &quiz : quizVector){
cout << quiz.getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
userInput = toLowercase(userInput);
a = toLowercase(quiz.getAnswer());
if (a == ("a: " + userInput)) {
// or:
// if (a.compare(2, string::npos, userInput) == 0) {
// or, if you strip off "A:" beforehand:
// if (a == userInput) {
cout << "Correct." << endl;
}
else {
cout << "Incorrect." << endl;
}
}
return 0;
}
This question already has answers here:
Making variables persist even after program termination
(3 answers)
I want to store a value even after my program ends
(1 answer)
Closed 2 years ago.
Most (if not all) games will remember the things (money, village size, manager amount, etc.) that you have so that when you start the game again, you still have everything you had obtained when you last left off. I am programming a game that needs to remember values, and I declare them initially at the beginning of the program. But since money equals zero, every time the user comes back to play the game, their earnings will be reset.
I will ultimately need this for most of my variables but I am actively working on Tutorial();. I am going to need the tutorial to only run once so I need the program to check whether the user has completed the tutorial every time the program begins. I have tried setting up a boolean value called isTutorialCompleted and having it check that in main when I run my functions. Code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//Game Variables
int money = 0;
string existingManagers = { "Benny, Rachel, Barnes, Flora, Gregory" };
string createManager = "";
vector<string> createdManagers {""};
bool isTutorialCompleted = false;
void initApp () {
}
void Tutorial() {
cout << "Please Enter your name" << "\n";
cin >> createManager;
createdManagers.push_back(createManager);
cout << "\n" << "You have created Manager " << createManager;
}
int main() {
initApp();
if (isTutorialCompleted == false) {
Tutorial();
}
}
This did not work due to the fact that every time I restarted the program the boolean value would reset so I tried making the boolean value undefined initially and then having it change in Tutorial. Code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//Game Variables
int money = 0;
string existingManagers = { "Benny, Rachel, Barnes, Flora, Gregory" };
string createManager = "";
vector<string> createdManagers {""};
bool isTutorialCompleted;
void initApp () {
}
void Tutorial() {
isTutorialCompleted = false;
cout << "Please Enter your name" << "\n";
cin >> createManager;
createdManagers.push_back(createManager);
cout << "\n" << "You have created Manager " << createManager;
isTutorialCompleted = true;
}
int main() {
initApp();
Tutorial();
}
The problem with this is that it would not keep the value. isTutorialCompleted would go back to undefined in the program and ultimately change to false when tutorial begins. Finally, I tried checking for the boolean value in initApp();. Code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//Game Variables
int money = 0;
string existingManagers = { "Benny, Rachel, Barnes, Flora, Gregory" };
string createManager = "";
vector<string> createdManagers {""};
bool isTutorialCompleted;
void initApp () {
//Check if tutorial is completed
if (isTutorialCompleted = true) {
Tutorial();
}
}
void Tutorial() {
cout << "Please Enter your name" << "\n";
cin >> createManager;
createdManagers.push_back(createManager);
cout << "\n" << "You have created Manager " << createManager;
isTutorialCompleted = true;
}
int main() {
initApp();
}
So the ultimate question is: How do you permanently store a variable so that when you restart the program, the stored variable does not reset?
Store and import from a config file whenever the game starts.
Let me preface by saying I am very new to coding but enjoy learning. I want to randomly generate a number then follow with 700 if statements that will ask a question according to what number is generated. So from the user pov it will randomly ask questions and then will generate another number after.
I've tried the timing random number generators. I can't seem to get rand operator to work. I just want a super basic generator.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
string a = "placeholder";
cout << "Welcome to Basic Strategy Practice" << endl;
cout << "You are given two aces and the dealer is showing a four. Hit,
double, or split ? " << endl;
cin >> a;
if (a == "split") {
cout << "Correct!" << endl;
}
else {
cout << "Incorrect" << endl;
}
return 0;
}
Basically, I would encapsulate the above code in an if statement that specifies which number was generated after each question is asked. I would think you would just put the if statement inside a while loop of some sort. Thanks!
I would do something like this:
#include <random>
int RandomBetween(int p_min, int p_max)
{
static default_random_engine generator;
std::uniform_int_distribution<int> distribution(p_min, p_max);
return distribution(generator);
}
After that, you can call this function in a switch:
switch(RandomBetween(a, b))
{
...
}
If you want an example of a complete quiz program I made this:
#include <string>
#include <iostream>
#include <tuple>
#include <chrono>
#include <vector>
#include <algorithm>
#include <random>
std::string ToLower(std::string p_target)
{
std::transform(p_target.begin(), p_target.end(), p_target.begin(), [](unsigned char c) { return std::tolower(c); });
return p_target;
}
int RandomBetween(int p_min, int p_max)
{
static std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(p_min, p_max);
return distribution(generator);
}
class Question
{
public:
Question(const std::string& p_message, const std::string& p_answer, bool p_caseSensitive) :
m_message(p_message),
m_answer(p_answer),
m_caseSensitive(p_caseSensitive)
{}
std::tuple<bool, float> Ask() const
{
std::string answer;
std::cout << m_message << std::endl;
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
std::cin >> answer;
end = std::chrono::system_clock::now();
return { answer == m_answer || (!m_caseSensitive && ToLower(answer) == ToLower(m_answer)), std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / 1000.0f };
}
private:
std::string m_message;
std::string m_answer;
bool m_caseSensitive;
};
int main()
{
bool gameRunning = true;
std::vector<Question> questions;
questions.emplace_back("Capital of France?", "Paris", false);
questions.emplace_back("Is C++ object oriented? [Y/n]", "y", false);
while (gameRunning)
{
const auto& [success, time] = questions[RandomBetween(0, 1)].Ask();
std::string answerSpeed = "(Answered in: " + std::to_string(time) + "s)";
if (success)
{
std::cout << "You are right!" << answerSpeed << std::endl;
}
else
{
std::cout << "You failed... Game is over!" << answerSpeed << std::endl;
gameRunning = false;
}
}
return 0;
}
Which can (Because it is a random game) outputs:
Capital of France?
Paris
You are right!(Answered in: 1.705000s)
Capital of France?
Paris
You are right!(Answered in: 2.368000s)
Capital of France?
Paris
You are right!(Answered in: 1.657000s)
Is C++ object oriented? [Y/n]
y
You are right!(Answered in: 3.927000s)
Capital of France?
I don't know
You failed... Game is over!(Answered in: 12.921000s)
So I am creating an hangman game and want to add a char into a string. I want to add a char of guess to the gatherguess string until the gatherguess matches hangman. Feel free to add some helpful tips to my code that will make me better. Also if it would be more then nice if you can also give me some sample code with dynamic memory allocation.
#include <stdio.h>
#include <string.h>
#include <iostream> // std::cout
#include <stdio.h>
#include <string.h>
#include <iostream> // std::cout
#include <algorithm> // std::for_each
#include <vector>
#include <set>
#include <string>
bool isitdone(std::string foo, std::string hang){
return foo == hang ? true : false ;
}
int main(){
std::string hangman;
char guess;
std::string gatherguess; //Get the letters guessed.
std::cin >> hangman; //Player enter the word to guess.
bool checkstatement; // Check to see if game is over.
for(int i =0; i < 10; ++i) {
std::cin >> guess; //Individual characters to guess
std::string doo;
int wordsin;
doo = hangman;
int y;
if(doo.rfind(guess) != std::string::npos) {
std::cout << "Right " << guess << " Is in the word" << std::endl;
std::cout << std::endl;
checkstatement = isitdone(gatherguess,doo);// I want to add guess char into gatherguess
//then check to see if gatherguess is equal to the word then the game will be complete
if(checkstatement == true) {
return 0;
}
} else {
std::cout << "Wrong" << std::endl;
}
}
return 0;
}
First of all, you should initialize gatherguess with enough placeholder characters:
auto hangman = std::string{};
std::cin >> hangman;
auto gatherguess = std::string{hangman.size(), '_'};
Now you can simply overwrite the '_' characters.
auto pos = hangman.find(guess)
if(pos != std::string::npos) {
// ...
do {
gatherguess[pos] = guess; // overwrite
pos = hangman.find(guess, pos); // find next ocurrence
} while(pos != std::string::npos)
// ...
}
I made some changes on your code. It contains some pieces of advice as comment.
//#include <stdio.h> // Do not include a library if you don not use it, because it makes the performance worse.
//#include <string> // Do not include a library if you don not use it, because it makes the performance worse.
#include <iostream> // std::cout
//#include <stdio.h> // It is pointless to include a library twice.
//#include <string.h>
//#include <iostream> // std::cout
//#include <algorithm> // std::for_each
//#include <vector> // Do not include a library if you don not use it, because it makes the performance worse.
//#include <set> // Do not include a library if you don not use it, because it makes the performance worse.
#include <string>
bool isitdone(const std::string& foo, const std::string& hang){ // Passing argument by const reference makes performance much better.
return foo == hang ? true : false ; // Indenting makes the code much more readable.
}
int main(){
const int N=10; // Store constant number in constant variable, because you can change its' value later easily.
std::string hangman;
char guess;
std::string gatherguess; //Get the letters guessed.
std::cin >> hangman; //Player enter the word to guess.
bool checkstatement; // Check to see if game is over.
for(int i =0; i < N; ++i)
{
std::cin >> guess; //Individual characters to guess
std::string doo;
int wordsin;
doo = hangman;
int y;
if(doo.rfind(guess) != std::string::npos)
{
std::cout << "Right " << guess << " Is in the word" << std::endl;
std::cout << std::endl;
checkstatement = isitdone(gatherguess,doo);// I want to add guess char into gatherguess
//then check to see if gatherguess is equal to the word then the game will be complete
if(checkstatement == true)
{
return 0;
}
} else
{
std::cout << "Wrong" << std::endl;
}
}
return 0;
}
I think there is a logical mistake in your program. What happens if a word contains more than 10 different characters? Do not count if the tipp is right.
You can add a char to a string this way:
#include <iostream>
#include <string>
int main(){
std::string str="123";
str+='4';
std::cout<<str<<std::endl;
return 0;
}
just a beginner student learning basic C++. I'm trying to figure out the best way to:
Turn a char array Name of 20 into a string that can be printed.
I found in other Stack Overflow topics to use "str()" such as "str(Name)", but it always comes up 'identifier not found'.
cout << "Name:" << str(Name) << endl;
Set a char array of 20 characters. For some reason, the following gives me errors when declaring. I've tweaked it so many times, but I cannot get why it won't give.
TESCStudent.Name[20] = {'S','u','p','e','r','P','r','o','g','r','a','m','m','e','r','\0'};
Full code I have so far:
#include <iostream>
#include <conio.h>
#include <string>
using namespace std;
//Step 1
struct StudentRecord
{
char Name[20];
//Accessor
void printInfo() const;
};
void StudentRecord::printInfo() const
{
cout << "Name:" << str(Name) << endl;
}
int main()
{
//Step 2
StudentRecord TESCStudent;
TESCStudent.Name[20] = {'S','u','p','e','r','P','r','o','g','r','a','m','m','e','r','\0'};
//Step 3
TESCStudent.printInfo();
_getch();
return 0;
}
Given that you are at a very beginner level, just use std::string:
#include <iostream>
#include <conio.h>
#include <string>
struct StudentRecord {
std::string Name;
void printInfo() const {
std::cout << "Name:" << Name << '\n';
}
};
int main() {
StudentRecord TESCStudent;
TESCStudent.Name = "SuperProgrammer";
TESCStudent.printInfo();
_getch();
}
Live demo
The syntax like this:
char Name[20] = {'S','u','p','e','r','\0'};
is used to initialize a variable when you define it. However, in your case,
StudentRecord TESCStudent;
TESCStudent.Name[20] = ...;
You've already defined it on the line before, so you can't "initialize", you have to "assign" it.
This is pretty much why you use std:string instead of char[].