Comparing char for validation in C++ - c++

/*
PROGRAM: Ch6_14.cpp
Written by Corey Starbird
This program calculates the balance
owed to a hospital for a patient.
Last modified: 10/28/13
*/
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
// Prototypes for In-patient and Out-patient functions.
double stayTotal (int, double, double, double); // For In-patients
double stayTotal (double, double); // For Out-patients
int main()
{
char patientType; // In-patient (I or i) or Out-patient (O or o)
double rate, // Daily rate for the In-patient stay
servCharge, // Service charge for the stay
medCharge, // Medication charge for the stay
inTotal, // Total for the In-patient stay
outTotal; // Total for the Out-patient stay
int days; // Number of days for the In-patient stay
// Find out if they were an In-patient or an Out-patient
cout << "Welcome, please enter (I) for an In-patient or (O) for an Out-patient:" << endl;
cin >> patientType;
while (patientType != 'I' || 'i' || 'O' || 'o')
{
cout << "Invalid entry. Please enter either (I) for an In-patient or (O) for an Out-patient:" << endl;
cin >> patientType;
}
cout << "FIN";
return 0;
}
Hey, brand new to C++ here. I am working on a project and I'm having trouble figuring out why my validation for patientTypeisn't working properly. I first had double quotes, but realized that would denote strings. I changed them to single quotes, my program will compile and run now, but the while loop runs no matter what I enter, I, i, O, o, or anything else.
I don't know why the while loop isn't checking the condition, seeing that I did enter one of the characters in the condition, and move on to cout. Probably a simple mistake, but I thank you in advance.

Your while condition is wrong.
You most likely want this:
while (patientType != 'I' && patientType != 'i' && patientType != 'O' && patientType != 'o')
You got to use &&. patientType isn't I or it isn't i would be always true. Also you got to use patientType != for every item being checked or the characters i, o, O would be implicitly converted to bool (true for all of them).

while (patientType != 'I' && patientType != 'i' &&
patientType != 'O' && patientType != 'o')
As written, the condition is always true, because three of the four expressions OR-ed together are non-zero.

The problem is this line
(patientType != 'I' || 'i' || 'O' || 'o')
This doesn't do what you think, you want
(patientType != 'I' && patientType != 'i' && patientType != 'O' && patientType != 'o')
The comparison operators are strictly between two values, the left and right side.
C and C++ treat any value that is not zero as being "true". So,
(patientType != 'I' || 'i' || 'O' || 'o')
Was being translated as
(patientType != 'I') or ('i' is not 0) or ('O' is not 0) or ('o' is not 0)

Related

Unable to compare characters (c++)

I'm trying to make a simple mad libs program in c++, and i want to check and see if a word that a user entered starts with a vowel, and if it does, change the "a" before the word, to an "an". I've been able to get the first character stored, but it will not compare to the other characters in the If statement. Am i doing this completely wrong?
#include <string>
#include <iostream>
using namespace std;
int main() {
string adj_3;
string anN;
char firstChar;
// GETTING USER'S WORD
cout << "ADJECTIVE: " << endl;
getline(cin, adj_3);
// GETTING FIRST CHARACTER
firstChar = adj_3[0];
// SEEING IF IT'S A VOWEL (not working)
if(firstChar == ('a' || 'e' || 'i' || 'o' || 'u' || 'A' || 'E' || 'I' || 'O' || 'U')) {
anN = "n";
}
else {
cout << "not working" << endl;
}
cout << "I am having a" << anN << " " << adj_3 << " time at camp." << endl;
}
The || operator needs to be applied to two arguments, like so:
if (firstChar == 'a' || firstChar == 'e' || firstChar == 'i' || ...)
firstChar == 'a' evaluates to a boolean. firstChar == 'a' || firstChar == 'e' takes the two booleans that results from those two operations, and returns another boolean, which is then fed into the next || operation as the first argument. In this way you can "chain" the || operations until one of them is true, or until they're all false.
See here for examples and explanation.
hnefatl's answer is one way.
You can also use switch case without break statements to check vowel. Something like:
switch(firstChar)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'A':
case 'E':
case 'I':
case 'O':
case 'U': cout<<"Vowel";
}
On top of that switch-case have many advantages over if-else ladder as stated here https://stackoverflow.com/a/1028463/6594779.
Logical operator || combines two boolean expressions, e.g. a==0 || b==1, and returns true if either of the two operands is true. If you pass a single character like 'a' as operand, this will be interpreted as true, since the value of 'a' is 97 and 97 != 0 => true. Hence, your expression ('a' || 'e' || 'i' || 'o' || 'u' || 'A' || 'E' || 'I' || 'O' || 'U') will always be true, and firstchar == (....) is the same as firstchar == true, which will probably give false.
You could write...
if (firstChar == 'a' || firstChar == 'e' || firstChar == 'i' || ...)
or...
if (strchr(firstChar, "aeiouAEIOU") != NULL)) ...
You can use an array too wherein you store all the vowels and then compare it. Something like shown below:
char vowels[10]={'a','e','i','o','u','A','E','I','O','U'};
int flag=0;
for(int i=0;i<10;i++)
{
if(vowels[i]==firstChar)
{
flag=1;
anN="n";
}
}
if(flag==1)
cout << "I am having a" << anN << " " << adj_3 << " time at camp." << endl;
else
cout << "not working" << endl;

C++: Having troubles with do while loop

do {
cout << "Enter the account type (C for current and S for savings): ";
cin >> account_type;
} while (account_type != 'S' || 'C');
I have account_type set as char,the problem is that everytime i run the program and i input S or C the loop keeps repeating.Can anyone help me know why its happening?
All non-zero values in c++ evaluate to true when used in a boolean operation. So account_type != 'S' || 'C' is the same as account_type != 'S' || true. Which means your loop never exits.
What you need to do is to preform both checks
do {
cout << "Enter the account type (C for current and S for savings): ";
cin >> account_type;
} while (account_type != 'S' && account_type != 'C');
Its because you cant say 'S' || 'C', you would think c++ would think that you mean if account_type is S or C however c++ looks at this in 2 separate sections: (account_type == 'S') || ('C'). ('C') will default to true therefore the loop loops forever.
What you need to write is:
do {
cout << "Enter the account type (C for current and S for savings): ";
cin >> account_type;
} while (account_type != 'S' && account_type != 'C');
You need to change the || to && because if account_type is S then it cant be C and the same vice versa therefore the loop never finishes.
Your while check is wrong. You have to write it like this:
while (account_type != 'S' || account_type != 'C')
You can't perform || checks, or any for that matter like that, you must always re-state the variable.

Pig Latin - strings

So I am supposed to convert English words to Pig Latin using stringConvertToPigLatin(string word) function. All the answers I could find on the internet were using char[], and I am not allowed to do so.
The program is supposed to begin with adding -way if the first letter is a vowel, and adding -ay if it's a consonant. The problem is that it is always adding "-way", even if my "word" has no vowel at all. What am I doing wrong? This is my function:
string ConvertToPigLatin(string word)
{
char first = word.at(0);
cout << first << endl;
if (first == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U')
{
word.append("-way");
}
else
{
word.append("-ay");
}
return word;
}
As noted in the comments your if statement is wrong. Each comparison needs to be done individually. From the comment.
if (first == 'a' || first == 'A' || first == 'e' || ...)
However, rather than using a long if statement you should consider stuffing all of the vowels into a string and using find. Something like the code below will be easier to read and follow.
#include <iostream>
#include <string>
std::string ConvertToPigLatin(std::string word)
{
static const std::string vowels("aAeEiIoOuU");
char first = word.at(0);
std::cout << first << std::endl;
if (vowels.find(first) != std::string::npos)
{
word.append("-way");
}
else
{
word.append("-ay");
}
return word;
}
int main()
{
std::cout << ConvertToPigLatin("pig") << '\n';
std::cout << ConvertToPigLatin("alone") << '\n';
}
This outputs
p
pig-ay
a
alone-way
I'll explain why your code isn't working:
if (first == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U')
Let's walk through that iff statement using the word "Pig"
First the program checks first == 'a'... first == 'P' so that is false.
Then the program checks to see if false || 'A' is true. Since 'A' is true, false || 'A' is also true.
Short circuit evaluation kicks in, and the code doesn't bother checking the rest of the statement, the if condition is true so -way is appended.
To do what you want, you need to compare first to each letter. I.E.,
if (first == 'a' || first == 'A' || ...
Don't worry too much, this is a pretty standard mistake.

how to only allow 3 values in a "if" and "while" statement to allow the loop to exit

I'm just stuck on some logic statements.
specifically the ones that are in the function char GetInteger() so how would I only allow 3 values to cause the loop to exit.
char GetInteger( /* out */ char& usrinput)
{
do
{
cin >> usrinput;
cin.ignore(200,'\n');
if (usrinput != 0 || usrinput != 1 || usrinput != 2)
{
cout << "Invalid Input." << userinput << " Try Again\n";
}
} while(usrinput != 0 || usrinput != 1 || usrinput != 2);
return userInput;
}
Two issues with this code:
First userinput has a type of char. So when you read from a stream you read a single character (after dropping white space). So when a user types 1<enter> you get the character '1' in the variable userinput. Note the character '1' is not the same as the number 1.
Thus your test should be:
userinput != '1';
Secondly your boolean logic is wrong. When first learning it is sometimes easier to state the problem as a list of values that you would like to be acceptable (not the unacceptable ones).
You want the conditions to be false if the userInput has one of your accepted values (any good value will fail the test and thus not invoke the bad code). The first step to this is to get a true if any of your values are valid.
// If any value is good then true.
userinput == '1' || userinput == '2' || userinput == '3'
To invert this just add a not to the expression.
if (! (userinput == '1' || userinput == '2' || userinput == '3') )
Note: in boolean logic
!(A || B) => (!A && !B)
So you could re-write the above as:
if (userinput != '1' && userinput != '2' && userinput != '3')
I think this was your main mistake you converted the == into != but did not convert the || into &&.
I would also suggest that you could simplify this (as you may get more valid result) byconverting this into a range based test.
if (userinput < '1' || userinput > '3')
{
// Test Failed.
}
Additionally. Since you have the test in two places. You should yank it outinto its own function. Then you can call the function to do the test.
bool isUserInputValid(char userInput)
{
return userInput >= '1' && userInput <= '3';
}
Now we can re-write your original function as:
char GetInteger( /* out */ char& usrinput)
{
do
{
cin >> usrinput;
cin.ignore(200,'\n');
if (!isUserInputValid(userinput))
{
cout << "Invalid Input." << userinput << " Try Again\n";
}
} while(!isUserInputValid(userinput));
return userInput;
}
First of all, you should use int instead of string as you are reading integer.
You can use while(1) instead of putting condition in while. Inside while loop, if your selection is 0 or 1 or 2, you can simply break the loop.

conditional statement in while loop

I must have missed something. I'm doing an exercise to learn c++ and it asks that if a user inputs either c,p,t or g character then carry on, otherwise re-request prompt, so I wrote this:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main(void){
cout << "Please enter one of the following choices:" << endl;
cout << "c) carnivore\t\t\tp) pianist\n";
cout << "t) tree\t\t\t\tg) game\n";
char ch;
do{
cout << "Please enter a c, p, t, or g: ";
cin >> ch;
cout << "\"" << ch << "\"" << endl;
}while(ch != 'c' || ch != 'p' || ch != 't' || ch != 'g');
cout << "End" << endl;
cin.clear();
cin.ignore();
cin.get();
return 0;
}
This does not work and all I get is the prompt re-requesting it even when pressing either of the correct characters.
However if I change this line:
while(ch != 'c' || ch != 'p' || ch != 't' || ch != 'g');
to
while(ch != 'c' && ch != 'p' && ch != 't' && ch != 'g');
why is that? My understanding is that the "OR" statement should work as one of the tests is correct.
why is that? My understanding is that the "OR" statement should work as one of the tests is correct.
Exactly. There is always one of the tests that passes. A character will either be not 'c', or not 'p'. It can't be both 'c' and 'p'. So the condition is always true, leading to an infinite loop.
The alternative condition with the conjunctions works because it is false as soon as ch is equal to one of the alternatives: one of the inequalities is false, and thus the whole condition is false.
My understanding is that the "OR" statement should work as one of the tests is correct.
Well, you could use ||, but the expression would have to be:
while(!(ch == 'c' || ch == 'p' || ch == 't' || ch == 'g'));
By applying the De Morgan's law, the above simplifies to:
while(ch != 'c' && ch != 'p' && ch != 't' && ch != 'g');