Unexpected acceptance of user input c++ class - c++

Just started working with classes in C++ and i'm an encountering a strange occurrence when requesting input from the user.
I have two outcomes the conditionals will accept in the getUserWantToPlay() member function: 'y' or 'n'. Otherwise, it will output a message requesting a proper response. I'm in a very early stage of the build and I was just doing some testing on this member function and I noticed that when I type "yes" or "no" it acts as if I typed 'y' or 'n'. Why is this happening?
Application Code
//implementation of TicTacToe
//Using classes this time
#include <iostream>
#include "TicTacToeClass.h"
int main()
{
//Assumes no play unless user decides they want to play and initializes game variable to TicTacToe class
bool play = false;
TicTacToe game;
play = game.getUserWantToPlay();
while(play == true)
{
std::cout << "Playing the game" << std::endl;
break;
}
return(0);
}
Class Implementation
//TicTacToe class implementation
//Leeroy Jenkins
#include "TicTacToeClass.h"
#include <iostream>
bool TicTacToe::getUserWantToPlay()
{
char response;
bool invalidResponse = true;
bool play = false;
while(invalidResponse == true)
{
std::cout << "Would you like to play a new game of TicTacToe? (y/n) " << std::endl;
std::cin >> response;
if(response == 'y')
{
invalidResponse = false;
play = true;
}
else if(response == 'n')
{
std::cout << "No Problem!";
invalidResponse = false;
}
else
{
std::cout << "Please input a proper response (y/n)" << std::endl;
}
}
return play;
}

Related

SDL inputs only working sometimes

I am experimenting with keyboard input in SDL and I have encountered a strange problem. Whenever I get input it only outputs the appropriate response sometimes (Clicking X only sometimes closes the program, pressing 1 only sometimes outputs "you pressed 1". Here is my main code:
#include <iostream>
#include <SDL.h>
#include "Screen.h"
#include "Input.h"
using namespace std;
int main(int argc, char *argv[]) {
Screen screen;
Input input;
if (screen.init() == false) {
cout << "Failure initializing SDL" << endl;
}
while (true) {
if (input.check_event() == "1") {
cout << "You pressed 1" << endl;
} else if (input.check_event() == "quit") {
break;
}
}
SDL_Quit();
return 0;
and here is my Input class:
#include <iostream>
#include <SDL.h>
#include "Input.h"
using namespace std;
string Input::check_event() {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
return "quit";
}
else if(event.type == SDL_KEYDOWN){
switch(event.key.keysym.sym){
case SDLK_1:
return "1";
}
}
}
return "null";
}
Any help would be appreciated!
From the documentation of SDL_PollEvent():
If event is not NULL, the next event is removed from the queue and
stored in the SDL_Event structure pointed to by event.
Analyzing your code:
if (input.check_event() == "1") {
This removes the event, whatever it is, from the queue.
} else if (input.check_event() == "quit") {
Say the return value of the 1st call to check_event() was "quit", then this call won't return "quit" again, because this information is now lost.
To fix that, call check_event() only once per loop iteration and store the result in a temporary variable. Then use only that variable in the conditions:
while (true) {
string event = input.check_event();
if (event == "1") {
cout << "You pressed 1" << endl;
} else if (event == "quit") {
break;
}
}

C++ File input works once, but not twice for the same file

So I am running a program that has the users input a command. I have a text file with a list of acceptable command words. I open the file first to make sure that what the user input is indeed a valid command, but after that step I close the file. After that, I use some if/else statements to run a function corresponding to the command. One command is to list all of the valid commands, which requires me to open the file again and simply output the contents. At this step, however, the program simply outputs nothing. Here is the code:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void mainMenu();
void comJunc(string comString);
void comList();
bool isCommand(string comString);
int main()
{
mainMenu();
return 0;
}
void mainMenu()//This function inputs a command
{
string comString;
bool isCom = false;
cout << endl;
cout << "||Welcome to the main menu||\n\nPlease enter a command. For a list of commands type \"comlist\"\n";
do
{
cout << ">";
cin >> comString;//Input command "comlist"
isCom = isCommand(comString);//Checks if command is valid
if(isCom == false)
cout << endl << "**Error** Command \"" << comString << "\" was not found. Type \"comlist\" for help\n";
}while(isCom == false);
comJunc(comString);
return;
}
bool isCommand(string comString)
{
bool sFlag = false;
string inString;
ifstream comFile;
if(comFile.is_open() == false)
{
comFile.open("commands.txt");
}
while(getline(comFile, inString))
{
if(comString == inString)
sFlag = true;
}
comFile.close();
return sFlag;
}
void comJunc(string comString)//Executes function based on command
{
//comlist, continue, start, customize, exit
if(comString == "comlist")
{
comList();//Calles comList function
}
else if(comString == "exit")
{
//does nothing (exits)
}
else
cout << "Error in comJunc";
return;
}
void comList()
{
string inString;
ifstream comFile;
if(comFile.is_open() == false)
{
comFile.open("command.txt");
}
while(getline(comFile, inString))//This loop is not executed
{
cout << "Random text";//Text is not displayed
cout << endl << inString;
}
cout << endl;
comFile.close();
return;
}
The console looks like this:
||Welcome to the main menu||
Please enter a command. For a list of commands type "comlist"
>
At which point I type "comlist"
The desired result is for the command.txt file to output its contents. It should look like this:
comlist
command2
command3
command4
command5
Instead, the screen is left blank and the program exits as usual.
Any help would be greatly appreciated. Thanks.

basic C++ (cout buffer or overflow i think?!)

ok, so im kinda new to C++ and im trying to build a basic login program. iv got it to work except for one problem... this is what iv got
void InitialLogin()
{
cout << "\t\t ===========LOGIN==========" << endl;
cout << "\t\n\n\n\tUsername/>> " ;
getline(cin, sUsername);
cout << "\t\n\tPassword/>> ";
getline(cin, sPassword);
if (sUsername == "myname" && sPassword == "mypass")
{
cout << "\n\t\t\t--ACCESS GRANTED--";
system("CLS");
}
else if (sUsername != "myname" && sPassword != "mypass")
{
SetConsoleTextAttribute(h, FOREGROUND_RED);
cout << "\n\t\t\t--ACCESS DENIED--\n\n\n";
SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
main();
}
}
after i run this, if the login was successfull i have the following run after the screen is cleard...
void Initialization()
{
cout << "/>> Aquireing file list......" << endl;
cout << "/>> file list aquired........" << endl;
cout << "/>> determing file location.." << endl;
}
now my problem is, if i get the username or password wrong say once i get the initialization output twice, if i get it wrong twice, the output is three times.
i need to know how to clear the overflow or buffer or something...
please help :)
Your function is attempting to call main(). This is not legal C++.
You should return a status to see if the login worked or not. Then just loop until the status either becomes "true", or the user has run out of chances. Here is a small example:
bool InitialLogin();
int main()
{
int numChances = 3;
int numCount = 0;
bool loginOk = false;
while (numCount < numChances && !loginOk )
{
loginOk = InitialiLogin();
++numCount;
}
if ( !loginOk )
{
// number of chances ran out
return 0;
}
else
{
// proceed. Login was successful
}
}
bool InitialLogin()
{
//...
if (sUsername == "myname" && sPassword == "mypass")
{
//...
return true;
}
// anything here means that the login failed. There is no need for an if()
//...
return false;
}
I feel you are getting this because you are calling the main() function when both the password and username are incorrect (As a side note you might want to change the && in this check to || as you want access to be denied if either the password or username are incorrect).
You might want to consider getting the InitialLogin() function to return a bool to show weather the login was successful or not. If not the get it to run InitialLogin() again if successful then get it to proceed with the code.
In the place where you call InitialLogin() you can use a while loop to get it to repeat.
while(!InitialLogin()){}
So when InitialLogin() is not false (bad login) it will try again and when it is not true (good login) it will continue onto next section of code.

How to skip cin on purpose in C++?

I need to have a while-loop running and accept input to it whenever there is an input. I'm not new to C++, but this hurdle is quite difficult. Due to an NDA (this school project is apparently some secret stuff) I can only show you the test case.
I've been grasping for straws trying to solve the problem; try catch, cin.get, cin.peek, if(cin.peek){}. If anybody can point me in the right direction I would be very grateful!
The program is not time-critical, but a function needs to be called with a fixed interval. It is not essential that the code is portable, that it is a while-cin-combination or anything like that; the code will only ever run on a Windows 7 or Windows 8 PC with at least dual core processor.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int input = 0;
int pastTime, nowTime;
pastTime = nowTime = time(0);
cin >> input;
while(input != -1)
{
if(input == 1)
{
cout << "Entered 1" << endl;
//To be done instead of the two 'elses',
//bypassing interval-dependant code
}
else if(input == 2)
{
cout << "Entered 2" << endl;
//To be done instead of the interval-dependant code
}
else if(pastTime == (nowTime - 5))
{
cout << "Nothing entered." << endl;
//Needs to be done with a fixed interval.
}
nowTime = time(0);
cin >> input;
}
return 0;
}
The solution was, based om James Beilby's link:
// This program is based on counter.cpp from Boost\lib\thread\tutorial
#include <boost/thread/thread.hpp>
#include <iostream>
#include <ctime>
int timeNow = time(0);
int timePast = time(0);
void fct_one()
{
while(1) //keeps running all the time
{
if(timePast == (timeNow - 3)) // only executed once every three seconds
{
//do some stuff
timePast = time(0);
}
timeNow = time(0); // time is continuously updated
}
}
void fct_two()
{
int input = 0;
int timeTemp = time(0);
while(1) //keeps running all the time
{
std::cin >> input; // cin blocking for input
if(input == 1)
{
//do some stuff
}
if(input == 2)
{
//do some stuff
}
if(input == -1)
{
std::cout << "Program is done. ";
system("pause");
exit(1);
}
}
}
int main()
{
boost::thread_group threads;
threads.create_thread(&fct_one)
threads.create_thread(&fct_two);
threads.join_all();
return 0;
}
I would completely separate reading input from cin and performing the default timeout function. You'll need something like a background thread that performs the default function based on the time interval. To handle the 1st two cases you'll need to signal the thread skipping the next execution (if this is really necessary), and just call any function you want or do nothing.
The simple answer is to put the code that runs at some interval on another thread. Since you've noted this is Windows, you could use a Timer Queue:
Begin with routines to start and stop your time dependent work:
HANDLE Start(HANDLE hTimerQueue)
{
DWORD timerMS = 5000; /* every 5 seconds */
HANDLE hTimer;
if (!CreateTimerQueueTimer(&hTimer,
hTimerQueue,
(WAITORTIMERCALLBACK)timerWork,
/*lpParam*/NULL,
/*start in ___ ms:*/0,
/*run every __ ms:*/timerMS,
/*flags*/0))
{
return NULL;
}
return hTimer;
}
BOOLEAN Stop(HANDLE hTimerQueue, HANDLE hTimer)
{
if (!DeleteTimerQueueTimer(hTimerQueue,
hTimer,
/*wait for our timer to complete*/INVALID_HANDLE_VALUE))
{
return FALSE;
}
return TRUE;
}
Then put your time dependent work into its own callback:
VOID CALLBACK timerWork(PVOID lpParam, BOOLEAN TimerOrWaitFired /*ignored*/)
{
for (int ii = 0; ii < 10; ++ii) {
std::cout << "timer work: " << ii << std::endl;
Sleep(250);
}
}
Finally, integrate these into your workflow:
int main(int argc, char* argv[])
{
HANDLE hTimerQueue = CreateTimerQueue(hTimerQueue);
if (NULL == hTimerQueue) return -1;
HANDLE hTimer = Start(hTimerQueue);
if (NULL == hTimer) return -1;
/* our timed callback is now running in the background */
int input = 0;
std::cin >> input;
while(input != -1)
{
if(input == 1)
{
if (Stop(hTimerQueue, hTimer)) {
std::cout << "Entered 1" << std::endl;
if (NULL == (hTimer = Start(hTimerQueue))) return -2;
}
}
else if(input == 2)
{
if (Stop(hTimerQueue, hTimer)) {
std::cout << "Entered 2" << std::endl;
if (NULL == (hTimer = Start(hTimerQueue))) return -2;
}
}
std::cin >> input;
}
DeleteTimerQueue(hTimerQueue);
return 0;
}

Method to return to beginning of function

Does C++ have any type of utility to return to the beginning of a function after a function call? For example, example the call to help() in the calculate function.
void help()
{
cout << "Welcome to this annoying calculator program.\n";
cout << "You can add(+), subtract(-), multiply(*), divide(/),\n";
cout << "find the remainder(%), square root(sqrt()), use exponents(pow(x,x)),\n";
cout << "use parentheses, assign variables (ex: let x = 3), and assign\n";
cout << " constants (ex: const pi = 3.14). Happy Calculating!\n";
return;
}
void clean_up_mess() // purge error tokens
{
ts.ignore(print);
}
const string prompt = "> ";
const string result = "= ";
void calculate()
{
while(true) try {
cout << prompt;
Token t = ts.get();
if (t.kind == help_user) help();
else if (t.kind == quit) return;
while (t.kind == print) t=ts.get();
ts.unget(t);
cout << result << statement() << endl;
}
catch(runtime_error& e) {
cerr << e.what() << endl;
clean_up_mess();
}
}
While technically my implementation of a help function works fine, it's not perfect. After help is called, and returns, it proceeds with trying to cout << result << statement() << endl; which isn't possible because no values have been entered. Thus it gives a little error message (elsewhere in the program) and then proceeds on with the program. No problem with functionality, but it's ugly and I don't like it (:P).
So is there any way for when the help function returns, to return to the beginning of calculate and start over? (I played around with inserting a function call in if(t.kind == help_user) block to call calculate, but as I figured that just delays the problem rather than solving it.)
You can use goto, but the moment you do that consider yourself over. It's considered bad practice and good uses of it are rare and far apart.
I think what you're looking for is continue:
void do_calculate(void)
{
while (true)
{
cout << prompt;
Token t = ts.get();
if (t.kind == help_user)
{
help();
continue; // <- here
}
else if (t.kind == quit)
{
return;
}
while (t.kind == print)
{
t = ts.get();
}
ts.unget(t);
cout << result << statement() << endl;
}
}
void calculate()
{
try
{
do_calculate();
}
catch (const std::exception& e)
{
cerr << e.what() << endl;
clean_up_mess();
}
}
I have also reformatted your code. I think this is more readable, to each his own but just wanted to let you compare.
The try/catch clause is now no longer interfering with the calculation function.
The 'if' statements use brackets for consistency. Also, it's much easier to read, because I know whatever the if is controlling is within these brackets.
The catch will catch a std::exception, rather than runtime_error. All standard exceptions inherit from std::exception, so by catching that you know you can catch anything.
This might be what you're looking for?
if (t.kind == help_user) {
help();
continue;
}
You can return to the top of a loop with the continue statement. That's the easiest way to achieve what you want since you have a while loop surrounding your code:
if (t.kind == help_user) {
help();
continue;
}
There's also the goto statement though that is almost always a bad idea. I'll leave that to you to read about on your own. For more information read up on "control flow".
In this specific instance I'd probably opt for just restructuring your code slightly by adding an else statement, like so:
if (t.kind == help_user)
help();
else if (t.kind == quit)
return;
else {
while (t.kind == print)
t=ts.get();
ts.unget(t);
cout << result << statement() << endl;
}
Yes, it is called logic:
void calculate()
{
while(true)
{
try {
cout << prompt;
Token t = ts.get();
if (t.kind == help_user)
help();
else
{
if (t.kind == quit) return;
while (t.kind == print) t=ts.get();
cout << result << statement() << endl;
}
ts.unget(t); // if statement above needs this then leave it in and
// add one call after help() as well ... not sure from code
}
catch(runtime_error& e) {
cerr << e.what() << endl;
clean_up_mess();
}
}