C++ How to protect against invalid input? - c++

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

Related

How can I throw a error if the user enters more than one integer

So this is my code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
long int iterFunc(int);
long int recurFunc(int);
int main() {
int n;
while(true){
try{
cout << "Enter: ";
if (!(cin >> n))
throw("Type Error");
if (n < 0)
throw n;
else
if (n == 0)
break;
cout << "Iterative: " << iterFunc(n) << endl;
cout << "Recursive: " << recurFunc(n) << endl;
}
catch(int n){
cout << "Error. Enter positive number." << endl;
}
catch(...){
cin.clear();
cin.ignore(100, '\n');
cout << "Error. Please enter a number" << endl;
}
}
cout << "Goodbye!";
return 0;
}
long int iterFunc(int n){
vector<long int> yVec = {1, 1, 1, 3, 5};
if (n <= 5)
return yVec[n - 1];
else
for(int i = 5;i < n; i++){
long int result = yVec[i - 1] + 3 * yVec[i- 5];
yVec.push_back(result);
}
return yVec.back();
}
long int recurFunc(int n){
switch (n) {
case 1:
case 2:
case 3:
return 1;
break;
case 4:
return 3;
break;
case 5:
return 5;
break;
default:
return recurFunc(n - 1) + 3 * recurFunc(n - 5);
break;
}
}`
The program shoud accept only one integer and return the y of the function using both iterative and recursive implemetations. Ex.: 30, 59, 433. How can I throw an error message if the user enters more then one integer, separated by space? Ex.: '3 45 32'.
I tried using if (cin.getline == ' ') throw("Error name") but the program still executes and return the y of the function for number in the input
Something like this works:
int main()
{
std::string str;
std::cout << "? : ";
std::getline(std::cin, str);
std::string::size_type pos(0);
int i = std::stoi(str, &pos);
if (pos != str.length())
return 1;
}
I found a part of my old code that might come in handy.
int val;
do
{
cin>>val;
if(!cin){ //you can add more conditions here
cin.clear();
cin.sync();
/* additional error handling */
}
else{
break; //input is correct - leaving loop
}
}while(true); //or here
Basically what !cin does is - it checks what type of value you actually want to write to, because it's needed anyway to figure out if data type is written to the correct type of our val. This means, that "30" or "433" etc. are integers (correct), "s" or "string" etc. are strings (or char*, correct me if I am wrong) (incorrect).
This also means, that "3 45 32" should be interpreted as string, which should result in another loop run.
Note: I didn't really test this code, so it might be completely wrong.
Edit: Okay now after some tests I realised this code needs some retweaking.
Firstly, "3 45 32" is not interpreted as string (now understandable). Instead, first number (before whitespace) is saved as an integer and all other numbers are stored in the buffer (next cin will be filled with it), which we can avoid using cin.clear() and cin.sync() once again.
The question is - is it okay for you to accept the first integer and ignore everything after the first whitespace? If not, you will have to save the input as string and extract whatever data you want from it.
I am leaving the original answer as is for simplicity of finding references in this edit.

When I input a number in char type, why i can't get a whole number?

I input a number in char type variable. like 12 or 22. but, console show me a 1 or 2.
How i get a whole number 12 ,22 in console?
#include <iostream>
int main()
{
using namespace std;
char a = 0;
cin >> a;
cout << a << endl;
return 0;
}
Here is console result.
12
1
C:\Users\kdwyh\source\repos\MyFirstProject\Debug\MyFirstProject.exe(프로세스 18464개)이(가) 종료되었습니다(코드: 0개).
이 창을 닫으려면 아무 키나 누르세요...
The reason I don't use int, string and something is because I want to get both number and Character in one variable.
So I want to see the results of combined numbers and character at the same time.
in that process i can't get a whole number.
#include <iostream>
using namespace std;
int index = 0;
constexpr int pagenum = 10;
void chapterlist(void);
void nextlist(void);
void beforelist(void);
void movechapter(char a);
int main(void)
{
char userin = 0;
bool toggle = 0;
cout << "결과를 볼 챕터를 고르시오." << endl;
chapterlist();
cout << "다음 페이지로 이동: n" << endl;
cin >> userin;
if (userin == 'n')
{
backflash:
while(toggle == 0)
{
nextlist();
cin >> userin;
if (userin == 'b')
{
toggle = 1;
goto backflash;
}
else if (userin == 'n')
continue;
else
{
system("cls");
movechapter(userin);
break;
}
}
while(toggle == 1)
{
beforelist();
cin >> userin;
if (userin == 'n')
{
toggle = 0;
goto backflash;
}
else if (userin == 'b')
continue;
else
{
system("cls");
movechapter(userin);
break;
}
}
}
else
{
system("cls");
movechapter(userin);
}
return 0;
}
void chapterlist(void)
{
int x = 0;
for (x = index + 1; x <= index + 10; x++)
cout << "Chapter." << x << endl;
}
void nextlist(void)
{
system("cls");
cout << "결과를 볼 챕터를 고르시오." << endl;
index = index + pagenum;
chapterlist();
cout << "다음 페이지로 이동: n" << endl;
cout << "이전 페이지로 이동: b" << endl;
}
void beforelist(void)
{
system("cls");
cout << "결과를 볼 챕터를 고르시오." << endl;
index = index - pagenum;
chapterlist();
cout << "다음 페이지로 이동: n" << endl;
cout << "이전 페이지로 이동: b" << endl;
}
void movechapter(char a)
{
cout << "선택한 Chapter." << a << "의 결과입니다." << endl;
}
In movechapter(), console show me a is 1 or 2, not 12, 22.
First, you have to understand what achar type is.
Character types: They can represent a single character, such as 'A' or '$'. The most basic type is char, which is a one-byte character. Other types are also provided for wider characters.
To simplify that, char can only hold one character.
Where as with your code, "12" is actually 2 separate characters, '1' and '2', and that's the reason it would not work.
Instead of declaring a as a char type, you could declare it as an int type, which is a type designed to hold numbers. So you would have:
int a = 0;
However, do note that int often has a maximum value of 2^31.
Or you could use std::string to store character strings. However, do note that if you wish to do any calculations to your string type, you would need to convert them to a number type first:
int myInt = std::stoi(myString);
Edit:
So I have re-checked your code after your update, there is nothing wrong with using std::string in your case. You can still check if user have input n or b by:
if (userin == "n")
Note that you would use double quotation mark, or "letter", around the content that you want to check.
On the other hand, you could use:
if(std::all_of(userin .begin(), userin.end(), ::isdigit))
To check if user have input a number.
Although char is just a number, it's presumed to mean "single character" here for input. Fix this by asking for something else:
int a = 0;
You can always cast that to char as necessary, testing, of course, for overflow.
You should be reading characters into a string, and then converting that string into an int. It would also probably make more sense to use something like getline() to read input, rather than cin >> a.
#include <string>
#include <iostream>
#include <stdexcept>
#include <stdio.h>
int main() {
std::string input_string;
/* note that there is no function that will convert an int string
to a char, only to an int. You can cast this to a char if needed,
or bounds check like I do */
int value;
while(1) {
getline(std::cin, input_string);
/* std::stoi throws std::invalid_argument when given a string
that doesn't start with a number */
try {
value = std::stoi(input_string);
} catch (std::invalid_argument) {
printf("Invalid number!\n");
continue;
}
/* You wanted a char, the max value of a `char` is 255. If
you are happy for any value, this check can be removed */
if (value > 255) {
printf("Too big, input a number between 0-255\n");
continue;
}
break;
}
printf("Number is %hhu\n", value);
}

How to allow only numbers in a variable?

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;
}
}

How do I change the int variable in a cycle and if so is there a more efficient way?

First post ever on this site so spare my life , please.
I'm trying to do a little encryption and decryption program imitating the Enigma cipher/machine from the WW2 (enough history lessons)
So I'm trying to input a number and a letter like so : 1h 2e 3l 4l 5o ;
Because I don't use a cycle I need to write for every variable that I'm adding the number , but what do I do if I have less letters than variables?The only way I can think of is using a cycle which checks if the input is a letter or not.That's why the current code I've written only can be used for specific amount of numbers and letters...
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int opt;
cout<<"Enter 1 for encryption and 2 for decryption. "<<endl;
cin>>opt;
if(opt == 1)
{
int setting1,setting2,setting3,setting4;
char a,b,c,d;
cout<<"_________________________________________________"<<endl;
cin>>setting1>>a>>setting2>>b>>setting3>>c>>setting4>>d;
a+=setting1;
b+=setting2;
c+=setting3;
d+=setting4;
cout<<(char)a<<" "<<(char)b<<" "<<(char)c<<" "<<(char)d<<endl;
}
if(opt == 2)
{
int setting1,setting2,setting3,setting4;
char a,b,c,d;
cout<<"_________________________________________________"<<endl;
cin>>setting1>>a>>setting2>>b>>setting3>>c>>setting4>>d;
a-=setting1;
b-=setting2;
c-=setting3;
d-=setting4;
cout<<(char)a<<(char)b<<(char)c<<(char)d<<endl;
}
if(opt !=1 && opt !=2)cout<<"ERROR!"<<endl;
std::cout << "Press ENTER to continue..."<<endl;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(),'\n');
return 0;
}
Also I was told that the last 2 lines would prevent the .exec from closing after it's done doing it's thing.
I recommend inputting your data in loops (cycles). But before that is accomplished, I suggest using a structure (or class) with an overloaded stream extraction operator.
struct Number_Letter
{
int number;
char letter;
friend std::istream& operator>>(std::istream& inp, Number_Letter& nl);
};
std::istream& operator>>(std::istream& inp, Number_Letter& nl)
{
inp >> nl.number;
if (inp)
{
inp >> nl.letter;
if (!isalpha(nl.letter))
{
// Error recovery for not reading a letter
}
}
else
{
// Error recovery for failing to read number.
}
return inp;
}
Your input loop would be something like:
Number_Letter nl;
while (std::cin >> nl)
{
// process the data
}
For cryptography, you may want to keep the data as a string:
std::string message;
getline(cin, message);
for (unsigned int i = 0; i < message.length(); i += 2)
{
if (!isdigit(message[i]))
{
cerr << "Invalid message type at position " << i << endl;
break;
}
if (i + 1 > message.length())
{
cerr << "Missing letter at end of message.\n";
break;
}
if (!isalpha(message[i+1]))
{
cerr << "Invalid message type at position " << i << endl;
break;
}
}
It sounds like you're trying to check for an unknown sequence of character/integers and need a loop to do the check?
int opt;
cout<<"Enter 1 for encryption and 2 for decryption. "<<endl;
cin>>opt;
if(opt != 1 && opt != 2)
{
cout << "Error" << endl;
return -1;
}
int integer;
char character;
char again;
do
{
cout<<"_________________________________________________"<<endl;
cin>>integer>>character;
if(opt == 1) {
character+=integer;
} else if(opt == 2) {
character-=integer;
}
cout << character <<endl;
cout << "Again (Y)?: ";
cin>>again;
}while(again == 'Y' || again == 'y');
std::cout << "Press ENTER to continue..."<<endl;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(),'\n');
return 0;

Adding a number to a word to call up a variable

Please be nice I am a total newby.
I have a list of variables (strings) from num1 to num90. I need to call these from a function by adding the number in an int to the word num.
The task is to convert digits to words from 'jumping into c++'...I might not be going about it in the 'right' way but this part has been stopping me for a while now!!
I'm trying like this:
#include <iostream>
#include <string>
using namespace std;
// Hard code numbers to 20 and then in tens to 90
string num1 = "one";
string num2 = "two";
string num3 = "three";
string num4 = "four";
string num5 = "five";
string num6 = "six";
string num7 = "seven";
string num8 = "eight";
string num9 = "nine";
Etc...up to 90
int main ()
{
// Break the number down into three digit blocks
int num = 0;
cout << "Please enter the number: ";
cin >> num;
while (num > 999)
{
int digit = (num % 1000);
num = ((num - digit)/1000);
//cout << digit << '\n';
//cout << num << '\n';
// For each block of numbers work out hundreds,
if (digit > 100)
{
int i = digit;
int j = (i % 100);
cout << num.append(j) << " hundred";
}
What I need to happen is the number stored in 'j' to be tagged onto the word num in order to call the string num*.
Is this possible?
Sure, use a map:
#include <map>
#include <string>
#include <iostream>
std::map<int, std::string> words { { 1, "one" }, { 2, "two" }, { 3, "three" } };
int main()
{
std::cout << words[1] << std::endl;
}
You'll probably have to deal with some special cases (up to twenty?), and you need a word for "hundred", etc. If you want to make it internationalizable, you'll have to think even harder.
What I need to happen is the number stored in 'j' to be tagged onto
the word num in order to call the string num*.
The trouble with that approach is that any variable names you use in your code are not compiled: when the program runs it will manipulate the values of your variables, but it doesn't know or care that you decided to use the name "num3" instead of "numero3" or "foobar".
If you want to make a link between a digit (3) and a string ("three") then you can use a Vector (as #Mark suggests, although you'll have problems after 20) or better still a Map (as #Kerrek suggests): these will work because in both cases the strings are referenced by the value of a variable (eg the value of digit in lookup[digit], or the literal value 1 in words[1]) rather than by the name of a variable.
EDIT:
For interest, here's a version using 'if' and 'switch'...
#include <iostream>
#include <string>
using namespace std;
string units2word(int units){
switch (units){
case 0: return "zero";
case 1: return "one";
case 2: return "two";
case 3: return "three";
// etc ...
case 18: return "eighteen";
case 19: return "nineteen";
}
}
string tens2word(int tens){
switch(tens){
case 2: return "twenty";
case 3: return "thirty";
// etc ...
case 9: return "ninety";
}
}
string num2words(int num) {
if (num > 99 && num%100 == 0) return units2word(num/100) + " hundred";
if (num > 99) return units2word(num/100) + " hundred and " + num2words(num%100);
if (num < 20) return units2word(num);
if (num%10 == 0) return tens2word(num/10);
return tens2word(num/10) +"-"+ units2word(num%10);
}
int main(int argc, char *argv[]) {
int num = -1;
while( num < 0 || num > 999){
cout << "Please enter a number between 0 and 999: ";
cin >> num;
}
cout << "You typed: " << num2words(num) << endl;
}
You should look at using std::vector. This gives you a variable that takes an index
std::vector<std::string> lookup;
lookup.push_back( "zero" ); // starts at lookup[0]
lookup.push_back( "one" );
lookup.push_back( "two" );
// etc
// then
std::cout << lookup[digit] << std::endl;
std::cout << lookup[num] << std::endl;