Exceptions in C++ how to get back to "main menu" - c++

Well, I'm studying for an exam so I tried to keep my code as simple as possible, but then something very weird happened: the exercise was to change the following code and, by using exceptions, get back to the main menu.
Here's the code of the question:
void ha_ha_loop()
{
int i, c;
while(1)
{
for(i=0; i < 3; i++)
{
cout << "Ha Ha Ha" << endl;
sleep(3);
} // for
ask_return();
} // while
} // ha_ha_loop
void dollar_loop()
{
int i;
while(1)
{
for(i=0; i < 3; i++)
{
cout << "$$$$$$$$$ " << endl;
sleep(3);
} // for
ask_return();
} /* while */
} // dollar_loop
void mainloop()
{
string answer;
while (1)
{
cout << "Press 1 for Ha Ha Ha." << endl;
cout << "Press 2 for $$$$$$$$." << endl;
cout << "Press 3 for to quit." << endl;
cin >> answer;
switch (answer[0])
{
case '1':
ha_ha_loop();
case '2':
dollar_loop();
case '3':
return;
} // switch
} // while
} // mainloop
And what I did was:
void ask_return() {
char c;
cout << "Return to main menu? y/n:"<<endl;
cin >> c;
if (c=='y') throw 1;
}
void ha_ha_loop()
{
int i, c;
while(1)
{
for(i=0; i < 3; i++)
{
cout << "Ha Ha Ha" << endl;
} // for
ask_return();
} // while
} // ha_ha_loop
void dollar_loop()
{
int i;
while(1)
{
for(i=0; i < 3; i++)
{
cout << "$$$$$$$$$ " << endl;
} // for
ask_return();
} /* while */
} // dollar_loop
void mainloop()
{
char answer;
while (1)
{
cout << "Press 1 for Ha Ha Ha." << endl;
cout << "Press 2 for $$$$$$$$." << endl;
cout << "Press 3 for to quit." << endl;
cin >> answer;
switch (answer)
{
case '1':
ha_ha_loop();
case '2':
dollar_loop();
case '3':
return;
}
}
}
int main() {
try {
mainloop();
} catch (...) {
mainloop();
}
}
It works fine at the beginning, but then after one time it terminates my program with an unhandled exception message. Why?
What is the simplest correct way to do that?
Edit:
this is a working way :
void ask_return() {
char c;
cout << "Return to main menu? y/n:"<<endl;
cin >> c;
if (c=='y') throw 1;
}
void ha_ha_loop()
{
int i, c;
while(1)
{
for(i=0; i < 3; i++)
{
cout << "Ha Ha Ha" << endl;
} // for
ask_return();
} // while
} // ha_ha_loop
void dollar_loop()
{
int i;
while(1)
{
for(i=0; i < 3; i++)
{
cout << "$$$$$$$$$ " << endl;
} // for
ask_return();
} /* while */
} // dollar_loop
void mainloop()
{
char answer;
while (1)
{
try {
cout << "Press 1 for Ha Ha Ha." << endl;
cout << "Press 2 for $$$$$$$$." << endl;
cout << "Press 3 for to quit." << endl;
cin >> answer;
switch (answer)
{
case '1':
ha_ha_loop();
case '2':
dollar_loop();
case '3':
return;
}
} catch (...) {
}
}
}
int main() {
mainloop();
}

I'll only answer the "how come" part, since the simplest correct way is what you're supposed to solve yourself. When you do
try {
mainloop();
} catch (...) {
mainloop();
}
you execute mainloop, catching any exceptions. When an exception is caught, the handler executes mainloop again, outside of a try block. You'll want to repeatedly go into mainloop, catching the exception every time.

OK, here's my suggestion.
First, ask_return() needs to get written. This is simple enough, and as far as I can tell you had it more-or-less right. I'm going to suggest actually using a std::exception though:
void ask_return()
{
char c;
cout << "Return to main menu? y/n" << endl;
cin >> c;
if ( c == 'y' )
{
throw std::exception(); // might as well use the class designed for this
}
}
There are numerous places where you could catch the exception, but the easiest place is within mainloop():
void mainloop()
{
string answer;
while (1)
{
cout << "Press 1 for Ha Ha Ha." << endl;
cout << "Press 2 for $$$$$$$$." << endl;
cout << "Press 3 for to quit." << endl;
cin >> answer;
try
{
switch (answer[0])
{
case '1':
ha_ha_loop();
case '2':
dollar_loop();
case '3':
return;
} // switch
}
catch (std::exception& e)
{
// do nothing, let the loop re-run.
}
} // while
} // mainloop
In this case, you don't even need to do anything about the exception: you just let the function keep looping, and it will work.

Related

I having problem with my searching function C++

i'am begginner in C++, i want to ask question about what's wrong about my coding, when i doing my work then found out problem i can't solve in searching function, there's no error notice or anything from visual studio but my function still didn't work,
sorry for my bad english.
here is my full code
#include <iostream>
#include <cstdlib>
#define MAX 5
using namespace std;
struct College {
int nim;
string name;
}mahasiswa;
struct queue {
College college[MAX];
int start,end = - 1;
}antrean;
void init() {
antrean.start= -1;
antrean.end = -1;
}
bool full() {
if (antrean.end== MAX - 1) {
return true;
}
else {
return false;
}
}
bool empty() {
if (antrean.end== -1) {
return true;
}
else {
return false;
}
}
void tampilData() {
int i;
if (!empty()) {
for (i = antrean.start; i < antrean.end; i++)
{
cout<<antrean.college[i].nim<<" | ";
cout << antrean.college[i].name << " | ";
cout << "\n";
}
}
cout<<"\n";
}
void inQueue() {
tampilData();
int elemennim;
string elemenname;
if (!full()) {
cout << "Input your NIM : ";
cin >> elemennim;
cout << "\n";
cout << "Input your name: ";
cin >> elemenname;
cout << "\n";
cout << "Succefully\n";
antrean.college[antrean.end].nim = elemennim;
antrean.college[antrean.end].name = elemenname;
antrean.end++;
}
else
{
cout << "Queue Penuh\n";
}
}
and this the error function i cant solve,
void searching(int key) {
for (int i = 0; i <= antrean.start; i++)
{
if (key == antrean.college[i].nim) {
cout << "Element found in index " << i;
}
else
{
cout << "Element not found\n";
}
cout << antrean.college[i].nim;
}
}
int main() {
int choice, elemen;
init();
cout << "Demo Queue dengan Linear Array" << endl;
do {
tampilData();
cout << "\nMenu Utama\n";
cout << "==============\n";
cout << "[1] Init \n[2] InQueue \n[3] Searching \n[4] out \n";
cout << "==============\n";
cout << "\nMasukkan pilihan: "; cin >> choice;
cout << "==============\n";
switch (choice) {
case 1: init(); break;
case 2: inQueue(); break;
case 3: cout << "masukkan NIM yang ingin dicari \n";
cin >> choice;
searching(choice); break;
} while (choice != 0);
return 0;
}
please help me, thank you very much

Error 'class HotelRoom' has no member named 'menu' even though it is there

I am attempting to build a hotel reservation program in C++. however, I have an issue. I keep getting the above error message and I can't seem to find a fix.
Please provide some assistance. Anything would be greatly appreciated. Below is what I have written thus far.
using namespace std;
class HotelRoom{
private:
int roomnum; //Room numbers
int roomcap; //Room capacity
int roomoccuoystst = 0;
int maxperperroom;
double dailyrate;
public:
HotelRoom()
{
roomcap = 0;
maxperperroom = 2;
dailyrate = 175;
}
int gettotal = 0;
int gettotallist = 0;
string room;
string guestroom,message;
void viewrooms()
{
char viewselect, back;
cout<<"Which room list would you like to view ?. 1 - Add rooms, 2 - Reserved rooms : " ;
cin>>viewselect;
switch(viewselect)
{
case '1':
viewaddromm();
break;
case '2':
viewresromm();
break;
default:
cout<<"Please select from the option provided or go back to the main menu. 1 - view rooms, 2 - to the mail menu or any other key to exit the program : ";
cin>>back;
switch(back)
{
case '1':
viewrooms();
break;
case '2':
hotelmenu();
break;
default:
exitpro();
}
}
}
void viewresromm()
{
int occup,rmchoose,up;
string roomtochange, items;
string guestroomdb;
int newaccupancy;
char decisionmade,savinf;
string fname, lname, nationality;
string checkaddroom;
ifstream getdatafromaddroom; //creation of the ifstream object
getdatafromaddroom.open("reserveroom.out");
if(getdatafromaddroom.fail()) //if statement used for error checking
{
cout<<"Could not open file"<<endl; //message that will be printed if the program cannot open the file
}
cout<<endl;
cout<<"First Name"<<'-'<<"Last Name"<<'-'<<"Nationality"<<'-'<<"Guest(s)"<<'-'<<"Room #"<<endl;
cout<<"-------------------------------------------------------"<<endl;
string items;
while(!getdatafromaddroom.eof())
{
// getdatafromaddroom >>fname>>lname>>nationality>>occup>>guestroomdb;
getline(getdatafromaddroom, items);
//cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<' '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<' '<<setw(9)<<guestroomdb<<endl;
gettotallist++;
if( getdatafromaddroom.eof() ) break;
cout<<items<<endl;
}
for(int getlist = 0; getlist < gettotallist; getlist++ )
{
cout<<items<<endl;
// cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<' '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<' '<<setw(9)<<guestroomdb<<endl;
}
}
void viewaddromm()
{
int occup,rmchoose,up;
string roomtochange;
string guestroomdb;
int newaccupancy;
char decisionmade,savinf;
string fname, lname, nationality;
string checkaddroom;
fstream getdatafromaddroom; //creation of the ifstream object
getdatafromaddroom.open("addroom.out");
if(getdatafromaddroom.fail()) //if statement used for error checking
{
cout<<"Could not open file"<<endl; //message that will be printed if the program cannot open the file
}
cout<<endl;
cout<<"First Name"<<'-'<<"Last Name"<<'-'<<"Nationality"<<'-'<<"Guest(s)"<<'-'<<"Room #"<<endl;
cout<<"-------------------------------------------------------"<<endl;
string items;
while(!getdatafromaddroom.eof())
{
// getdatafromaddroom >>fname>>lname>>nationality>>occup>>guestroomdb;
getline(getdatafromaddroom, items);
//cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<' '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<' '<<setw(9)<<guestroomdb<<endl;
gettotallist++;
if( getdatafromaddroom.eof() ) break;
cout<<items<<endl;
}
for(int getlist = 0; getlist < gettotallist; getlist++ )
{
cout<<items<<endl;
// cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<' '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<' '<<setw(9)<<guestroomdb<<endl;
}
}
void exitpro()
{
cout<<"Program closing......Goodbye"<<endl;
system("Pause");
exit(0);
}
menu()
{
char menuchoice;
cout<<"[-------------------------------------------------------]"<<endl;
cout<<"[-Welcome to the hotel booking and reseration menu-]"<<endl;
cout<<"[--------------------------------------------------------]"<<endl;
cout<<setw(30)<<"Addroom -- 1"<<endl;
cout<<setw(32)<<"Reserve a room -- 2"<<endl;
cout<<setw(34)<<" Modify a room -- 3"<<endl;
cout<<setw(36)<<"View roms -- 4"<<endl;
cout<<setw(38)<<" Exist -- 5"<<endl;
cin>>menuchoice;
switch(menuchoice)
{
case '1':
Addroom();
break;
case '2':
reserveroom();
break;
case '3':
modifyroom();
break;
case '4':
viewrooms();
break;
}
}
};
#endif
#include<string>
#include<iostream>
#include<fstream>
#include<iomanip>
using namespace std;
class HotelRoom
{
private:
int roomnum; // Room numbers
int roomcap; // Room capacity
int roomoccuoystst = 0;
int maxperperroom;
double dailyrate;
public:
HotelRoom()
{
roomcap = 0;
maxperperroom = 2;
dailyrate = 175;
}
int gettotal = 0;
int gettotallist = 0;
string room;
string guestroom, message;
void viewrooms()
{
char viewselect, back;
cout << "Which room list would you like to view ?. 1 - Add rooms, 2 - Reserved rooms : ";
cin >> viewselect;
switch (viewselect)
{
case '1':
viewaddromm();
break;
case '2':
viewresromm();
break;
default:
cout <<
"Please select from the option provided or go back to the main menu. 1 - view rooms, 2 - to the mail menu or any other key to exit the program : ";
cin >> back;
switch (back)
{
case '1':
viewrooms();
break;
case '2':
menu();
break;
default:
exitpro();
}
}
}
void viewresromm()
{
string roomtochange, items;
string guestroomdb;
// int newaccupancy;
// char decisionmade,savinf;
string fname, lname, nationality;
string checkaddroom;
ifstream getdatafromaddroom; // creation of the ifstream object
getdatafromaddroom.open("reserveroom.out");
if (getdatafromaddroom.fail()) // if statement used for error
// checking
{
cout << "Could not open file" << endl; // message that will be
// printed if the program
// cannot open the file
return;
}
cout << endl;
cout << "First Name" << '-' << "Last Name" << '-' << "Nationality" << '-' << "Guest(s)" <<
'-' << "Room #" << endl;
cout << "-------------------------------------------------------" << endl;
// string items;
while (!getdatafromaddroom.eof())
{
// getdatafromaddroom
// >>fname>>lname>>nationality>>occup>>guestroomdb;
getline(getdatafromaddroom, items);
// cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<'
// '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<'
// '<<setw(9)<<guestroomdb<<endl;
gettotallist++;
if (getdatafromaddroom.eof())
break;
cout << items << endl;
}
for (int getlist = 0; getlist < gettotallist; getlist++)
{
cout << items << endl;
// cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<'
// '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<'
// '<<setw(9)<<guestroomdb<<endl;
}
}
void viewaddromm()
{
// int occup,rmchoose,up;
string roomtochange;
string guestroomdb;
// int newaccupancy;
// char decisionmade,savinf;
string fname, lname, nationality;
string checkaddroom;
fstream getdatafromaddroom; // creation of the ifstream object
getdatafromaddroom.open("addroom.out");
if (getdatafromaddroom.fail()) // if statement used for error
// checking
{
cout << "Could not open file" << endl; // message that will be
// printed if the program
// cannot open the file
return;
}
cout << endl;
cout << "First Name" << '-' << "Last Name" << '-' << "Nationality" << '-' << "Guest(s)" <<
'-' << "Room #" << endl;
cout << "-------------------------------------------------------" << endl;
string items;
while (!getdatafromaddroom.eof())
{
// getdatafromaddroom
// >>fname>>lname>>nationality>>occup>>guestroomdb;
getline(getdatafromaddroom, items);
// cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<'
// '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<'
// '<<setw(9)<<guestroomdb<<endl;
gettotallist++;
if (getdatafromaddroom.eof())
break;
cout << items << endl;
}
for (int getlist = 0; getlist < gettotallist; getlist++)
{
cout << items << endl;
// cout<<setw(5)<<fname<<' '<<setw(10)<<lname<<'
// '<<setw(10)<<nationality<<' '<<setw(10)<<occup<<'
// '<<setw(9)<<guestroomdb<<endl;
}
}
void exitpro()
{
cout << "Program closing......Goodbye" << endl;
// system("Pause");
exit(0);
}
void Addroom()
{
std::string mess = __func__;
mess += " is not yet implimented.";
throw new std::logic_error(mess.c_str());
}
void reserveroom()
{
std::string mess = __func__;
mess += " is not yet implimented.";
throw new std::logic_error(mess.c_str());
}
void modifyroom()
{
std::string mess = __func__;
mess += " is not yet implimented.";
throw new std::logic_error(mess.c_str());
}
void menu()
{
while (true)
{
char menuchoice;
cout << "[-------------------------------------------------------]" << endl;
cout << "[-Welcome to the hotel booking and reseration menu-]" << endl;
cout << "[--------------------------------------------------------]" << endl;
cout << setw(30) << "Addroom -- 1" << endl;
cout << setw(30) << "Reserve a room -- 2" << endl;
cout << setw(30) << "Modify a room -- 3" << endl;
cout << setw(30) << "View rooms -- 4" << endl;
cout << setw(30) << "Exit -- 5" << endl;
cin >> menuchoice;
switch (menuchoice)
{
case '1':
Addroom();
break;
case '2':
reserveroom();
break;
case '3':
modifyroom();
break;
case '4':
viewrooms();
break;
case '5':
exitpro();
}
}
}
};
int main()
{
try
{
HotelRoom room;
room.menu();
}
catch(std::logic_error * ex)
{
std::cout << ex->what();
}
}
you have a lot more to go with this project. I've fixed the portion you specifically asked about and its now a runninng application with somewhat approperate diagnostics. I'm not going to get too deep into how this language works but you have several functions that were not implimented, missing return types, and just general logic errors like trying to use a file after you determined it wasnt open. it runs now, and you can get a clear indication of what you need to complete. You also had several unused varables.
i added , at minimal,
void Addroom()
{
std::string mess = __func__;
mess += " is not yet implimented.";
throw new std::logic_error(mess.c_str());
}
void reserveroom()
{
std::string mess = __func__;
mess += " is not yet implimented.";
throw new std::logic_error(mess.c_str());
}
void modifyroom()
{
std::string mess = __func__;
mess += " is not yet implimented.";
throw new std::logic_error(mess.c_str());
}
and a return type to menu.
`void menu()
you cannot call functions you have not yet written, and all functions have a return type even if they return nothing.
Good luck!

Alternative to goto in nested loops?

This code is working fine, however this whole time I've tried avoiding using the goto statements that you will see in the switch (dice_total) statement.
Without the goto statements, the program will not loop back to the beginning of while (again=='y' || again=='Y'), and instead it keeps looping itself when it reaches the do-while loop.
However, I believe that it is also important to say, that if dice_total is = to the point_total the first time around then the program will function properly, and loop back to the beginning. For example, when the program starts, the first round will generate the point_total, which we will say its 10. Which is a value that will allow the program to continue to the next round, and if the dice_total also gets the same number, 10, the program will say you win, and the loop will work properly. However, if the program reaches the do while loop, and generates a number that isn't 10, but generates a 10 after a few loops, then the program will not loop to the beginning. So what I want to ask, what is wrong with my switch(dice_total) statement, and how can I fix it, to give the program the same effect without using the goto statements?
#include "stdafx.h"
#include <iostream>
#include <random>
#include <string>
using namespace std;
int main()
{
//Declared Variables***********************************
char again = 'y';
int point1;
int point2;
int point_total;
int round_1=1;
int dice1;
int dice2;
int dice_total;
//*****************************************************
//RANDOM SEED******************************************
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int>dist(1, 6);
//*****************************************************
start://TEMPORARY
while (again == 'y'||again=='Y')
{
int round_1 = 1;
system("CLS");
cout << "WELCOME TO THE CRAPS GAME" << endl;
cout << "THROWING ROUND:" << round_1 << " DICES.............." << endl;
point1 = dist(mt);
point2 = dist(mt);
point_total = point1 + point2;
cout << "ROUND: " << round_1 << " First dice is: " << point1 << " and second dice is: " << point2 <<" and the total is:"<<point_total<< endl;
switch (point_total)
{
case 7:
case 11:
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!" << endl;
cin >> again;
break;
case 2:
case 3:
case 12:
cout << "YOU LOST, PRESS Y TO TRY AGAIN" << endl;
cin >> again;
break;
default:
do
{
++round_1;
cout << "ROUND " << round_1 << endl;
dice1 = dist(mt);
dice2 = dist(mt);
dice_total = dice1 + dice2;
cout << "THROWING ROUND: " << round_1 << " DICES.............." << endl;
cout << "ROUND 1 DICE TOTAL IS: " << point_total << endl;
cout << "ROUND: " << round_1 << " First dice is: " << dice1 << " and second dice is: " << dice2 << " and the total is:" << dice_total << endl;
switch (dice_total)
{
case 11:
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!" << endl;
cin >> again;
goto start;
case 2:
case 3:
case 7:
case 12:
cout << "YOU LOST, PRESS Y TO TRY AGAIN" << endl;
cin >> again;
goto start;
default:
if (dice_total == point_total)
{
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!<<endl;
cin >> again;
break;
}//if
else
{
cout << "Going to next round" << endl;
}
}//dice_total
}//do
while (dice_total != point_total);
break;
}//switch point
}//again while
}//main
The problem you're facing is usual when you have too many nested loops in the same function, and is an indicator that you need to refactor parts of your code to be in their own functions.
If you do this, then you have more possibilities to control the flow of your code: in each function you have break and return, and as you can return a custom value, you can use it to determine in the surrounding function if you need to break or return again.
Besides, this gives you the opportunity to put self-explanatory names to your functions, which makes your code clearer for people that look at it for the first time (as it's written, it's so dense that I can't understand it unless I stare at it for some minutes).
An example of what I mean in code:
Before
int main() {
start:
while (a) {
b1();
switch(c) {
case 1:
do {
d();
if (cond) goto start;
} while(e);
break;
}
b2();
}
}
After
int main() {
while (a) {
if (!doStuff1())
break;
}
...
}
bool doStuff1() {
b1();
while (a) {
bool res = doStuff2();
if (res) return true;
}
b2();
...
}
bool doStuff2() {
switch(c) {
case 1:
if (doStuff3()) return true;
}
return false;
}
bool doStuff3() {
do {
d();
if (cond) return true;
} while (e);
return false;
}
How about this design?
bool stop=false;
while(!stop && (again == 'y'||again=='Y'))
{
while(again == 'y'||again=='Y')
{
// ...
break; /* breaks inner while*/
// ...
stop=true;
break; /* breaks inner while, and prevents running outer loop*/
}
}

Error with getch()

void move_player(int& x, int& y) {
int old_x, old_y, new_x, new_y;
switch (getch()) {
case 0x31: // miscare stanga
if (current_x>min_x) {
old_x=x;
new_x=x-1;
if (y==1) {
path[1][old_x]=' ';
path[1][new_x]=player;
system("cls");
for (int y=0;y<3;y++) {
for (int x=0;x<20;x++) {
cout << path[y][x];
}
cout << endl;
}
} else if (y==2) {
path[2][old_x]='_';
path[2][new_x]=player;
system("cls");
for (int y1=0;y1<3;y1++) {
for (int x1=0;x1<20;x1++) {
cout << path[y1][x1];
}
cout << endl;
}
}
}
break;
case 0x32:
if (x<max_x) {
old_x=current_x;
new_x=current_x+1;
if (y==1) {
path[1][old_x]=' ';
path[1][new_x]=player;
system("cls");
for (int y2=0;y2<3;y2++) {
for (int x2=0;x2<20;x2++) {
cout << path[y2][x2];
}
cout << endl;
}
} else if (y==2) {
path[2][old_x]='_';
path[2][new_x]=player;
system("cls");
for (int y3=0;y3<3;y3++) {
for (int x3=0;x3<20;x3++) {
cout << path[y3][x3];
}
cout << endl;
}
}
}
break;
case 0x33:
if (y>min_y) {
old_y=y;
new_y=y-1;
path[old_y][x]='_';
path[new_y][x]=player;
system("cls");
for (int y4=0;y4<3;y4++) {
for (int x4=0;x4<20;x4++) {
cout << path[y4][x4];
}
cout << endl;
}
}
break;
case 0x34:
if (y<max_y) {
old_y=y;
new_y=y+1;
path[old_y][x]=' ';
path[new_y][x]=player;
system("cls");
for (int y5=0;y5<3;y5++) {
for (int x5=0;x5<20;x5++) {
cout << path[y5][x5];
}
cout << endl;
}
}
}
x=new_x;
y=new_y;
}
This is the function for moving a player in a two dimensional space.
It is represented by an array which I declared as char path[3][20] and the player can only move in path[1][20] or path[2][20]. The first layer of the array is just represented by a bunch of lines, kind of setting the boundaries for the map. Btw, the player starts at path[2][0] or lower left corner.
(I can't move it left or down in the starting position, only right or up)
The problem is, that when I run this, I can move it fine just once right, but then when I try it to move left or right it does nothing, and when I try to move it up or down the console just frezees and it quits.
How can I solve it?

Infinite loop reading from stdin using cin::fail()

I'm struggling with a vector push_back function.
The goal is to have a function which pushes n number of elements until you decide to stop.
So my idea of a 'stop', is cin.fail().
The faulty function is
void pushbackVector(vector<double> &data)
{
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
Problem is that when I attempt to use it, I enter a infinite loop.
I have yet to sort the first vector in ASC order, second in DESC order and concatenate the first and second into the third vector. However I'm confident that I can manage this on my own.
Anyway the whole code....
#include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
menu();
vector<double> row1;
vector<double> row2;
/* not yet used
vector<double> row3;
*/
int input;
cin >> input;
bool exit = 0;
while (!exit)
{
switch (input)
{
case 1:
pushbackVector(row1);
break;
case 2:
pushbackVector(row2);
break;
case 3:
printVector(row1);
break;
case 4:
printVector(row2);
break;
case 5:
cout << "Printing out the contents of row 1\n";
printVector(row1);
cout << "Printing out the contents of row 2\n";
printVector(row2);
cout << "Printing out the contents of row 3\n";
// printVector(row3);
break;
case 6:
cout << "Exitting\n";
exit = 1;
break;
default:
cout << "Invalid choice\n";
}
}
return 0;
}
void menu()
{
cout << "Choose an option\n";
cout << "1) Enter first vector\n";
cout << "2) Enter second vector\n";
cout << "3) Print out the first vector\n";
cout << "4) Print out the second vector\n";
cout << "5) Print out all three vectoros\n";
cout << "6) Exitting the program\n";
}
void printVector(const vector<double> &data)
{
for(int i = 0; i < data.size(); i++)
{
cout << data[i] << ", ";
}
cout << "\n";
}
void pushbackVector(vector<double> &data)
{
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
}
void sortVector (vector<double> &data)
{
cout << "Sorting your vector \n";
sort(data.begin(), data.end());
}
You're only reading once, move the read inside the loop:
void pushbackVector(vector<double> &data)
{
double input;
// cin >> input; --------------
//
for (int i = 0; i < 100; i++) //
{ //
cin >> input; // <---------
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
That'll make sure that you actually get input. Now, if you're not going to enter 100 values, you need to somehow notify the stream. That's done by insert "EOF character" in it. Press CTRL+Z on windows or CTRL+D on unix terminals.
When this gets read from the stream, it enters a fail (and eof) state and it'll stay like that unless you clear the error flags by calling cin.clear() when appropriate.
You've made the same mistake also in main. You only read once before the while loop, so input keeps the value you initialy entered and keeps entering the same choice. I think that's the infinite loop you're talking about. To fix it, move the read statement just before the switch.
Hope that helps.
Also, this is how I'd write the function:
double input;
for (int i = 0; (cin >> input) && i < 100; ++i) {
data.push_back(input);
}
cout << "Ending input.\n";
Streams can be used in boolean expression - they convert to the result of !fail() - and such are a convenient and idiomatic way to control a loop.
The infinite loop is cause by the fact that you are reading:
cin >> input;
once and then entering a while loop (in your main) that will keep going forever (unless the input is initially equal to 6).
Change:
cin >> input;
bool exit = 0;
while (!exit)
{
// ...
to:
bool exit = 0;
while (!exit)
{
cin >> input;
// ...
Depending on what your logic is, the same is happening in the pushbackVector function at:
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
// ...
You might want to change that to:
double input;
for (int i = 0; i < 100; i++)
{
cin >> input;
// ...
Do something like this instead:
void pushbackVector(vector<double> &data)
{
double input;
while (cin >> input) //will return true when there's valid input, otherwise false
{
if (input == -1)
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
This will read the input until you enter -1 or enter invalid input.
I think relying on cin.fail() is just not a good idea. The proper way to use fail() is explained in the link. It is not what you may expect.
Putting aside the reading which is misplaced, if you enter something you should not, you need to purge the input.
Add in the block of te first if
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
I would write the function the following way
void pushbackVector( std::vector<double> &data )
{
cin.clear();
cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
data.insert( data.end(), std::istream_iterator<double>( std::cin ), std::istream_iterator<double>() );
}
I was done some days before but I forgot to post my answer.
Who knew that I could just say if the cin fails, stop the input but don't end the program, lol.
#include<iostream>
#include<vector>
#include<algorithm> // for sort algorithms
#include<iomanip> // for setprecision
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
vector<double> row1;
vector<double> row2;
vector<double> row3;
int input;
bool exit = false;
while(!exit)
{
menu();
cin >> input;
switch (input)
{
case 1:
cout << "Entering vector 1\n";
pushbackVector(row1);
sortVector(row1);
cout << "\n";
break;
case 2:
cout << "Entering vector 2\n";
pushbackVector(row2);
sortVector(row2);
reverse(row2.begin(), row2.end());
cout << "\n";
break;
case 3:
cout << "Printing out vector 1\n";
printVector(row1);
cout << "\n";
break;
case 4:
cout << "Printing out vector 2\n";
printVector(row2);
cout << "\n";
break;
case 5:
// reserve enough space for all of row1's and row2's elements
row3.reserve(row1.size() + row2.size());
// insert row1's elements at the end of row3
row3.insert(row3.end(), row1.begin(), row1.end());
// insert row2's elements at the end of row3
row3.insert(row3.end(), row2.begin(), row2.end());
cout << "Printing out the contents of vector 1\n";
printVector(row1);
cout << "Printing out the contents of vector 2\n";
printVector(row2);
cout << "Printing out the contents of vector 3\n";
printVector(row3);
cout << "\n";
break;
case 6:
cout << "Exitting\n";
exit = true;
break;
default:
cout << "Invalid choice\n";
}
}
return 0;
}
void menu()
{
cout << "Choose an option\n";
cout << "1) Enter first vector\n";
cout << "2) Enter second vector\n";
cout << "3) Print out the first vector\n";
cout << "4) Print out the second vector\n";
cout << "5) Print out all three vectoros\n";
cout << "6) Exitting the program\n";
}
void printVector(const vector<double> &data)
{
for(int i = 0; i < data.size(); i++)
{
cout << setprecision(4) << data[i] << " ";
}
cout << "\n";
}
void pushbackVector(vector<double> &data)
{
double input;
int numOfItems;
cout << "How many items you want to add into vector?: ";
cin >> numOfItems;
for (int i = 0; i < numOfItems; i++)
{
cin >> input;
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
}
void sortVector(vector<double> &data)
{
cout << "Sorting your vector \n";
sort(data.begin(), data.end());
}