checking if entered value is float, clearing cin - c++

I have tried a few different variations of this code and I can't seem to get it right. I am pretty new to c++ yet so that might explain it. This code is part of a simple calculator. It basically asks the user to enter two numbers (they can be floats) and then asks the user for a mathematical operator and then does the operation. If a user enters something that's not a number and then enters a number when asked to enter a number again from the if statement the console prints "-9.25596e+061". This is the code:
#include "stdafx.h"
#include <iostream>
#include <cctype>
using namespace std;
double getUserInput()
{
//Make double, assign double, return double if number
double dUserInput;
//checks if it failed to cin
if (!(cin >> dUserInput))
{
//statement is true
cin.clear();
cin.ignore(99999, '\n');
cout << "You did not enter a number, please try again: ";
getUserInput();
}else
//statement if false
cout << "Number entered"; //for debugging purposes
return dUserInput;
}

You missed to add return in the recursive call to getUserInput.
Change the line
getUserInput();
to
return getUserInput();
Update
You can change the function to a non-recursive version.
double getUserInput()
{
//Make double, assign double, return double if number
double dUserInput;
//checks if it failed to cin
while (!(cin >> dUserInput))
{
cin.clear();
cin.ignore(99999, '\n');
cout << "You did not enter a number, please try again: ";
}
cout << "Number entered"; //for debugging purposes
return dUserInput;
}

Related

Undefined behaviour when entering `char` for integer variable with `std::cin`

I have this while loop, just to check if the entered number is 2. If the user entered by accident a letter instead of a number the loop goes to infinity even though I've added isdigit, but didn't fix the loop from going crazy if the input is a character. This is code:
int num1;
bool cond {false};
while(!cond){
cout<<"enter 2:";
cin>>num1;
if (!isdigit(num1)){
cout<<"not a digit:";
cin>>num1;
}
//
if(num1 == 2)
cond = true;
}
I would suggest trying something a little more straightforward instead of your current code:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num1;
cout << "Please enter the number 2:";
cin >> num1;
while (num1 != 2)
{
cin.clear(); //Clears the error flag on cin.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You did not enter the number 2, Please try again:";
cin >> num1;
}
return 0;
}
Now, cin.ignore(numeric_limits<streamsize>::max(), '\n'); is when it ignores up until '\n' or EOF \n is the delimiter meaning that, that is the character at which cin will stop ignoring.
Furthermore, numeric_limits<streamsize>::max() is basically saying there is no limit to the number of characters to ignore.
You need to use the header file #include<limits> to use this.
I recommend separating the reading of input data from converting it to a number. A good method for this is to use stringstream. Here's a working example:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int num1;
string input;
bool cond{ false };
cout << "enter 2:";
while (!cond) {
getline(cin, input);
stringstream ss(input);
ss >> num1;
if( ss.fail() ){
cout << "not a digit:";
continue;
}
//
if (num1 == 2)
cond = true;
else
cout << "enter 2:";
}
return 0;
}
int num1;
bool cond {false};
do{
cout<<"enter 2:";
cin>>num1;
if (cin.good()) {
cond = true;
}else {
cin.clear();
cin.ignore();
cout << "Invalid, please enter 2." << endl;
}
}while(!cond);
While false, execute statements. Also, if you want the user to re-enter a number, cin must be flushed.
Try declaring the variable num1 as char because isdigit(ch) works for char and not for int.
I hope this solves your problem
Why does the loop iterate infinitely?
Let's take this example
int a;
std::cin >> a;
std::cout << "Entered: " << a;
Now let's test it with different inputs
with int
5
Entered: 5
10
Entered: 10
Yes just as we would expect, but what happens when you enter a char?
with char
r
Entered: 0
f
Entered: 0
Why does this happen?
When you declare the variable int, and then do std::cin >> , you are telling the input method that the user will enter an integer, but when it doesn't get what it expected, it will fail. C++ will not implicitly convert the value of char into int. Hence, you get strange results.
How to solve this?
As I have mentioned earlier, it fails. When this fails you can catch it this way
if (!(std::cin >> a))
{
std::cout << "Invalid input ! \n";
}
We're saying, if the input fails, show the message.
let's test this new code.
int a;
if (!(std::cin >> a))
{
std::cout << "Invalid input !\n";
}
else
{
std::cout << "Entered: " << a;
}
5
Entered: 5
r
Invalid input !
How to print char value of the int?
If you want to just print the ASCII value of the entered number, you need to cast the value into char.
You can do
int num = 48;
char character_value = num;
Here C++ will implicitly convert char into int.
But if you need a safer type of conversion, prefer using static_cast<>.
The syntax looks like this
int a = 5;
char character_value = static_cast<char>(a);
Static cast in C++
Type casting in C++
Dealing with invalid input in C++

For Loops (C++)

Assignment:
The program should ask the user to enter a positive number and display all numbers from 1 to the input value. If the number is not positive, an error message should show up asking the user to re - enter the number.
My specific problem:
For my program, if the user enters an incorrect number and then re - enters a positive number, it does not display all the numbers from 1 to the input value. The program just ends.
#include <iostream>
using namespace std;
int main()
{
int userChoice;
int i = 1;
cout << "Enter a positive integer" << endl;
cin >> userChoice;
if (userChoice > 0)
{
for (i = 1; i <= userChoice; i++)
{
cout << "Loop 1:" << endl;
cout << i << endl;
}
}
else if (userChoice < 0)
cout << "Please re - enter" << endl;
cin >> userChoice;
system("pause");
return 0;
}
You need some sort of loop at the top of your program, that keeps asking for input until the user provides something valid. It looks like a homework assignment, so I will provide pseudo-code, not something exact:
std::cout << "Enter a number:\n";
std::cin >> choice;
while (choice wasn't valid) { // 1
tell the user something went wrong // 2
ask again for input in basically the same way as above // 3
}
// after this, go ahead with your for loop
It is actually possible to avoid the duplication here for step 3, but I worry that might be a little confusing for you, so one duplicated line really isn't such a big problem.
As an aside, you may wish to reconsider your use of what are often considered bad practices: using namespace std; and endl. (Disclaimer - these are opinions, not hard facts).

How to cover myself if user inputs a non number in my random number guessing game

Need help figuring out how to cover myself in case the user enters anything other than a number.
I've tried ending my if/elseif statements with an else to cover if the number is ! <,>,or = to. Doesn't seem to work and I kinda see why logically but can't figure out an alternative.
#include <iostream>
#include <ctime>
#include <stdlib.h>
using namespace std;
int main()
{
int number, guess;
srand(time(NULL));
number = rand()%100+1;
do
{
cout << "Guess a number from 1-100.\n";
cin >> guess;
if (guess < number)
cout << "Too low. Try again.\n";
else if(guess > number)
cout << "Too High. Try again.\n";
else if (guess == number)
cout << "Nice job. You got it right on.\n";
else
cout << "Ummm...A number please. Let's try again.\n";
}while (guess != number);
return 0;
}
Read the user input in as a string rather than a number. Then check that the string contains a valid numeric value and then convert to a number:
#include <string>
std::string GuessText;
unsigned long GuessNumber;
size_t NumberStart;
cin >> GuessText;
// check that user entered a valid number
NumberStart = GuessText.find_first_of("0123456789");
if (NumberStart == string::npos)
cout << "Ummm...A number please. Let's try again.\n";
else
{
// get the substring that contains the number
GuessText = GuessText.substr(PositionStart);
// convert string to number
GuessNumber = std::stoul(GuessText, nullptr, 0);
....
}
Try using isnan to check if the input value is a number. It not, have a while loop to keep re-asking for input untill the user inputs a number.
https://en.cppreference.com/w/cpp/numeric/math/isnan

How to print out a double value without losing first digit

When I run my code, it only prints the decimal parts of the double. On another page, I took a inputted double and printed out the double the way it was inputted.
But for my following code, it only prints out the decimals. For example, when I input 1.95 it only prints out 0.95. Why is it removing the first digit? I see nothing in my code that points to this.
I have already tried it in a more simple way and it worked. And I dont see any problems that would mess with the double in my code.
#include <iostream>
using namespace std;
int main()
{
double price;
char user_input;
do
{
cout << "Enter the purchase price (xx.xx) or `q' to quit: ";
cin >> user_input;
if (user_input == 'q')
{
return 0;
}
else
{
cin >> price;
int multiple = price * 100;
if (multiple % 5 == 0)
{
break;
}
else
{
cout << "Illegal price: Must be a non-negative multiple of 5 cents.\n" << endl;
}
}
} while (user_input != 'q');
cout << price << endl;
}
When I input 1.95, I get 0.95. But the output should be 1.95.
Problem covered in other answer: Reading for the 'q' removed the first character from the stream before it could be parsed into a double.
A solution: Read the double first. If the read fails, check to see if the input is a 'q'.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
double price;
while (true)
{
cout << "Enter the purchase price (xx.xx) or `q' to quit: ";
if (cin >> price)
{
// use price
}
else // reading price failed. Find out why.
{
if (!cin.eof()) // didn't hit the end of the stream
{
// clear fail flag
cin.clear();
char user_input;
if (cin >> user_input && user_input == 'q') // test for q
{
break; // note: Not return. Cannot print price if the
// program returns
}
// Not a q or not readable. clean up whatever crap is still
// in the stream
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
else
{
// someone closed the stream. Not much you can do here but exit
cerr << "Stream closed or broken. Cannot continue.";
return -1;
}
}
}
cout << price << endl;// Undefined behaviour if price was never set.
}
Another reasonable alternative is to read all input as std::string. If the string is not "q", attempt to convert it to a double with std::stod or an std::istringstream.
When you type 1.95 in the command line, variable user_input gets assigned '1', and price gets assigned .95.

How to call the function to pass the value in this code? C++

I am trying to do the homework but I can't figure how to continue from here. The assignment requires to design a calculator for controlling budget. Here are the requirements:
Have you ever been low on cash and couldn’t go beyond a certain dollar limit when shopping? You sort of need a calculator in your head. It would be cool if a device was actually part of the cart and as you add an item into the cart it would increment your total counter. To solve this, we are going to write a program that keeps a tally of the amount that we have spent so far as we visit a store.
What Your Program Should Do:
Allow the shopper (user) to enter in the product name and the cost. This should be echoed and confirmed. Make sure to check for bad data.
The user should be allowed to continue this until they want to check out.
Your program needs to keep a running total.
Upon checkout, the grand total should be displayed.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
int item_info(float, char);
int main()
{
//Declare all varibles.
char itemName[100];
float itemPrice;
char option;
float total;
int count;
count = 1;
// Setting decimal point for output.
cout.setf(ios::fixed, ios::floatfield);
cout.setf(ios::showpoint);
cout.precision(2);
item_info(itemPrice, itemName[100]);
total = total + itemPrice;
//Ask user if they want to continued to add more items.
cout << "Do you want to add more items? (Y/N)";
cin >> option;
if (option == 'Y' || option == 'y')
{
item_info(itemPrice, itemName[100]);
}
else
{
cout << "The total price of all items: $" << total << ".\n";
}
}
int item_info(float itemPrice, char itemName[100])
{
//Ask for input.
cout << "Please enter the item name: ";
cin.get(itemName, '\n');
//Ask for the price of the item.
cout << "Please enter the price of the item: ";
cin >> itemPrice;
//Check if it's a valid data.
while (!cin)
{
cin.clear();
cin.ignore(100, '\n');
cout << "Invalid input! Please enter the item price:";
cin >> itemPrice;
}
//Only take necessary data.
cin.ignore(100, '\n');
//Confirm the user input.
cout << "Item information:" << itemName <<": " << itemPrice <<"\n";
return itemPrice;
}
Can someone tell me how to fix it ?
You have two obvious problems: First is that the declaration and definition of item_info doesn't match. One takes a single character, the other an array of characters.
The second problem is that you call the function with a single character, but the problem is that you index out of bounds of the itemName array.
My guess is that the function is supposed to take a string (i.e. an array of characters), which means that the declaration and the call are wrong. You should not use an index when calling the function, just pass itemName like any other argument (see e.g. itemPrice).
First of all, your item_info parameters differ in definition and declaration:
int item_info(float, char);//should be char[100]
int item_info(float itemPrice, char itemName[100])
{
<...>
}
Second, here you are passing only the 100th element of the array, not the array itself:
item_info(itemPrice, itemName[100]); //should be item_info(itemPrice, itemName);
Finally, you should really use std::string for that, it will help you avoid such problems.
Your item_info function return an int, and you don't use this return value anywhere.
If you want to use itemPrice and itemName as an in/out parameters, you need to use a reference &.
Also, why not use std::string instead of a char array?
And as the other answers mentions. The declaration and definition of item_info doesn't match.