Logic error when checking if input is alphanumeric - c++

The purpose of this program is to check if the character entered by the user is alphanumeric. Once the void function confirms correct entry then it is passed to string test to output a message. I know it's not great coding but it has to be done this way.
I keep getting a logic error & I can't figure out why? Can someone please help?
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
void get_option(char& input);
/**
Takes character entered user input and loops until correct answer
#param y character entered by user
#return to main() once valid entry received
*/
string test(char);
/**
Takes checks character entered user input and loops until correct answer
#param y alphanumeric character entered by user
#return to main() once valid entry received
*/
int main()
{
char y;
//call get_option to prompt for input
get_option(y);
//call test after user input is valid
test(y);
return 0;
}
void get_option(char &x)
{
cout << "Please enter an alphanumeric character: ";
cin >> x;
while (!(isdigit(x)||islower(x)||isupper(x)))
{
cout << "Please enter an alphanumeric character: ";
cin >> x;
}
}
string test(char y)
{
if (isupper(y))
{
cout << "An upper case letter is entered!";
} else if (islower(y)) {
cout << "A lower case letter is entered!";
} else if (isdigit(y)) {
cout << "A digit is entered!";
}
return "";
}

I got the program to work perfectly by changing the return type of the test(char) function:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
void get_option(char& input);
/**
Takes character entered user input and loops until correct answer
#param y character entered by user
#return to main() once valid entry received
*/
int test(char); //Changed from string to int
/**
Takes checks character entered user input and loops until correct answer
#param y alphanumeric character entered by user
#return to main() once valid entry received
*/
int main()
{
char y;
//call get_option to prompt for input
get_option(y);
//call test after user input is valid
test(y);
return 0;
}
void get_option(char &x)
{
cout << "Please enter an alphanumeric character: ";
cin >> x;
while (!(isdigit(x)||islower(x)||isupper(x)))
{
cout << "Please enter an alphanumeric character: ";
cin >> x;
}
}
int test(char y) //Also changed from string to int
{
if (isupper(y))
{
cout << "An upper case letter is entered!";
} else if (islower(y)) {
cout << "A lower case letter is entered!";
} else if (isdigit(y)) {
cout << "A digit is entered!";
}
return 0;
}
(Testing was on JDoodle using the C++14 compiler.)
(Also, tested using Xcode. Still works)

When I tried it in my setup (g++ 6.4, cygwin), I did not get any output. When I added << endl to the output lines, the output showed up.
I suspect you're experiencing the same problem.
string test(char y)
{
if (isupper(y))
{
cout << "An upper case letter is entered!" << endl; // Add endl
}
else if (islower(y))
{
cout << "A lower case letter is entered!" << endl;
}
else if (isdigit(y))
{
cout << "A digit is entered!" << endl;
}
// This does not make sense but it is syntactically valid.
return 0;
}
JiveDadson is right. The problem was the return 0 line. It causes undefined behavior. Changing the that line to
return "";
fixes the output problem, endl or not. Having the endl is nicer but is not necessary. Fixing the return statement is the most important task.

Related

Whats a good way to get the program to end based on user input?

I did my "Hello World", I'm just getting started on my programming adventure with C++. Here is the first thing I've written, what are some ways to get it to end with user input? I'd like a yes or no option that would terminate the program. Also any feedback is welcome, thank you
#include <iostream>
using namespace std;
void Welcome();
void calculateNum();
void tryAgain();
int main() {
Welcome();
while (true) {
calculateNum();
tryAgain();
}
system("pause");
}
void calculateNum() {
float userNumber;
cin >> userNumber;
for (int i = 100; i >= 1; i--) {
float cNumber = i* userNumber;
cout << i << " >>>>> " << cNumber << endl;
}
}
void Welcome() {
cout << "Welcome \n Enter a number to see the first 100 multiples \n";
}
void tryAgain() {
cout << "Try again? Enter another number... ";
}
Here is one option:
Switch to do ... while loop, with the condition at the end.
Make your tryAgain() function return a boolean and put it in the while condition.
In tryAgain function read input from the user, and compare it to expected answers.
First, lets add a new header for string, it will make some things easier:
#include <string>
Second, lets rebuild the loop:
do {
calculateNum();
} while (tryAgain());
And finally, lets modify the function:
bool tryAgain() {
string answer;
cout << "Try again? (yes / no)\n";
cin >> answer;
if (answer == "yes") return true;
return false;
}
Now, there is a slightly shorter way to write that return, but it might be confusing for new learners:
return answer == "yes";
You don't need the if because == is an operator that returns bool type value.
You can change your calculateNum() in the following way:
Change the return value of your calculateNum() function into bool to indicate whether the program shall continue or stop
read the input into a std::string
check if the string is equal to your exit string like 'q' for quit
3.a in that case, your function returns false to indicate the caller that the program shall stop
3.b otherwise, create a stringstream with your string and read the content of the stream into your float variable and continue as you do like now
In your loop in your main function you break if calculateNum() returned false
Here is a simple solution:
#include <iostream>
// Here are two new Includes!
#include <sstream>
#include <string>
using namespace std;
void Welcome();
// Change return value of calculateNum()
bool calculateNum();
void tryAgain();
int main()
{
Welcome();
while (true)
{
if (!calculateNum())
break;
tryAgain();
}
system("pause");
}
bool calculateNum()
{
//Read input into string
string userInput;
cin >> userInput;
//Check for quit - string - here just simple q
if (userInput == "q")
return false;
//otherwise use a std::stringstream to read the string into a float as done before from cin.
float userNumber;
stringstream ss(userInput);
ss >> userNumber;
//and proces your numbers as before
for (int i = 100; i >= 1; i--)
{
float cNumber = i * userNumber;
cout << i << " >>>>> " << cNumber << endl;
}
return true;
}
void Welcome()
{
cout << "Welcome \n Enter a number to see the first 100 multiples \n";
}
void tryAgain()
{
cout << "Try again? Enter another number... ";
}
Having your users input in a string you can even do further checks like checking if the user entered a valid number, interpret localized numbers like . and , for decimal delimitters depending on your system settings and so on.

C++ program stuck in an infinite loop

Please note that I am a complete beginner at C++. I'm trying to write a simple program for an ATM and I have to account for all errors. User may use only integers for input so I need to check if input value is indeed an integer, and my program (this one is shortened) works for the most part.
The problem arises when I try to input a string value instead of an integer while choosing an operation. It works with invalid value integers, but with strings it creates an infinite loop until it eventually stops (unless I add system("cls"), then it doesn't even stop), when it should output the same result as it does for invalid integers:
Invalid choice of operation.
Please select an operation:
1 - Balance inquiry
7 - Return card
Enter your choice and press return:
Here is my code:
#include <iostream>
#include <string>
using namespace std;
bool isNumber(string s) //function to determine if input value is int
{
for (int i = 0; i < s.length(); i++)
if (isdigit(s[i]) == false)
return false;
return true;
}
int ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
else if (rtrn == "2" and isNumber(rtrn)) { return true; }
else {cout << "Invalid choice." << endl; ReturnCard(); };
return 0;
}
int menu() //function for operation choice and execution
{
int choice;
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == 1 and isNumber(to_string(choice))) { cout << "Your balance is $" << balance; "\n\n"; }
else if (choice == 7 and isNumber(to_string(choice))) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; menu(); }
} while (ReturnCard()==false);
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}
I've tried every possible solution I know, but nothing seems to work.
***There is a different bug, which is that when I get to the "Do you wish to continue?" part and input any invalid value and follow it up with 2 (which is supposed to end the program) after it asks again, it outputs the result for 1 (continue running - menu etc.). I have already emailed my teacher about this and this is not my main question, but I would appreciate any help.
Thank you!
There are a few things mixed up in your code. Always try to compile your code with maximum warnings turned on, e.g., for GCC add at least the -Wall flag.
Then your compiler would warn you of some of the mistakes you made.
First, it seems like you are confusing string choice and int choice. Two different variables in different scopes. The string one is unused and completely redundant. You can delete it and nothing will change.
In menu, you say cin >> choice;, where choice is of type int. The stream operator >> works like this: It will try to read as many characters as it can, such that the characters match the requested type. So this will only read ints.
Then you convert your valid int into a string and call isNumber() - which will alway return true.
So if you wish to read any line of text and handle it, you can use getline():
string inp;
std::getline(std::cin, inp);
if (!isNumber(inp)) {
std::cout << "ERROR\n";
return 1;
}
int choice = std::stoi(inp); // May throw an exception if invalid range
See stoi
Your isNumber() implementation could look like this:
#include <algorithm>
bool is_number(const string &inp) {
return std::all_of(inp.cbegin(), inp.cend(),
[](unsigned char c){ return std::isdigit(c); });
}
If you are into that functional style, like I am ;)
EDIT:
Btw., another bug which the compiler warns about: cout << "Your balance is $" << balance; "\n\n"; - the newlines are separated by ;, so it's a new statement and this does nothing. You probably wanted the << operator instead.
Recursive call bug:
In { cout << "Invalid choice of operation."; menu(); } and same for ReturnCard(), the function calls itself (recursion).
This is not at all what you want! This will start the function over, but once that call has ended, you continue where that call happened.
What you want in menu() is to start the loop over. You can do that with the continue keyword.
You want the same for ReturnCard(). But you need a loop there.
And now, that I read that code, you don't even need to convert the input to an integer. All you do is compare it. So you can simply do:
string inp;
std::getline(std::cin, inp);
if (inp == "1" || inp == "2") {
// good
} else {
// Invalid
}
Unless that is part of your task.
It is always good to save console input in a string variable instead of another
type, e.g. int or double. This avoids trouble with input errors, e.g. if
characters instead of numbers are given by the program user. Afterwards the
string variable could by analyzed for further actions.
Therefore I changed the type of choice from int to string and adopted the
downstream code to it.
Please try the following program and consider my adaptations which are
written as comments starting with tag //CKE:. Thanks.
#include <iostream>
#include <string>
using namespace std;
bool isNumber(const string& s) //function to determine if input value is int
{
for (size_t i = 0; i < s.length(); i++) //CKE: keep same variable type, e.g. unsigned
if (isdigit(s[i]) == false)
return false;
return true;
}
bool ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
if (rtrn == "2" and isNumber(rtrn)) { return true; } //CKE: remove redundant else
cout << "Invalid choice." << endl; ReturnCard(); //CKE: remove redundant else + semicolon
return false;
}
int menu() //function for operation choice and execution
{
string choice; //CKE: change variable type here from int to string
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == "1" and isNumber(choice)) { cout << "Your balance is $" << balance << "\n\n"; } //CKE: semicolon replaced by output stream operator
else if (choice == "7" and isNumber(choice)) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; } //CKE: remove recursion here as it isn't required
} while (!ReturnCard()); //CKE: negate result of ReturnCard function
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}

Assigning the "Enter Key" value to a string [C++]

In this rather simple exercise I have to receive an user input, store said input into a string, pass the string to a function by reference and finally modify the string so that every character is "parsed" by the toupper() function.
However, should the user insert 'q' as input, the program stops saying "Bye" OR if he just presses the Enter Key, the program is supposed to say something like "Hey, this string is empty".
Now the real problem here is in the last part since my code won't manage the case where the user inputs only the Enter Key value (to be honest, even if I just text a bunch of spaces followed by the Enter Key, nothing happens)
void uppercase(std::string &);
int main(){
using namespace std;
string ex2;
cout << "Exercise 2" <<endl;
while(ex2!="Bye"){
cout << "Enter a string(q to quit): ";
cin >> ex2;
cout << "Was: " << ex2 << endl << "Now is: ";
uppercase(ex2);
}
return 0;
}
void uppercase(std::string &str){
using namespace std;
if(str[0]=='\n')
cout <<"Empty string dude!" << endl;
else{
if(str.length()==1 && str[0]=='q'){ //press 'q' to exit program
str="Bye";
cout << str;
}
else{ //uppercase
for(int i=0;i<str.length();i++){
str[i]=(toupper(str[i]));
}
cout << str <<endl;
}
}
}
I also tried the compare() function and even to compare the whole string to null (pointless, but still worth a shot) and to the string "";
Sorry for the bad interpretation of your problem, trying
if( (str.length()==1 && str[0]=='q') || str.length() == 0)
{}
May help you out of the problem

Show * while I input (Hide/mask input)

I am in the process of getting password as input.
I have gone through various examples but they either used while loop or SETCONSOLE method. Both had issues.
Implementing while loop printed 1 * before I even entered a char. The other method used echo to HIDE the characters while I typed whereas I want to be printed. I would appreciate helping me masking my input with a * using SETCONSOLE method. I would be greatly obliged. The code's attached !
void signup(){
gotoxy(10, 10);
string n, p1,p2;
cout << "Enter your username: " << endl; // TEST if username already exists
gotoxy(31, 10);
cin >> n;
lp:
gotoxy(10, 11);
cout << "Enter your password: " << endl; // TEST if username already exists
gotoxy(31, 11);
getline(cin, p1);
system("cls");
gotoxy(10, 10);
cout << "Re-Enter your password to confirm: " << endl; // TEST if username already exists
gotoxy(45, 10);
getline(cin, p2);
if (p2!=p1)
{
system("cls");
gotoxy(10, 10);
cout << "Passwords donot match! Please enter again!";
goto lp;
}
}
Here a simple example using getch. YES it c method, not c++, but it is very efficient.
It can be extended to block spaces, tabs, etc.
Also see the comments in the code...
#include <iostream>
#include <string>
#include<conio.h>
using namespace std;
int main(){
string res;
char c;
cout<<"enter password:";
do{
c = getch();
switch(c){
case 0://special keys. like: arrows, f1-12 etc.
getch();//just ignore also the next character.
break;
case 13://enter
cout<<endl;
break;
case 8://backspace
if(res.length()>0){
res.erase(res.end()-1); //remove last character from string
cout<<c<<' '<<c;//go back, write space over the character and back again.
}
break;
default://regular ascii
res += c;//add to string
cout<<'*';//print `*`
break;
}
}while(c!=13);
//print result:
cout<<res<<endl;
return 0;
}
You probably want to use getch() (#include <conio.h>) to read a character without its being echoed to the screen. Then when you've validated that it's a character you want to accept, you can print out a * at the correct position.

error: expected primary-expression before '.' token

I am currently teaching myself C++ using A C++ for Dummies All-In-One; second edition. TO create this program I am using Qt. I understand it to be a good practice to organize objects and classes in your header files and prospectively your member functions in a .cpp file built in addition to the main.cpp. In this regard I try to run the exercises in this book as such but just recently encountered the following error.
expected primary-expression before '.' token
This error occurs on Lines 31, 32, and 37 so they appear to be relevant to my class member functions specifically.
My main.cpp
#include "controlinginput.h"
#include <QtCore/QCoreApplication>
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// just a basic name-entering
string name;
cout << "What is your name?";
cin >> name;
cout << "Hello " << name << endl;
/* now you are asked for a number
but the computer will allow you to enter anything*/
int x;
cout << endl << "Enter a number! Any Number!" << endl;
cin >> x;
cout << "You choose " << x << endl;
/* now youll be asked for a number again
but the computer will only allow numbers */
cout << endl<< "This time you will ONLY be able to enter a number! " << endl;
cout << "SO, Pick a number! any number!" << endl;
string entered = ControlingInput.enterOnlyNumbers(); // ###Error###
int num = ControlingInput.stringToANumber(entered); // ###Error###
cout << endl << "You entered " << num << endl; // value is displayed
//Now finally we enter the password
cout << endl;
cout << "Please enter a password" << endl;
string password = ControlingInput.EnterPassword(); // ###Error###
cout << "shh... your password is " << password << endl;
return a.exec();
}
I did some research to find that this error indicates a pretty broad range of misuse of syntax. Unfortunately I was unable to find an instance that resembled mine specifically; I was hoping to get some insight from some of the more experienced programmers. If this is a simple issue that is on account of negligence on my end I apologize in advance and appreciate the feedback. I learn better if it gave me allot of trouble as opposed to a little..
Because these include my member functions I have also included my header file and .cpp
controlingInput.cpp (I have included my header file and iostream and sstream here but for some reason the editor was giving me problems on here)
using namespace std;
ControlingInput::ControlingInput()
{
}
int ControlingInput::stringToANumber(string MyString)
{
istringstream converter(MyString); //Holds the string that was passed to this function
int result; //Holds the integer result
//perform the conversion
converter >> result;
return result; //function completes and returns converted string
}
string ControlingInput::enterOnlyNumbers()
{
string numbAsString = ""; // this holds our numeric string
char ch = getch(); // This gets a single character from our user
//Says to keep gettting characters from our user untill user presses enter
while (ch != '\r') // \r is the enter key
{
//This says to add characters only if they are numbers
if (ch >= '0' && ch <='9')
{
cout << ch; // show
numbAsString += ch; // add character to the string
}
ch = getch(); // get the next character from the user
}
return numbAsString;
}
string ControlingInput::EnterPassword()
{
string numbAsString = ""; //this will hold our password string
char ch = getch(); // this gets a single char from our users just like before
//keep gettting characters from the user until enter/return is pressed
while (ch != '\r'); // \r is the enter or return key
{
//for security passwords are displayed as asterisks instead of characters
cout << '*';
//add character input into the password string
numbAsString += ch;
//Get the next character from the user
ch = getch();
}
return numbAsString; // return the user input from this function
And Here is my controlingInput.h
#ifndef CONTROLINGINPUT_H
#define CONTROLINGINPUT_H
#include <iostream>
using namespace std;
class ControlingInput
{
public:
int stringToANumber(string MyString);
string EnterPassword();
string enterOnlyNumbers();
};
#endif // CONTROLINGINPUT_H
Thanks in advance for any feedback.
You are attempting to call instance variables with the class itself as if they were static (which would still be invalid syntax). For this to work properly you need an instance of ControlingInput.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ControlingInput ctrlInput; //Create instance
...
string entered = ctrlInput.enterOnlyNumbers();
int num = ctrlInput.stringToANumber(entered);
cout << endl << "You entered " << num << endl; // value is displayed
...
string password = ctrlInput.EnterPassword();
cout << "shh... your password is " << password << endl;
return a.exec();
}