How to allow only numbers in a variable? - c++

I am having some problems with my code, here is a part of the code I am having problem with.
Point of this code is that if a user enters something that is not a number, for example a character p, program should ask user to enter again, this part works.
If user enters a combination of numbers and characters program should ask user to enter again. For example n12 or 12n are not valid.
Part where a character comes first, like n12 doesn't cause problems, but the problem comes where a number is first and something else second, like 12n, which is not valid, but my code prints out the number 12 and later says that number is not valid.
#include <iostream>
using namespace std;
int main ()
{
int n;
while(1)
{
cout<<"Enter a number, 0 for exit: ";
cin>>n;
if(!cin)
{
cout<<"You didnt enter a valid number\n";
cin.clear();
cin.ignore(1000,'\n');
continue;
}
cout<<"Number is: "<<n<<endl;
if(n==0) return 0;
}
}
Examples of output of the code:
1°
Enter a number, 0 for exit: 12
Number is: 12
2°
Enter a number, 0 for exit: n
You didnt enter valid number
3°
Enter a number, 0 for exit: n12
You didnt enter valid number
4° <--- this one does not work properly
Enter a number, 0 for exit: 12n
Number is: 12
Enter a number, 0 for exit: You didnt enter valid number
Edit: if it's possible, I'd like to solve this problem without including additional libraries.

You could use isdigit(), std::string and std::all_of() from additional standard libraries (which is okay, not an overkill), like this (you store the input in the string and then you check if for every character of that string the isdigit function succeeds, which means that the input is purely numerically in that case):
#include <iostream>
#include <cctype>
#include <string>
int main()
{
std::string str;
std::cin >> str;
(std::all_of(str.begin(), str.end(), [] (char c) { return isdigit(c); })) ? std::cout << "It's a number!\n" : std::cout << "isdigit() failed\n";
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
4
It's a number!
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
f
isdigit() failed
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
12n
isdigit() failed

You need to check the whole line that the user entered, not just part of it. istream::operator>> stops reading when it encounters a character that does not belong to the data type currently being read. That is why input like 12n gets processed as 12 and n separately.
You are not going to solve this using just <iostream> functionality alone. This is best handled using things like std::getline() and std::stoi()/std::strtol(), eg:
#include <iostream>
#include <string>
using namespace std;
bool to_int(const string &str, int &i)
{
size_t pos;
i = stoi(str, &pos);
return (str.c_str()[pos] == '\0');
}
int main ()
{
string line;
int n;
do
{
cout << "Enter a number, 0 for exit: ";
getline(cin, line);
if (!to_int(line, n))
{
cout << "You didn't enter a valid number\n";
continue;
}
cout << "Number is: " << n << endl;
if (n == 0) break;
}
while (1);
return 0;
}
If you don't want to use a conversion function like std::stoi(), at least use a std::istringstream instead:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
bool to_int(const string &str, int &i)
{
char c;
istringstream iss(str);
iss >> i;
return !(iss.fail() || iss.get(c));
}
int main ()
{
string line;
int n;
do
{
cout << "Enter a number, 0 for exit: ";
getline(cin, line);
if (!to_int(line, n))
{
cout << "You didn't enter a valid number\n";
continue;
}
cout << "Number is: " << n << endl;
if (n == 0) break;
}
while (1);
return 0;
}

Loop through the number, if it has something other than a digit, print "You didnt enter valid number", else print the number. We will be getting input as a string and using ctype.h to verify if the string's character it is a digit:
#include <iostream>
#include <string>
#include <ctype.h>
using namespace std;
int main()
{
string n;
bool is_valid = true;
while (1)
{
cout << "Enter a number, 0 for exit: ";
cin >> n;
for (size_t i = 0; i < n.length(); i++) {
if (!isdigit(n[i])) {
cout << "You didnt enter a valid number\n";
is_valid = false;
break;
}
}
if (is_valid) cout << "Number is: " << n << endl;
if (n == "0") return 0;
}
}

Related

C++ Loop for String

I am struggling to create a loop for getting input from user. The input must push_back() each instance.
#include <iostream>
#include <array>
#include <cstring>
#include <vector>
#include <string>
#include <string.h>
using namespace std;
int main()
{
vector <string> bookQ = { "what","book","is","that","you","are","reading" };
for (int i = 0; i < bookQ.size(); i++) {
cout << bookQ[i] << ' ';
}
cout << endl;
string input;
int x = 0;
for (x != '1') { // require a loop to input string and end when user prompts
cout << "Enter 1 to stop" << endl; //
cin >> x; //
getline(cin, input); //
bookQ.push_back(input); //
} //
for (int i = 0; i < bookQ.size(); i++) {
cout << bookQ[i] << ' ';
}
cout << endl;
return 0;
}
Your for loop is missing the declaration and (iteration) expression parts:
for (declaration-or-expression; declaration-or-expression; expression)
so it should have looked like this:
for (;x != '1';) {
which is generally written as
while (x != '1') {
That would cause problems though since it would not stop directly when the user entered 1.
You are also comparing an int with a char ('1'), so in order to exit the loop, the user would have had to enter 49 (the ASCII value for 1), not 1.
You are also mixing formatted input (cin >> x) with unformatted input (getline). I suggest that you stick to one only.
Example:
while(cout << "Enter 1 to stop\n", getline(cin, input) && input != "1") {
bookQ.push_back(input);
}
Assuming you meant that input is a string, then you've made a few mistakes with types. First of all, you've used wrong type for variable x, you used int which is integer type, and the type string is required. Secondly, when comparing x with '1' you used single quotes, which define the type of variable as char, not string. To make 1 a string you should use double quotes, like so "1". Besides that, you have used for(condition), which is incorrect syntax. You should use while(condition). Also, when your loop iterates, the x variable is the input book name, and input variable is always an empty string, so I would suggest replace input with x everywhere. The working code is below.
P.S. I am not sure whether you want "1" to be in the final vector, so I haven't changed that
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<string> bookQ = {"what", "book", "is", "that", "you", "are", "reading"};
for (int i = 0; i < bookQ.size(); i++) {
cout << bookQ[i] << ' ';
}
cout << endl;
string input;
string x;
while (x != "1") {
cout << "Enter 1 to stop" << endl;
cin >> x;
bookQ.push_back(x);
}
for (int i = 0; i < bookQ.size(); i++) {
cout << bookQ[i] << ' ';
}
cout << endl;
return 0;
}
simply check if input is 1 everytime the user enters somthing, and when it does = 1, simply break loop.
string x;
while (true) { // require a loop to input string and end when user prompts
cout << "Enter 1 to stop" << endl;
cin >> x;
if (x == "1"){
break;
}
getline(cin, x);
bookQ.push_back(x);
}
}
First, your for syntax is wrong. You want a while loop instead, or in this case a do..while loop would make more sense. Also, you are pushing the user's input into the vector before validating what the input actually is.
Second, x is an integer, but '1' is a character whose ASCII value is number 49. Your loop will never end, because != will always be true. Since you want the user to enter number 1 to stop the loop, you need to drop the quotes:
Third, what is the point of pre-populating bookQ? Just declare the bookQ without any initial data, and then cout the entire question as a normal string. This way, after the user is done entering input, the vector will contain only the user's input and nothing else.
Try something more like this:
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
vector <string> bookQ;
string input;
cout << "what book is that you are reading" << endl;
do {
cout << "Enter a book, or 1 to stop" << endl;
getline(cin >> ws, input);
if (input == "1") break;
bookQ.push_back(input);
}
while (true);
for (size_t i = 0; i < bookQ.size(); ++i) {
cout << bookQ[i] << ' ';
}
cout << endl;
return 0;
}

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++

C++ How to protect against invalid input?

In my program, I want users to choose between two choices. Simply, 1 or 2. I have written the program to where it will protect against an invalid numeric value such as 3 or 28, but I cannot protect against alphabetical input.
Code is as follows:
int whileInt = 0;
int choiceOne_One = 0;
while(whileInt == 0)
{
cin >> choiceOne_One;
if(choiceOne_One != 1 && choiceOne_One != 2)
{
cout << "Woah! That wasn't an option! Try Again.\n";
}
else if(choiceOne_One == 1)
{
whileInt++;
cout << "\nYou have died. Be more careful.\n";
}
else if(choiceOne_One == 2)
{
whileInt++;
cout << "\nYou have survived the alien invasion due to your cunning sense of "
"safety.\nCongratulations.\n";
}
}
My brain still works in Java, please help me figure this out. It will definitely be appreciated.
Try this :
#include <iostream>
using namespace std;
int main()
{
char input;
cin>>input;
switch(input)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
cout<<"valid input"<<endl;
break;
default :
cout<<"Invalid input"<<endl;
}
return 0;
}
You can define a case for all your valid inputs, leave the rest to default.
Integers from 0-9 have their ASCII values from 48-57 respectively.
This solution wont be helpful if you have
. input>9 or input<0
. input such as 1abc
Might be a bit late but my favorite way to do and this is what i use :
#include <iostream>
#include <string>
#include <limits>
//T is for our variable and lambdaFunc will be our lambda function or
//function pointer
template<typename T, typename lambdaFunc>
auto secureEntry(T& variable, LambdaFunc lFunc, std::string errorMessage) //can ommit error message
{
while(!(std::cin(variable)) && !lFunc(variable)){
std::cout << errorMessage << std::endl;
std::cin.clear();
std::ignore((std::numeric_limits<std::streamsize>::max)(), '\n');
}
}
int main(int argc, char* argv[]){
int mynumber = {0};
std::string errorMessage = "Please use a number bigger than 0 and lower than 5"
secureEntry(myNumber, [](int& mynumber) -> bool{
return mynumber > 0 && mynumber < 5;
}, errorMessage)
}
you can do this also
int whileInt=0;
int choiceOne_One = 0;
while(whileInt == 0)
{
cin >> choiceOne_One;
if (choiceOne_One == 1 || choiceOne_One == 2){
if (choiceOne_One == 1){
whileInt++;
cout << "\nYou have died. Be more careful.\n";
}
else {
whileInt++;
cout << "\nYou have survived the alien invasion due to your cunning sense of "
"safety.\nCongratulations.\n";
}
}
else {
cout << "Woah! That wasn't an option! Try Again.\n";
}
}
Try reading a std::string with std::getline, then simply compare the string with "1" or "2". Otherwise, you can just read the whole line with std::getline, then use std::stoi (C++11) to transform the read string into an integer. The result of std::stoi tells you whether the transformation was successful or not (i.e., whether the string represented an integer). If successful, then you can simply compare the integer with 1 or 2. If not successful, then an std::invalid_argument or std::out_of_range exception is thrown.
First case (with std::string comparison):
#include <iostream>
int main()
{
std::string input;
std::getline(std::cin, input);
if (input != "1" && input != "2")
std::cout << "Invalid input!";
}
Second case (using std::stoi):
#include <iostream>
int main()
{
std::string input;
std::getline(std::cin, input);
int n = std::stoi(input); // throws exception if cannot convert to int
if (n != 1 && n != 2)
std::cout << "Invalid input!";
}
If you change the program so that cin puts a User's answer to a std::string, then you could do tests on the string value.
If the string's length() was more than 1, it cannot be '1' or '2'
There are additional tests you can do, like std::isalpha(int ch)
#include <stdio.h>
#include <string>
#include <iostream>
int main(int argc, char * argv[]) {
std::string value;
std::cin >> value;
std::cout << "Value is " << value << "\n";
std::cout << "length of value is " << value.length() << "\n";
char ch;
ch = value.at(0);
if(std::isalpha(ch)) std::cout << "You did not enter a number" << "\n";
return 0;
}
robert#debian:/tmp$ g++ -Wall test.cpp
robert#debian:/tmp$ ./a.out
123
Value is 123
length of value is 3
robert#debian:/tmp$ ./a.out
abc
Value is abc
length of value is 3
You did not enter a number

C++ count number of characters in a string

I am so close, I need to count the number of given characters in a given string. It needs to loop over and over again but i keep getting this error:
countchar.cpp:27:22: error: â was not declared in this scope
countchar.cpp:27:38: error: â was not declared in this scope
countchar.cpp:27:61: error: â cannot be used as a function
I really am not too familiar with the algorith of count but if someone could help out, that would be appreciated. Here is my code:
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
char character;
string sentence;
char answer;
while(1) {
cout << "Enter a character to count the number of times it is in a sentence: ";
cin >> character;
cout << "Enter a sentence and to search for a specified character: ";
getline(cin, sentence);
if(character == '\n' || sentence.empty())
{
cout << "Please enter a valid answer:\n";
break;
}
else {
int count = count(begin(sentence), end(sentence), character);
cout << "Your sentence had" << count << character
<< "character(s)";
}
cout << "Do you wish to enter another sentence (y/n)?: ";
cin >> answer;
if (answer == 'n'){
break;
}
}
return 0;
}
The problem seems to be in this line:
int count = count(begin(sentence), end(sentence), character);
You declare a variable count and immediately after you use it as a function. You have to rename the variable (to, say, c) to use function std::count.
As for the remaining errors, you should use sentence.begin() instead of begin(sentence) and similarly sentence.end() instead of end(sentence).

Recognize "010" and similar numbers as a palindrome using modulus in C++

First post! This is my second semester with "Advanced C & C++" so any help is GREATLY appreciated. I've already scoured as much of stackoverflow and a few other resources to try and help me understand what I'm doing (or not doing) with this slew of logically inept code.
The goal of this program is to recognize whether or not a 'number' given by the user is a palindrome. Sounds simple enough right?! Ugh...well this is what I have been stuck on:
#include <iostream>
using std::cout;
using std::cin;
#include <string>
using std::string;
#include <cstdlib>
int main()
{
//variable declarations
string buffer;
//user input
cout << "Enter a number to see if it is a palindrome[Q to quit]: ";
getline(cin, buffer);
//looooop
while(buffer != "Q" && buffer !="q")
{
int userNum, length, sum = 0, temp;
userNum = atoi(buffer.c_str());
for(temp = userNum; userNum !=0; userNum=userNum/10)
{
length = userNum % 10;
sum = sum*10+length;
}
if(temp==sum)
cout << temp << " is a palindrome!!\n\n";
else
cout << buffer << " is NOT a palindrome!\n\n";
cout << "Enter a number to see if it is a palindrome[Q to quit]: ";
getline(cin, buffer);
}
}
The problem arises when input of "010", or "400" is given. "400" is essentially "00400" in this case and both should be seen as a palindrome.
A better approach would be to get trailing zeros for the given number as below:
int noOfTrailingZeros = str.length;
while(str[--noOfTrailingZeros]=='0');
noOfTrailingZeros = str.length - noOfTrailingZeros;
Or the integer way as:
int noOfTrailingZeros = str.length;
while(num%10==0)
{
noOfTrailingZeros++;
num/=10;
}
Now, check for the input string whether it has the same number of zeros befire the number or not as:
int counterZeros = 0;
while(str[counterZeros++]=='0');
check these 2 numbers and if trailing zeros are more than the zeros at beginning, add that many at the beginning and pass that string to palindrome function.
First of all, to recognize a palindrome, you don't have to do atoi. Just pass from the start to the middle checking if
buffer[i] == buffer[length - i]
Second, use the atoi to make sure it is a number and you're done.
Other way is to compare the string with itself reversed:
string input;
cout << "Please enter a string: ";
cin >> input;
if (input == string(input.rbegin(), input.rend())) {
cout << input << " is a palindrome";
}