Chars in do while loop conditions - c++

I am having trouble with the last do while loop in my code. I have conditions set to stop the look when Y, N, y, or n are entered but even if those values are entered the loops continues to run and continue to ask for a Y or N. In debugging it seems that the Ascii value for the character is also stored in the variable? What do I need to change to have the do while loop end when there is an input of any of those 4 characters?
#include <string>
#include <iostream>
#include <iomanip>``
using namespace std;
int main()
{
int numberOfShapes, i, j, k, rectangleBase, rectangleHeight;
char star = '*';
char filled;
do
{
cout << "Enter the integer between 6 and 20 that you would like to be the base of the rectangle: ";
cin >> rectangleBase;
}while (rectangleBase < 6 || rectangleBase > 20);
rectangleHeight = rectangleBase / 2;
do
{
cout << "Enter the number of shapes you would like to draw(Greater than 0 and less than or equal to 10: ";
cin >> numberOfShapes;
} while (numberOfShapes <= 0 || numberOfShapes > 10);
do
{
cout << "Would you like a filled shape? [Y or N]: ";
cin >> filled;
} while (filled != 'Y' || filled != 'N' || filled != 'y' || filled != 'n');

Your loop end condition is wrong:
while (filled != 'Y' || filled != 'N' || filled != 'y' || filled != 'n');
consider that the value is 'y' then your condition will be:
(true || true || false || true)
which evaluates to true.
Change to:
while (filled != 'Y' && filled != 'N' && filled != 'y' && filled != 'n');
Then it will be:
-> 'y' (true && true && false && true) -> false
-> 'l' (true && true && true && true) -> true

You need to use && not ||:
} while (filled != 'Y' && filled != 'N' && filled != 'y' && filled != 'n');

If you write it as you say it, perhaps it would be more clear and will help to avoid these mistakes:
do
{
cout << "Would you like a filled shape? [Y or N]: ";
cin >> filled;
if (filled == 'Y' || filled == 'N' || filled == 'y' || filled == 'n')
break;
}
while (true);

Related

Why is my Else If 'vehicleHeight' code being ignored? [duplicate]

This question already has answers here:
Can you use 2 or more OR conditions in an if statement? [duplicate]
(9 answers)
Closed 2 years ago.
cout << "Are you driving a vehicle onto the ferry? (y/n) ";
cin >> vehicle;
if (vehicle == 'y' || vehicle == 'Y') {
cout << "What is the length of the vehicle in feet? ";
cin >> vehicleLength;
if (vehicleLength > 20) {
extraLengthCharge = (vehicleLength - 20) * extraLengthPrice; }
cout << "Is the vehicle over 7 feet high? (y/n) ";
cin >> vehicleHeight;
if (vehicleHeight == 'y' || 'Y') {
vehiclePrice = 69.00, fuelSurcharge = 10.40;
} else if (vehicleHeight == 'n' || 'N') {
vehiclePrice = 43.00, fuelSurcharge = 4.15;
}
else if (vehicle == 'n' || vehicle == 'N') {
vehiclePrice = 0, fuelSurcharge = 0; }
}
My code will give me the correct 'fare' if the response is yes, but if I type in no it will still assign the 'yes' value. I assume it has something to do with my else if statement format for vehicleHeight.
Thanks and sorry for the novice question.
The conditions vehicleHeight == 'y' || 'Y' and vehicleHeight == 'n' || 'N' will be always true because 'Y' and 'N' will be always true and logical OR is used with them.
You should use conditions vehicleHeight == 'y' || vehicleHeight == 'Y' and vehicleHeight == 'n' || vehicleHeight == 'N' like what you used in other if statements instead.

How can I better check whether two char variables are in some set of values?

Recently, our professor has requested that we use two char variables (day) to receive the input from the user.
The code below works fine as a check to ensure that either Mo, Tu, We, Th, Fr, Sa, Su are the only two characters which are entered together as a pair. If anything else is received as input, it'll loop and ask the user for valid input.
The input should be case-insensitive, meaning that, for example, "mO" and "tu" are acceptable. It seems like there is a lot of repetition that is happening. Is there a way to clean this up?
cout << "Please enter the day of the week did you made the long distance call (Mo Tu We Th Fr Sa Su): ";
cin >> dayOne >> dayTwo;
while ((dayOne != 'M' && dayOne != 'm' || dayTwo != 'O' && dayTwo != 'o') &&
(dayOne != 'T' && dayOne != 't' || dayTwo != 'U' && dayTwo != 'u') &&
(dayOne != 'W' && dayOne != 'w' || dayTwo != 'e' && dayTwo != 'E') &&
(dayOne != 'T' && dayOne != 't' || dayOne != 'H' && dayTwo != 'h') &&
(dayOne != 'F' && dayOne != 'f' || dayTwo != 'R' && dayTwo != 'r') &&
(dayOne != 'S' && dayOne != 's' || dayTwo != 'A' && dayTwo != 'a') &&
(dayOne != 'S' && dayOne != 's' || dayTwo != 'U' && dayTwo != 'u'))
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << endl << "You have entered an invalid day. Please re-enter a day in the correct format (Mo Tu We Th Fr Sa Su): ";
cin >> dayOne >> dayTwo;
}
You could write a fold-expression that compares 2 characters to a string:
template<typename ...Days>
bool any_of(char a, char b, Days ...days)
{
return (... || (a == days[0] && b == days[1]));
}
and then use it like this:
while (! any_of(std::tolower(dayOne), std::tolower(dayTwo), "mo", "tu", "we", "th", "fr", "sa", "su"))
// keep asking for input
Here's a demo.
This should satisfy the requirement of using 2 char inputs.
You typically use tolower or toupper to convert your char variable to the correct case first. I like using tolower - it looks marginally better.
dayOne = tolower(dayOne);
dayTwo = tolower(dayTwo);
while (
(dayOne != 'm' || dayTwo != 'o') &&
(dayOne != 't' || dayTwo != 'u') &&
(dayOne != 'w' || dayTwo != 'e') &&
(dayOne != 't' || dayTwo != 'h') &&
(dayOne != 'f' || dayTwo != 'r') &&
(dayOne != 's' || dayTwo != 'a') &&
(dayOne != 's' || dayTwo != 'u'))
{
...
}
You can further change it by using memcmp to compare both characters at once, but I am not sure it would simplify the code.
Another approach that might be worth mention is to organize your data, so that you can use std functions against it (std::find)
// Example program
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
int main()
{
const std::vector<std::string> days = {
"mo", "tu", "we", "th", "fr", "sa", "su"
};
bool found = false;
while (found == false) {
char dayOne, dayTwo;
std::cout << "Please enter the first letter of the day" << std::endl;
std::cin >> dayOne;
std::cout << "Please enter the second letter of the day" << std::endl;
std::cin >> dayTwo;
std::string fullDay;
fullDay += std::tolower(dayOne);
fullDay += std::tolower(dayTwo);
found = std::find(days.begin(), days.end(), fullDay) != days.end();
std::cout << (found ? "correct day " : "invalid day, please try again ")
<< fullDay
<< std::endl;
}
}
run it here
How about
switch (256 * tolower(dayOne) + tolower(dayTwo))
{
case 256 * 'm' + 'o':
// Monday
case 256 * 't' + 'u':
// Tuesday
}
and so on?
Don't know if you're using/allowed regexes, but I'd solve it like this:
bool isDayOfTheWeek(char a, char b)
{
std::string day({a, b});
std::regex pattern("Mo|Tu|We|Th|Fr|Sa|Su", std::regex_constants::icase);
return std::regex_search(day, pattern);
}
Then simply:
cout << "Please enter the day of the week did you made the long distance call (Mo Tu We Th Fr Sa Su): ";
cin >> dayOne >> dayTwo;
while (!isDayOfTheWeek(dayOne, dayTwo))
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << endl << "You have entered an invalid day. Please re-enter a day in the correct format (Mo Tu We Th Fr Sa Su): ";
cin >> dayOne >> dayTwo;
}
I would first convert inputs to lowercase, which cuts on the amount of possible combinations. Then I would solve it with a single if-statement per day:
// returns 0-6 for valid days, -1 for invalid ones
int dayOfWeek(char a, char b) {
a = tolower(a); // requires #include <cctype>
b = tolower(b);
if (a == 'm' && b == 'o') return 0;
// 5 more here
if (a == 's' && b == 'u') return 6;
return -1; // date was invalid
}
And then I would use it as #PaulEvans suggested:
cout << "Please enter the day of the week did you made the long distance call (Mo Tu We Th Fr Sa Su): ";
cin >> dayOne >> dayTwo;
int day = -1;
while ((day = dayOfWeek(dayOne, dayTwo)) == -1)
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << endl << "You have entered an invalid day. Please re-enter a day in the correct format (Mo Tu We Th Fr Sa Su): ";
cin >> dayOne >> dayTwo;
}
// day is 0 for monday, ... 6 for sunday

Two conditions for while loop. What's my error?

I have a questoin. Everything here seems to work fine, besides the following line:
} while (OneMoreTime != 'y' || OneMoreTime != 'n');
Full Code;
#include <iostream>
using namespace std;
int main()
{
int ARRAY_LENGTH = 5;
int MyArray[ARRAY_LENGTH] = {1, 2, 3, 4, 5};
cout << "Values in the array: " << ARRAY_LENGTH << endl;
for (char OneMoreTime = '\0'; OneMoreTime = 'n'; )
{
int WhichNumber = ARRAY_LENGTH;
do
{
cout << "What numbers from the array do you want to see, counting backwards? ";
cin >> WhichNumber;
} while ((WhichNumber > ARRAY_LENGTH) || (WhichNumber <= 0));
//calculating the correct position in the array (from start)
int Number2Print = ARRAY_LENGTH - WhichNumber;
//printing
cout << "The number is: " << MyArray[Number2Print] << endl;
//continue?
do
{
cout << "One more time? (y/n) ";
cin >> OneMoreTime;
} while (OneMoreTime != 'y' || OneMoreTime != 'n');
}
return 0;
}
What I get is it constantly asks "One more time? (y/n)" after successfully printing the first time. If I just use one condition it will work (but that wouldn't be enough).
That condition will always be true as OneMoreTime cannot be both equal to n and y. What you probably mean is to use && (and)
while (OneMoreTime != 'y' && OneMoreTime != 'n');
this statment
while (OneMoreTime != 'y' || OneMoreTime != 'n');
is a false statment, what you will get is no matter what you put in is gonna return true and
continue the loop.
A || B, if you put 'y' ,B is true, if you put 'n', A is true, so the 'or' operation will return true if either one of the condition is true.
if you using
while (OneMoreTime != 'y' && OneMoreTime != 'n');
it will still put next value in the array if you input 'n'

Need to add a loop to exit or repeat in C++

I want to make a code that asks user for input either to quit or repeat. I am not getting the desired output.
int main()
{
char yes,yn;
do
{
cout << "Hello world!" << endl;
while(yn != 'y' || yn != 'Y' || yn != 'n' || yn != 'N')
{
cout<<"enter (Y/N): ";
cin>>yes;
yn = yes;
}
}while(yn == 'y' || yn == 'Y');
}
Program asks for user input, when I input "Y,y,N or n", it should get out of the loop and then decide whether exit or repeat. But it isn't getting out of the loop and asking me for input again and again. I am not getting what is stopping to get out of the loop.
I didn't test, but your issue seems to be here:
while(yn != 'y' || yn != 'Y' || yn != 'n' || yn != 'N')
This condition is always true (yet shouldn't). It should be :
while(yn != 'y' && yn != 'Y' && yn != 'n' && yn != 'N')
or
while(!(yn == 'y' || yn == 'Y' || yn == 'n' || yn == 'N'))
Moreover, yn isn't initiliazed, you may want to do a do { ... } while(...); again.
while(yn != 'y' || yn != 'Y' || yn != 'n' || yn != 'N')
Is always true. It should be
while(yn != 'y' && yn != 'Y' && yn != 'n' && yn != 'N')
Firstly, this expression:
(yn != 'y' || yn != 'Y' || yn != 'n' || yn != 'N')
is always true, as yn is always not equal to one of those things.
(yn != 'y' && yn != 'Y' && yn != 'n' && yn != 'N')
is probably what you meant.
Secondly, your life would be easier if you did
yes = toupper (yes);
(i.e. put it in upper case), then you'd only have to look for one thing.
Thirdly, and most seriously, your inner while examines the value of yes before it's been initialized. Either use a do while() construct, or intialize the value to something before the loop.
Fourthly, it's not clear what you are trying do to here. Do you really need two loops at all?
I think do while loop is all you need for the execution...
int main()
{
char yes,yn;
do
{
cout << "Hello world!" << endl;
cout<<"enter (Y/N): ";
cin>>yes;
yn = yes;
if(yn=='N'||yn=='n')
{
break;
}
}while(true);
}
your loop does not exit becuse your while loop is always true..
while(yn != 'y' || yn != 'Y' || yn != 'n' || yn != 'N')
Now I have added a break statement in your loop on a if condition and changed the do while condition
in this case it will run the loop on any condition and will exit the loop only when the user enter n or N
You did not initialize variable yn. So this statement
while(yn != 'y' || yn != 'Y' || yn != 'n' || yn != 'N')
has no sense and in fact it is unnecessary.
Try the following code
#include <iostream>
int main()
{
char yes_no;
do
{
std::cout << "\nHello world!" << std::endl;
std::cout<< "Do you want to repeat? (enter Y/N): ";
std::cin >> yes_no;
} while ( yes_no == 'y' || yes_no == 'Y' );
}
Thank you all for help. I have got what i wanted from all of you. Here is the final code running successfully. I have improved my code using suggestion from everyone of yours opinion.
int main()
{
char yes,yn;
do
{
.......... (main content of program, do things here.)
do
{
cout<<"Do again? (Y/N):";
cin>>yes;
yn = toupper(yes);
if(yn!='N' && yn != 'Y')
{
cout<<"Invalid selection"<<endl;
}
if(yn=='N' || yn == 'Y')
{
break;
}
}
while(true);
}
while(yn == 'Y');
}

Evaluating if statement with single char C++

I am trying to evaluate a single char:
bool repeat = true;
while (repeat)
//code
char x;
cout << "Would you like to tansfer another file? Y/N ";
cin >> x;
if (x == 'y' || x == 'Y')
repeat = true;
if (x == 'n' || x == 'N')
repeat = false;
else
throw "Input error";
I keep getting Input Error as my console output. Any ideas why? I can't get the while loop to repeat.
You are missing an else here:
if (x == 'n' || x == 'N')
should be:
else if (x == 'n' || x == 'N')
and you need to add braces after the while to encompass the input and if statements.
You forget braces {} after while:
while (repeat)
{
char x;
cout << "Would you like to tansfer another file? Y/N ";
cin >> x;
if (x == 'y' || x == 'Y')
repeat = true;
else
if (x == 'n' || x == 'N')
repeat = false;
else
throw "Input error";
}