Why does my try catch exception stop working after the catch? - c++

I have a segment of code here that runs partially. I am able to input both the characters (c, a, r) and numbers initially, but after entering a character input, the code no long accepts integer inputs. Why does this happen?
I think it has something to do with my try catch exception.
code:
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
using namespace std;
int item;
string input;
float total = 0;
int flag = 0;
float maintotal = 0;
int main() {
cout.precision(2);
cout << std::fixed;
cout << "Vending Machine" << endl;
cout << "----Items------" << endl;
vendingMachine();
cout << "Enter c to checkout" << endl;
cout << "Enter a to add items" << endl;
cout << "Enter r to remove items" << endl;
while (true) {
cout << "Enter your selection: " << flush;
cin >> input;
try
{
item = stoi(input); //convert to int
}
catch (exception &e)
{
//std::cout << e.what();
flag = -1; //if not set flag
if (input == "c"){
checkout();
}
if (input == "a") {
add();
cout << "mainadd total: " << total << endl;
}
if (input == "r") {
remove();
}
}
if (flag != -1) //only execute with no errors
{
total = enterSelection();
cout << "total from main: " << total << endl;
}
}
return 0;
}

Once you've set flag to -1, it's never changed back to 0. The initialization you perform at the top of the file happens just once, before main is even called. So, after that, when you set it to -1 in the catch block, it never went to a part of the code that set it back to 0. As you saw, setting flag = 0 at the beginning of the while loop corrects that omission.

Related

Do-While Loop in Functions

I am just studying so don't judge me hard please.
I have a problem. I know how to do a do-while loop. But today I have learned about functions. So I made do-while loops in functions and they are looping infinitely. How do I stop the loops?
#include <iostream>
using namespace std;
void text()
{
cout << "Log in to see the Menu. " << endl;
}
void lg()
{
const string login = "el1oz";
string input;
cout << "Login > " << flush;
cin >> input;
do{
if(login == input){
break;
}
else{
cout << "Try again." << endl;
}
}while(true);
cout << "Correct Login! " << endl;
}
void pw()
{
const string password = "Mau01171995";
string input1;
cout << "Password > " << flush;
cin >> input1;
do{
if(password == input1){
break;
}
else{
cout << "Try again. " << endl;
}
}while(true);
cout << "Correct Passsword! " << endl;
}
int main()
{
text();
lg();
pw();
return 0;
}
You're not changing input after the code enters in the loop. You should put the cin >> input inside the loop.
Also consider when to use a while loop vs a do while loop. In this case a while loop is better.
You probably should not use using namespace std; (More information here).
You should use more descriptive names.
#include <iostream>
using std::cin;
using std::string;
using std::cout;
using std::flush;
using std::endl;
void printWelcome()
{
cout << "Log in to see the Menu. " << endl;
}
void inputUser()
{
const string login = "el1oz";
string input;
cout << "Login > " << flush;
while(cin >> input){
if(login == input){
break;
}
else{
cout << "Try again." << endl;
}
}
cout << "Correct Login! " << endl;
}
void inputPassword()
{
const string password = "Mau01171995";
string input;
cout << "Password > " << flush;
while(cin >> input){
if(password == input){
break;
}
else{
cout << "Try again. " << endl;
}
}
cout << "Correct Passsword! " << endl;
}
int main()
{
printWelcome();
inputUser();
inputPpassword();
return 0;
}

Why does program complain of too many commas?

Here is my code, I have attached the screenshot of what output Zybooks expects, and what my output is. I am trying to get it to output exactly what Zybooks is asking, however something seams to be wrong. It is compiling though. Or maybe Zybooks is just being stupid?
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cstring>
using namespace std;
int main() {
string title;
string col1;
string col2;
string val;
int numCommas = 0;
vector<string> stringData;
vector<int> intData;
cout << "Enter a title for the data:" << endl;
getline(cin, title);
cout << "You entered: " << title << endl << endl;
cout << "Enter the column 1 header:" << endl;
getline(cin, col1);
cout << "You entered: " << col1 << endl << endl;
cout << "Enter the column 2 header:" << endl;
getline(cin, col2);
cout << "You entered: " << col2 << endl << endl;
while (1) {
cout << "Enter a data point (-1 to stop input):" << endl;
getline(cin, val);
if (val == "-1") {
break;
}
if (val.find(',') == -1) {
cout << "Error: No comma in string." << endl << endl;
}
else {
for (int i = 0; i < val.length(); i++) {
if (val.at(i) == ',') {
numCommas++;
if (numCommas > 1){
break;
}
}
}
if (numCommas == 1) {
stringData.push_back(val.substr(0, val.find(',')));
intData.push_back(stoi(val.substr(val.find(',') + 1, val.length() - 1)));
cout << "Data string: " << val.substr(0, val.find(',')) << endl;
cout << "Data integer: " << stoi(val.substr(val.find(',') + 1, val.length() - 1)) << endl;
}
else {
cout << "Error: Too many commas in input." << endl << endl;
}
}
}
return 0;
}
Thanks.
Thanks.
Your problem is that you initialise numCommas to zero at the start of the program rather than at the start of each author input. That means, once it exceeds one, it will stay that high at least(a), meaning future inputs will always be seen as having too many commas.
You just need to set it to zero immediately before checking each input.
(a) Well, until it wraps around (if it wraps around). But that will be an awful lot of commas you need to input :-)

C++ : How to assign the same input to a string and an integer in 2 lines?

I'm a very beginner in C++ and I'm actually following the Google tutorial.
Trying to go a little further with the second example, here is my problematic : checking if the input is a number and, if not, being able to restate it in the error message.
Here is a way I used to solve that but the code length tells me that there is a shorter way :
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <stdlib.h>
using namespace std;
bool IsInteger(string str) {
size_t non_num_position = str.find_first_not_of("0123456789-");
size_t sign_position = str.find_first_of("-", 1);
if (non_num_position == string::npos && sign_position == string::npos) {
return true;
}
return false;
}
void Guess() {
int input_number = 0;
string input_string;
do {
cout << "Try to guess the number between 0 and 100 (type -1 to quit) : ";
cin >> input_string;
if (!IsInteger(input_string)) {
int input_string_length = input_string.size();
cout << "Sorry but « " << input_string << " » is not a number." << endl;
cin.clear();
cin.ignore(input_string_length, '\n');
continue;
}
input_number = atoi(input_string.c_str());
if (input_number != -1) {
cout << "You chose " << input_number << endl;
}
} while (input_number != -1);
cout << "The End." << endl;
}
int main() {
Guess();
return 0;
}
Here is the shorter way I try to follow but cin seems to be "emptied" once assigned to input_number (because of the bitwise operator ?) :
void Guess() {
int input_number = 0;
string input_string;
do {
cout << "Try to guess the number between 0 and 100 (type -1 to quit) : ";
if (!(cin >> input_number)) {
getline(cin, input_string);
cout << "Sorry but " << input_string << " is not a number." << endl;
cin.clear();
cin.ignore(100, '\n');
continue;
}
if (input_number != -1) {
cout << "You chose " << input_number << endl;
}
} while (input_number != -1);
cout << "The End." << endl;
}
SOLUTION :
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
void Guess() {
int input_number = 0;
string input_string;
do {
cout << "Try to guess the number between 0 and 100 (type -1 to quit) : ";
cin >> input_string;
try {
input_number = stoi(input_string);
if (input_number != -1) {
cout << "You chose " << input_number << endl;
}
}
catch (const exception&) {
cout << "Sorry but " << input_string << " is not a number." << endl;
}
} while (input_number != -1);
cout << "The End." << endl;
}
int main() {
Guess();
return 0;
}
The problem with your first attempt is that IsInteger is unnecessarily complicated and long. Otherwise, you had the right idea. Your second attempt is much less correct.... once you read from cin, the data is gone. So, as in the first attempt, you need to store the data in a string.
Here's an example which is a little shorter and doesn't need IsInteger at all:
size_t p = 0;
int input_number = std::stoi(input_string, &p);
if (p < input_string.length())
{
cout << "Sorry but " << input_string << " is not a number." << endl;
conitnue;
}
stoi's second argument tells you where the conversion to integer stopped working. So if there was non-int data in the string (such as '123abc') then p will be somewhere before the end of the string. If p is at the end, then the whole string must have been a number.

c++ segmentation fault (core dumped) with modulus

I am working on a program that allows the user to practice division. My code is below:
//div1
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
using namespace std;
#define CLS "\033[2J\033[1;1H"
#define NEWLINE "\n"
int main() {
srand(time(NULL));
int a, div1, div2;
div1=rand()%11;
div2=rand()%11;
while (div2>div1) {
swap(div1,div2);
continue;
}
if (div1%div2!=0) {
return main();
} else {
cout << CLS;
cout << NEWLINE;
do {
cout << div1 << " / " << div2 << " = ?" << endl;
cin >> a;
cout << CLS;
cout << NEWLINE;
cout << "\t\tWrong!!" << endl;
cout << NEWLINE;
} while (a!=div1/div2);
cout << CLS;
cout << NEWLINE;
cout << "\t\tCorrect!!" << endl;
cout << NEWLINE;
cout << "Hit enter to continue." << endl;
cin.ignore();
cin.get();
return main();
}
return 0;
}
Basically, what it is supposed to do is first choose two random numbers. Then, it is supposed to check to see if the second number (div2) is greater than the first (div1), and if they are, it will switch them. Then, it will use the modulus (div1%div2) to make sure that the two numbers can be divided by each other without a remainder. If they cannot be divided without a remainder, it will restart the program (return main();). However, whenever I run it, I get the segmentation fault: core dumped, either when I start it or after running it a few times. Any ideas on how to fix this?
Thanks!!
Here's an example of what I've said in the comments. Obviously, you can refactor this so that it works more gracefully (as of now it'll give you floating point exceptions sometimes), but it gives you an idea on how to do this without calling main again.
NOTE: You do not need to make a constant for NEWLINE. There is already a built-in constant in std. In fact, you're already using that constant (endl). So you can just do cout << endl instead of cout << NEWLINE.
//div1
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
using namespace std;
#define CLS "\033[2J\033[1;1H"
#define NEWLINE "\n"
int main() {
while(true) {
srand(time(NULL));
int a, div1, div2;
div1=rand()%11;
div2=rand()%11;
while (div2>div1) {
swap(div1,div2);
continue;
}
if (div1%div2!=0) {
} else {
cout << CLS;
cout << NEWLINE;
do {
cout << div1 << " / " << div2 << " = ?" << endl;
cin >> a;
cout << CLS;
cout << NEWLINE;
cout << "\t\tWrong!!" << endl;
cout << NEWLINE;
} while (a!=div1/div2);
cout << CLS;
cout << NEWLINE;
cout << "\t\tCorrect!!" << endl;
cout << NEWLINE;
cout << "Hit enter to continue." << endl;
cin.ignore();
cin.get();
}
}
return 0;
}
This code can get into "divide by 0" error. This is why you would be getting error.
The line "if (div1%div2!=0) {" seems erroneous.
In this line if div2 == 0, then your code will crash.

if statements for c++

My program so far, my question is do i have to include the if statements after each cout/cin code or is there a way to generalize it? :
#include <iostream>
using namespace std;
int main ()
{
double watts, hours_per_day, watt_hours, dollars_per_wh, result;
dollars_per_wh= .00008;
cout << " How many Watts for the Air conditioner? ";
cin >> watts;
cout << " How many hours/day do you run the Air Conditioner? ";
cin >> hours_per_day;
if (watts< 0)
{
cout << "Error- negative watts detected " << endl;
return 1;
}
if (hours_per_day< 0)
{
cout << "Error - negative hours/day detected " << endl;
return 1;
}
cout << "How many Watts for the Television? " ;
cin >> watts;
cout << "How many hours/day do you run the Television? " ;
cin >> hours_per_day;
if (watts< 0)
{
cout << "Error- negative watts detected " << endl;
return 1;
}
if (hours_per_day< 0)
{
cout << "Error - negative hours/day detected " << endl;
return 1;
}
cout << "How many Watts for the Washer? " ;
cin >> watts;
cout << "How many hours/day do you run the Washer? " ;
cin >> hours_per_day;
if (watts< 0)
{
cout << "Error- negative watts detected " << endl;
return 1;
}
if (hours_per_day< 0)
{
cout << "Error - negative hours/day detected " << endl;
return 1;
}
return 0 ;
}
You can write a function that takes two parameters:
bool check(int watts, int hours_per_day)
{
if (watts< 0)
{
cout << "Error- negative watts detected " << endl;
return false;
}
if (hours_per_day< 0)
{
cout << "Error - negative hours/day detected " << endl;
return false;
}
}
Then in your main function you can replace the two if statements with one:
if(!check(watts, hours_per_day))
{
return 1;
}
If you want to collect all the inputs first and then evaluate them, then maybe use an array for watts and hours_per_day. Then you can run through the array and check each entry.
Yes, you can pull them out into a separate function:
void cinNonNegative(double &x)
{
cin >> x;
if (x< 0)
{
cout << "Error- negative value detected " << endl;
exit(1);
}
}
int main()
{
...
cout << " How many Watts for the Air conditioner? ";
cinNonNegative(watts);
cout << " How many hours/day do you run the Air Conditioner? ";
cinNonNegative(hours_per_day);
...
}
And if you want to be more specific about the error message (e.g. "negative watts" instead of "negative value") you can add another parameter to cinNonNegative for the name of the variable (e.g. "watts").
The following solution gives you a function that:
Returns a boolean that says if the function succeeded/failed
Allows you to name the value that should be received
Allows you to set minimal and maximal values
If needed, you can build other custom functions for getting integers, or other functions for getting any other kind of input. This way you can concentrate all the input tests into a single place.
#include <iostream>
using namespace std;
bool getint(int &result, const char *name, int minValue, int maxValue)
{
bool success = false;
int value = 0;
cout << "Please enter " << name << ": ";
if (!(cin >> value))
{
cout << "Error: bad input detected" << endl;
}
else if (value < minValue)
{
cout << "Error: " << name << " is less than " << minValue << endl;
}
else if (value > maxValue)
{
cout << "Error: " << name << " is more than " << maxValue << endl;
}
else
{
success = true;
result = value;
}
return success;
}
int main()
{
int watts;
getint(watts, "Watts for the AC", 0, 10000);
return 0;
}