Input Validation to Accept Only Int Values - c++

I am designing a program to read several user inputs and the specifications include that they are always positive integers. These values will then be modified to keep only the hundreds value then and used to display a bar chart. The problem I am having is with the program's input validation. Should the user disregard instructions and enter a decimal value instead of an integer, immediately the remainder of the program's output displays without the ability for the user to input any additional values. My attempt at catching this problem is shown below in the if statements.
int main() {
int store1;
int store2;
cout << "Enter today's sales for store 1:" << endl;
cin >> store1;
if(store1 < 0 || ((store1 % 1))!=0)
cout << "Value of sales must be an integer greater than zero" << endl;
cout << "Enter today's sales for store 2:" << endl;
cin >> store2;
if(store2 < 0 || ((store2 % 1))!=0)
cout << "Value of sales must be zero or greater" << endl;
If the user inputs a decimal the program output is:
Enter today's sales for store 1:
400.34
Enter today's sales for store 2:
Enter today's sales for store 3:
Value of sales must be zero or greater
Enter today's sales for store 4:
Enter today's sales for store 5:
SALES BAR CHART
(Each * = $100)
Store 1: ****
Store 2:
Store 3:
Store 4:
Store 5:
Process finished with exit code 0
If I had to guess, the values after the decimal (in this case 3 and 4) were passed to input for store 2 and 3 respectively, and since they were less than 100, an * was not displayed next to the appropriate store. I haven't included my code to get hundreds values and output *'s for readability sake, and because I'm almost positive my problem is related to cin.
To summarize, I need to validate user input so that only a positive integer is accepted through any input method. Any help is greatly appreciated!

You can use strtoll to convert and validate an input string encoding an integer.
Value read from cin is of string type and then it is passed to get_positive_integer() that is a wrapper to strtoll, converting and validating the string, it returns -1 when the string is not at the expected format, else it returns the decoded positive integer. Note the use of an intermediate long long type to easy check for overflow, and the use of getline to read a whole input line without breaking strings at spaces which would pass inputs of first line to next readings.
#include <climits>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
int get_positive_integer(const string& str)
{
const char* s = str.c_str();
char* end;
long long val = strtoll(s, &end, 10);
if (end == s) {
// str was not encoding an integer.
return -1;
}
if (*end) {
// Stopped reading before the end of the string
// the whole string was not an integer.
return -1;
}
if (val > INT_MAX) {
// Too big to fit in an int type
return -1;
}
if (val <= 0) {
// Not a positive integer.
return -1;
}
return val;
}
int main()
{
string input;
cout << "Enter a positive integer:" << endl;
getline(cin, input);
int value = get_positive_integer(input);
if (value < 0) {
cout << "Not a valid positive integer" << endl;
return EXIT_FAILURE;
}
cout << "Value: " << value << endl;
return EXIT_SUCCESS;
}

Related

Hi I want user to enter 5 numbers and then output the sum in the end

I have used a loop for that:
int number1;
int sum=0;
for(int i =1; i<6; i++){
cout<<"Enter number:\n";
cin>>number1;
sum+=number1;
}
cout<<sum;
cout<<"Total Sum is = "<<sum<<"\n";
return 0;
}
My question is how can I print first statement like this ...
"Enter first number"
Enter Second number" and so on
Whenever you are reading numbers (or any value for that matter), you must check the stream-state (see: std::basic_istream State Functions). You have four stream states you must test following every input:
.bad() or .eof(). If badbit is set an unrecoverable error occurred, and if eofbit is set, there is nothing more to read (you can combine both into a single test that exits if either are set)
.fail() is set when a read error occurs, such as the user entering "FIVE" instead of 5 where integer input is expected. You handle failbit being set by calling .clear() to clear failbit and then call ignore() to empty the characters causing the failure before your next read attempt, and finally
.good() - valid input was received from the user, you can proceed to the next input.
By validating your input here, you can Require the user provide 5 valid integer values for you to sum. Do not use a for loop, instead use a while (or do .. while();) and only increment your counter when good input is received.
Putting that altogether, you can do:
#include <iostream>
#include <limits>
int main (void) {
int number = 0,
sum = 0;
const char *label[] = { "first", "second", "third", "fourth", "fifth" };
while (number < 5) /* loop continually until 5 int entered */
{
int tmp; /* temporary int to fill with user-input */
std::cout << "\nenter " << label[number] << " number: ";
if (! (std::cin >> tmp) ) { /* check stream state */
/* if eof() or bad() exit */
if (std::cin.eof() || std::cin.bad()) {
std::cerr << " (user canceled or unreconverable error)\n";
return 1;
}
else if (std::cin.fail()) { /* if failbit */
std::cerr << " error: invalid input.\n";
std::cin.clear(); /* clear failbit */
/* extract any characters that remain unread */
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
else { /* on succesful read of int, add to sum, increment number */
sum += tmp;
number++;
}
}
std::cout << "\nsum: " << sum << '\n';
}
Now your code will gracefully handle an invalid input without exiting just because a stray character was entered.
Example Use/Output
When you write an input routine, go try and break it. Enter invalid data and make sure you handle all error cases correctly. If something doesn't work right, go fix it. Repeat until you input routine can handle all corner-cases as well as the cat stepping on the keyboard:
$ ./bin/sumintlabel
enter first number: 3
enter second number: four five six seven!!
error: invalid input.
enter second number: 4
enter third number: 5
enter fourth number: 6
enter fifth number: 7
sum: 25
Form good habits now regarding handling input, it will pay dividends for the rest of your programming career. Let me know if you have questions.
if you need to print the words "first"... untill "fifth" then I'd do it like this:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int number1;
int sum=0;
string positions[5] = {"first", "second", "third", "fourth", "fifth"};
for(int i = 0; i<5; i++){
cout<<"Enter the " << positions[i] << " number:" << endl;
cin>>number1;
sum+=number1;
}
cout<<"Total Sum is = "<<sum<<"\n";
return 0;
}
I used an array of strings to display the words and changed the for loop to start at 0 so that we can go through the array positions and add the 5 numbers as well. If you just want to use: 1st, 2nd, 3rd... then you could change the for loop to what it was and do:
cout<<"Enter the " << i << "st" << " number:" << endl;
But for this you would have to use the if statement to print the right endings("st", "rd", "nd"). I think it would take longer for it to run but its miliseconds so we wouldn't even notice hahaha.
Hope it helped :)
You can use switch():
#include <iostream>
using std::cin;
using std::cout;
using std::string;
int main() {
int number1;
int sum = 0;
for(int i = 1; i < 6; i++) {
string num;
switch(i) {
case 1:
num = "first";
break;
case 2:
num = "second";
break;
//and 3 4 5 like this
}
cout << "Enter " << num << " number:\n";
cin >> number1;
sum += number1;
}
cout << "Total Sum is = " << sum << "\n";
return 0;
}
or you can use struct or containers like vector (in fact you have to use containers if you want to get a huge number of data.)

Adding string characters to a for loop after converting int to string in c++

So I'm busy with a school project and new to C++ and I'm a bit stuck, so here is the question:
When your program begins, it should prompt the user to enter an integer number greater than or equal to 1. This number should be assigned to a variable called control.
You must create a for loop that iterates a number of times equal to control. Each time it iterates, it must append a numeric digit to a string, with the first digit added being 1, and for each iteration, the next number is the previous number multiplied by the original number input. Additionally, the spaces that would ordinarily be between the numbers must instead be the ”#” symbol.
Once the loop is finished iterating, it must display the string that you have constructed.
As a hint, consider the use of string streams for converting between integer to string.
Examples of this program are below:
Please enter a number: 3
1#3#9
Please enter a number: 5
1#5#25#125#625
Please enter a number: 1
1
And here is my code so far :
int main()
{
int control;
int value;
string final;
int test;
stringstream convert;
cout << "Please enter a number: " << endl;
cin >> control;
if (control >= 1)
{
value = 1;
for (int count = 2; count <= control; count++)
{
value = value * control; <---- SO IM STUCK HERE
convert << value; TRYING TO INSERT "#"
final = convert.str() + "#"; BETWEEN THE VALUES
}
cout << "1#" << final << endl;
}
else
{
cout << "Please enter a valid number!" << endl;
}
system("pause");
return 0;
}
Thanks in advance for the help.
Okay so it seemed to be a very simple fix, I feel like an idiot but thanks for the help.
Old code : convert << value;
New code : convert << '#' << value;

Why does a string become an integer in C++?

#include <iostream>
using namespace std;
int main () {
int N;
cout << " Input an integer:";
cin >> N;
cout << " The integer entered is:" << N << endl;
}
when I input an Integer it returns the same value but when I input hello it gives me 1961729588.
The string doesn't become an integer, the std::cin operation fails and what you get as output is the garbage value that was in N originally. Initialize N to 0, and type in "hello" you should see 0 as output.
"when I input an Integer it returns the same value but when I input hello it gives me 1961729588?."
The cin >> N; actually fails returning false for the stream state, when a input is given that cannot be converted to an integer. You can check for such error condition with
if(!(cin >> N)) {
cerr << "Input a valid number!" << endl;
}
else {
cout << " The integer entered is:" << N << endl;
}
The value of N will be initialized (reset) to int() (default value) which actually renders to 0.
Full live sample
#include <iostream>
using namespace std;
int main () {
int N;
cout << " Input an integer:";
if(!(cin >> N)) {
cout << "Input a valid number!" << endl;
cout << "N = " << N << endl;
}
else {
cout << " The integer entered is:" << N << endl;
}
return 0;
}
Input
Hello
Output
Input an integer:Input a valid number!
N = 0
This was cross checked with a Ideone code sample
I cannot reproduce getting some garbage value like 1961729588. The value was correctly reset by the std::istream& operator>>(std::istream&, int&); input operator.
Is it an issue of your current compiler's implementation, c++ standards level (-std=c++11) settings?
I have found some notes about eventual differences regarding c++ standards at cppreference.com:
Though I didn't spot what they really refer to with 'a value as described above', to be honest.
When you input a non-integer the input fails. When the input fails, N retains its original value which isn't defined, i.e., writing results in undefined behavior. You should test your inputs, e.g.:
if (std::cin >> N) {
// do something with the successful input
}
else {
// deal with the input failure
}
When you enter cin >> N; the compiler sees that N was declared as an int. Thus your program will call a function that will attempt to read text representing an int from cin and store the result in N.
To do this it will read as much numeric characters from cin as it can, and stop when a non-numeric character is encountered.
For example if you enter 32\n your program reads 3, then 2, then \n. When it sees the \n it stops reading, because \n is not a number. The program will push \n back on to the stream (in case we want to read it later) and store 32 in N.
Suppose instead of a number you type some word such as "hello". The your program will read h and then stop, because h is not a number. h will be pushed back onto the stream (to be read later) and nothing will be stored in N. cin will return an error since no numeric characters were read.
This still does not explain the value of 1961729588.
Notice N was never initialised. According to the C++ Standard the value of an uninitialised automatic variable is undefined. Thus the value of N will be some garbage value. In your case this was 1961729588.

How to make an integer validation function that does not accept floating point values?

getRegionTotal() is the function I'm using for validation right now. It works pretty well in that if the user enters something like "twenty" or -7, it will not accept that and it will keep asking for new values until it gets one that is valid. However if the user enters 60.7 for the number of accidents in the north region, it will accept 60 and drop the .7 part. Then it will give both the regular instructions and the more specific instructions when it asks for the number of accidents in the south region.
//These will hold the number of accidents in each region last year
int northTotal = 0;
int southTotal = 0;
int eastTotal = 0;
int westTotal = 0;
int centralTotal = 0;
//passing 0 for northTotal, southTotal etc. because main doesn't know
//values of them until the function returns a value. When it returns a value
//it will go into the variables on the left. getRegionTotal will get the number
//of accidents for a region from the user and prompt the user using the string that
//is in the first argument.
northTotal = getRegionTotal("North", northTotal);
southTotal = getRegionTotal("South", southTotal);
eastTotal = getRegionTotal("East", eastTotal);
westTotal = getRegionTotal("West", westTotal);
centralTotal = getRegionTotal("Central", centralTotal);
int getRegionTotal(string regionName, int regionTotal)
{
//instructs user to enter number of accidents reported in a particular region
cout << "\nNumber of automobile accidents reported in " << regionName << " " << cityName << ": ";
//while regionTotal is not an integer or regionTotal is negative
while (!(cin >> regionTotal) || (regionTotal < 0) )
{
//give user more specific instructions
cout << "\nPlease enter a positive whole number for the number of\n";
cout << "automobile accidents in " << regionName << " " << cityName << ": ";
cin.clear(); //clear out cin object
cin.ignore(100, '\n'); //ignore whatever is in the cin object
//up to 100 characters or until
// a new line character
}
//returns a valid value for the number of accidents for the region
return regionTotal;
}
Parse the whole line and make sure you've consumed the whole line.
With iostreams:
#include <iostream>
#include <sstream>
#include <string>
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
int result;
if (!(iss >> result >> std::ws && iss.get() == EOF))
{
// error, die. For example:
std::cout << "Unparsable input: '" << line << "'\n";
continue;
}
// else use "result"
}
With stdlib:
#include <errno>
#include <cstdlib>
char const * input = line.c_str(); // from above, say
char * e;
errno = 0;
long int result = std::strtol(input, &e, 10);
if (e == input || *e != '\0' || errno != 0)
{
// error
}
The two approaches are fundamentally identical, but the former may be more "idiomatic C++". That said, if you already have an existing string, the strtol-approach is a neat alternative, since it gives you precise error handling: did you consume the whole string (if not, e points to the next character); did you consume any of the string (if not, e points to the beginning); was there an overflow or underflow (check errno). On the other hand, the iostreams approach lets you consume trailing whitespace (thanks to >> std::ws), which the strtol-solution doesn't.
There's also std::stol which wraps strtol (and similarly for strtoull/strtod etc.), but it throws an exception on error, and I believe that exceptions are not the right tool for structuring control flow of normal behaviour like reading user input. Also, you cannot control how those wrappers operates; for example, the succeed even if they don't consume the entire string (but don't tell you how far they got), and you cannot specify the number base.

Input an integer, get spaced output in C++?

I'm working on homework and I'm stumped on this problem: Write a program that prompts the user to input an integer and then outputs both the individual digits of the number and the sum of the digits. For example, it should output the individual digits of 3456 as 3 4 5 6, [...], output 4000 as
4 0 0 0, and the individual digits of -2345 as 2 3 4 5.
Here's my code so far:
int main()
{
string a; //declares string
cout << "Type an integer: "; //prompts user to input an integer
cin >> a; //stores into string a
cout << "There are " << a.size() << " digits in " << a << endl; //retrieves length of string a
cout << a.at(0);
cout << endl;
system ("pause"); //pauses the system so user can read the screen
return 0; //returns 0 if program works properly
}
Can anyone enlighten me on what I'm doing wrong/what my next step is?
So the steps are..
store the input
display them all one by one separated by spaces
figure out the sum and display that
.
#include<string>
#include<iostream>
using namespace std;
int main()
{
string a;
cout << "Type an integer: ";
// 1. store the input
cin >> a;
// 2. display them all one by one separated by spaces
for(int i=0;i<a.size();++i)
cout << a[i] << ' ';
cout << endl;
// 3. figure out the sum and display that
int total = 0;
for(int i=0;i<a.size();++i)
total += a[i] - '0';
cout << total << endl;
system("pause");
return 0;
}
The tricky part is getting the correct sum in step 3.
total += a[i] - '0';
Lets say for example that a[i] is the character '4'. The ASCII value of character '4' is the integer equivalent of 52, and the ASCII integer equivalent of '0' is 48. Therefore if we take '4' - '0', we will get the difference of 4, which is the integer representation we are looking for in this case.
Here is a simple ASCII chart with character values.
Hope this helps!
You probably want to input the number as a string. This will allow you to do digit by digit processing. Then the user will enter the number once instead of many times as digits.
You could try this piece of code:
int num = 0;
cin>>num;
//Make sure array is large enough to hold all digits
//For an int 10 digits it the max
int digits[10] = {0};
//This variable tracks the count of actual number of
//digits extracted from user input
int digitCount = 0;
while (num > 0)
{
digits[digitCount] = num % 10; //Extract digit at units place
num = num / 10; //Advance through the number
digitCount++;
}
for(int count= digitCount-1 ; count >= 0; count-- )
{
cout<<digits[count]<<" ";
}
Note that the printing loop runs backwards (i.e from digitCount to zero) because the digits are extracted and stored starting from the units place. For a number a like 12345 the digits array will contain 5 4 3 2 1.
Rhonda, I can understand your frustration, computers are like that... they do what you say, not what you mean :-) Hang in there.
You say your program should output each of the digits in the number, yet your program asks the user to enter each of the digits. That is confusing.
Also, you first assign a value to "num" here
cin >> num;
then you overwrite "num" in this line
cin >> num >> a;
I'm not sure what you mean to do here, but what you're telling the computer to do is to read an integer from the input and assign it to "num" and assign the rest to the line to string "a"... if the rest of the line just has a space, the space will be discarded... it acts as a separator. That is probably confusing you as well.
int main()
{
int runningTotal = 0;
std::string inputString;
std::cin >> inputString;
for ( std::string::iterator _it = inputString.begin();
_it != inputString.end(); ++_it )
{
// *_it now represents an individual char of the input string
char a = *_it; char* b = &a;
if ( a != '-' )
{
runningTotal += atoi( std::string( b ).c_str() );
std::cout << *_it << " ";
}
}
std::cout << std::endl << "Total of all digits: " << runningTotal << std::endl;
std::cin.get();
std::system( "pause" );
return 0;
}
I threw this together quickly for you. Hope it's of help.