C++ user input restrictions - c++

I'm currently working on a program and thinking if it is possible to implement another restrictions for the user input. The restrictions that I made as of now is that the user is only allow to input alpha and spaces, hitting enter without any input will not be also accepted.
cout<<"Input customer's lastname\t\t: ";
getline(cin,lname);
if(lname.find_first_not_of("abcdefghijklmnopqrstuvwxyz ")!=string::npos)
{
cout<<"You can only input alpha here!\n";
cin.clear();
goto p1;
}
else if(lname.empty())
{
cout<<"Please enter your lastname!\n";
cin.clear();
goto p1;
}
The another restrictions that I want is if the user input is all spaces, the program will also show a message. Second, I wonder if it's possible to detect the input if the user typed it properly like (de la Cruz) the words should be only separated by one space and if not another message will show. I cant think on how to do it, I already did some research but I couldn't found any similar to this with C++. I don't know if this is possible since I'm just starting to learn C++, or maybe I don't have enough logic at all. :(

A little help from me on checking for spaces.
bool has_only_spaces(const std::string& str)
{
return str.find_first_not_of (' ') == str.npos;
}
bool has_two_consecutive_spaces(const std::string& str)
{
for (unsigned int i = 1; i < str.length(); i++)
{
if ((str[i - 1] == str[i]) && (str[i] == ' '))
{
return true;
}
}
return false;
}
int main()
{
std::string lname;
std::cout << "Input customer's last name: ";
getline(std::cin, lname);
if (has_only_spaces(lname) || has_two_consecutive_spaces(lname))
{
std::cout << "Not a valid input" << std::endl;
std::cin.clear();
}
}

Create a function to check whether the input is valid. Use the function in a while loop.
bools isInputValid(std::string const& input)
{
// add all the checks
}
Use it as:
std::cout << "Enter input\n";
while ( getline(std::cout, line) )
{
if ( isInputValid(line) )
{
break;
}
std::cout << "Input is not vaild. Try again\n";
}

Related

How do i throw an exception if user input anything beside string?

I am stuck at where I want the user to enter a string only if the user enters a number is considered an invalid input.
Here is part of my code:
try {
cout << "What is the model of your car? ";
cin >> model;
//Error checking
// if user enter anything beside string excute this block
if (model ) {
throw runtime_error("INVALID INPUT");
}
cout << "what year is your " << model << "? ";
cin >> year;
if (cin.fail()) {
throw runtime_error("Not a number");
}
if (year < 0) {
throw runtime_error("Year can't be negative");
}
Well, model will always be a string, even if you put numbers in it. Because "1" is a string, and 65 is 'A', etc. But I think you mean how do you check if a string doesn't contain numbers.
bool contains_num(const std::string & str)
{
bool ret = false;
for(int i = 0; i < str.length(); i++)
if(isdigit(str[i]))
ret = true;
return ret;
}
This function will catch edge cases like an empty string, too.

Detect blank input on integer type variable?

I am currently working on a text based adventure game as a project for class. I have mostly everything started and working fine. The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room." For the life of me I cannot figure it out. Any help is much appreciated.
Code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
bool game_play = true;
bool game_start = true;
int room_change;
int room_current = 0;
while (game_play == true) {
if (game_start == true) {
srand((unsigned int)time(NULL));
room_change = rand() % 2 + 1;
game_start = false;
}
else {
for (bool check = false; check == false;) { // Check if input is invalid
cin >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
}
else if (room_change == room_current) {
cout << "You're already in that room.";
}
else {
check = true;
}
}
}
switch (room_change) {
case 1:
cout << "You are in room 1.";
room_current = 1;
break;
case 2:
cout << "You are in room 2.";
room_current = 2;
break;
case 3:
game_play = false;
break;
default:
cout << "That room doesn't exist.";
}
}
return 0;
}
I just ran your code and when you hit enter, it will keep waiting until you enter a number or something invalid such as a character or a string. I did find that if you change your code from
cin >> room_change;
to
cin >> noskipws >> room_change;
when the user inputs a blank, it will cause the cin.fail() to return true and then proceed to print "Choose an existing room."
In your situation, the while loop will keep getting called until we have valid input. The "Choose an existing room" does get repeated because room_change is an integer, so when we hit enter, the '\n' will be left in the buffer. The while loop on the next iteration then reads that '\n' and executes the cin.fail() before letting you input something else. One solution I found is to use more cin.ignore() statements.
for (bool check = false; check == false;) { // Check if input is invalid
cin >> noskipws >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
} else if (room_change == room_current) {
cout << "You're already in that room.";
cin.ignore();
} else {
check = true;
cin.ignore();
}
}
The reason is because we want to get rid of that '\n' so that the cin.fail() does not execute. However, I did find that when you input a character, it will print "Choose an existing room" twice. It will print the first time because a character is not an integer, and a second time because of that '\n'.
The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room."
Using std::getline and then extracting the number from the line using a std::istringstream is a better strategy for that.
std::string line;
std::cout << "Choose an existing room. ";
while ( std::getline(std::cin, line) )
{
// Try to get the room_change using istringstream.
std::istringstream str(line);
if ( str >> room_change )
{
// Successfully read the room.
break;
}
// Problem reading room_change.
// Try again.
std::cout << "Choose an existing room. ";
}
#include <iostream>
using namespace std;
int main(){
int room_change=200;
cout<<"Enter Blank";
cin>>room_change;
if(room_change==NULL){
cout<<"There is NO-THING"<<endl;
}
if(room_change!=NULL){
cout<<"There is something and that is :"<<room_change<<endl;
}
return 0;
}
But a much simpler approach to this would be to use Strings. If this is a Homework of sort and you are limited to Integer variable only. Its much more complicated if you want to detect if an Buffer is empty or not. Regardless of homework limitation, the OS layer input is String based. How can I use cin.get() to detect an empty user input?

Getting error "code will never execute" when using do-while loop for password checking function in c++e

I put a do/while loop in my password function but it doesn't work. I use xcode10 to code c++ and when I use a semicolon after the while statement it shows an error saying code will never execute
string password (string g)
{
string ch = "hello" ;
cout << "Enter password";
getline(cin, g);
do {
if (ch.compare(g) != 0) {
cout << " INCORRECT PASSWORD";
return (0);
} else {
cout << "correct password";
return (string(g));
}
} while (ch.compare(g) == 0); //this is where it shows the error that the code will never exec
}
I wanted to put this loop and a few other things so I can make this a infinite loop till you enter the correct password.
Well in your if statement you will return in both cases causing the function to stop so it will never get to the while condition to test it
string password(string g)
{
string ch = "hello";
cout << "Enter password\n";
do
{
getline(cin, g);
if (ch.compare(g) != 0)
{
cout << " INCORRECT PASSWORD\n";
}
else {
cout << "correct password";
return (string(g));
}
} while (ch.compare(g) != 0);
}
You need to check if you get input at all too, in case of EOF.
string password() { // you don't need g as parameters in, your overwriting it
string const ch = "hello"; // make ch const to show it not supposed to change
cout << "Enter password";
string g; // defining g here since now you need it
while (getline(cin, g)) { // check that the read from cin is OK
if (ch != g) { // simple notation for comparing two strings. There's also == available
cout << "INCORRECT PASSWORD. Please try again\n"; // no return if you want to try again
} else {
cout << "correct password";
return g; // you could also return ch here since they have the same content
}
}
cout << "Unable to read line. aborting\n"; // not really a lot you can do if there is no input to read.
return string(); // returning empty string.
}
There is Return statement in the "if" and also in the "else".
You can see that no matter what will be the result of ch.compare(g), the function will return to it's caller.
That's why it will never do the "while".
Try to set the Return statements in different place in the code :)

why the need for cin.unget() in this context, C++?

I'm relatively new to programming and i was experimenting with some codes from Bjarne's book on principles and practice using C++.
I would like to know why is there the need for cin.unget() when the input is not an integer whereas cin.unget() is not needed when the input is an integer?
Do note that this code is not perfect as the author is merely attempting to illustrate some pointers on users' input and output. The code is as follows:
void skip_to_int()
{
if (cin.fail()){
cin.clear();
for (char ch; cin>>ch; ) { // throw away non-digits
if (isdigit(ch) || ch=='-') {
cin.unget();
return;
}
}
}
error("no input");
}
int main(){
cout << "Please enter an integer in the range 1 to 10(inclusive):\n";
int n = 0;
while (true) {
if (cin>>n) { // we got an integer; now check it
if (1<=n && n<=10) break;
cout << "Sorry " << n
<< " is not in the [1:10] range; please try again\n";
}
else {
cout << "Sorry, that was not a number; please try again\n";
skip_to_int(); }
}
}
It's scanning through your input stream to find digits or - which is part of a negative digit presumably. This is a rather curious way of stripping off things like spaces or tabs.
The reason for unget() is to push that character back into the stream so it can be parsed later with cin>>n. If you consumed it and threw it away it wouldn't be available at that point.

Reading input commands with up to 3 commands

I have a program which prompts the user to input a command. Based on the command, it will perform different functions.
example commands:
help
set value 20
set another 30
print this
print that
How can I split these into 3 separate variables and continue the program? I'm having trouble with a simple
string command;
string item;
string value;
cin >> command >> item >> value;
Because unless the user inputs all three, the program won't continue.
This is what I came up with, I can't answer my own question so this will do.
Thank you for the input. This is what I came up with after researching some of those functions mentioned by #JoachimPileborg. It seems to work just how I need it.
int main() {
bool done = false;
char input[30];
std::string command, item, value;
//output instructions, get user input
std::cout << "Type 'help' to find more about commands.\n";
do{
std::cin.getline(input,30);
//parse user input from char to an array
istringstream iss;
string commands[3];
iss.str (input);
for (int i = 0; i < 3; i++) {
iss >> commands[i];
}
//set each part of the array to appropriate value
command = commands[0];
item = commands[1];
value = commands[2];
//properly sort out which command is being called
//first: check if command has 3 parts
if (commands[2].length() != 0){
cout << command << item << value;
}
//second:if it doesnt have 3 parts, check if it has 2 parts
else if (commands[1].length() != 0){
cout << command << item;
}
//third:if it doesn't have 2 parts, check for 1 part
else if (commands[0].length() != 0){
if (command == "help"){
commandline.help();
done = true;
}
else{
cout << "Incorrect Command! Please try again!";
}
}
else
cout << "No command found, please try again!";
}while(!done);
}
"How can I split these into 3 separate variables and continue the program?"
Don't have distinct variables, use an appropriate standard library container to collect a variable number of parameters given for a command.
The very simplest way,- I can imagine -, how to implement such thing, would probably look like this:
std::string cmdline;
while(cmdline != "quit") {
std::cout << "Enter command > ";
std::getline(std::cin),cmdline);
if(!cmdline.empty()) {
std::istringstream iss(cmdline);
std::vector<std::string> cmditems;
std::string cmditem;
while(iss >> cmditem) {
cmditems.push_back(cmditem);
}
if(cmditems.empty()) { // Just whitespaces input
continue;
}
// accessing cmditems[0] is always safe at this point
if(cmditems[0] == "help") {
printHelp();
}
else if(cmditems[0] == "set") {
// Check if the number of command arguments actually
// fit the required ones
if(cmditems.size() < 3) {
std::cerr << "Please enter a name and value!" << std::endl;
continue;
}
setValue(cmditems[1],cmditems[2]);
}
else if(cmditems[0] == "print") {
// Check if the number of command arguments actually
// fit the required ones
if(cmditems.size() < 2) {
std::cerr << "Please enter a name to print!" << std::endl;
continue;
}
printValue(cmditems[1]);
}
// and so on ...
}
}