While loop not acting as expected in Dev C++ - c++

I'm trying to get a while loop to accept the condition of looping until the values 1 or 2 are entered using the code below
while((choice != 1) || (choice != 2))
{
cout << "\nEnter 1 to read a file, Enter 2 to enter your own values: ";
cin >> choice;
}
As best as I can remember this has worked for me previously so I'm not sure why it's not working now and I think it may be something to do with how I installed Dev C++ as per the screenshot linked here. I vaguely recall having to fix this issue on my old PC but can't remember how to fix it exactly. Any help with either explaining where I've gone wrong in the code or how to fix the Dev C++ error would be greatly appreciated.

The issue with your loop is that this condition:
(choice != 1) || (choice != 2)
is guaranteed to be true for every value. If choice is 1, the second clause of the disjunction will be true; if it's 2, the first clause will be true; if it's any other number both will be true. If any of the clauses are true in a disjunction, the entire condition is true. This means your condition will always be true.
What you need is a conjunction of the clauses:
(choice != 1) && (choice != 2)
// ^^
With this the loop condition will only be true when both clauses are true, and this requires choice to be something other than 1 or 2.

If choice is equal to 1, one of your conditions is false but the other is still true. It is similar when choice is 2. Change your "OR" statement to an "AND" and it should only loop when the user enters something other than one or two.

Related

Why does this while loop keep looping even when its false? In C++

This is the code in question:
int integer;
while (integer != 0 || integer != 1) {
cout << "Choose an integer: \n0\n1\n";
cin >> integer;
}
When I type 1 it continues looping even though the statement is false.
I have had this problem before or similar but it got fixed in a weird way that seems to not be working right now.
The other code that was having problems was this one:
while(chosen != 1 || chosen != 2 || chosen != 3)
{
cin >> chosen;
}
I got it fixed by doing this:
while(chosen < 1 || chosen > 3)
Does annyone know whats happening here? Ty in advance!
let me put you out of your misery
while(chosen != 1 && chosen != 2 && chosen != 3)
{
cin >> chosen;
}
This is a common issue, people translate the human idea in their heads into code: "if its not 1 or 2 or 3 then do xx". But that doesnt work.
(chosen != 1 || chosen != 2 || chosen != 3)
will always be true.
If chosen is say 0 then chosen != 1 is true. So the overall condition is true.
If chosen is 1 (which should be the end of your loop) then chosen !=1 is false, BUT chosen != 2 is true so the overall condition is still true (its true if one of the clauses is true, this is what 'or' / '||' means).
In fact there is no value for chosen which will cause the overall condition to be false. Chosen is always going to not equal one of 1 or 2 or 3.
Your problem came from the looseness of human thought, in conversation we would get what you mean, but not computers. What you wanted was "if its not 1 and its not 2 and its not 3 do xx". Ie
while(chosen != 1 && chosen != 2 && chosen != 3)

Using Variables inside an if, which are used in the if-statement

I edited this post to clarify my problem. Try to run the following program. It always stucks at the cin. you can cin as much number as u want but it wont continue. Thanks for all the answers
int main(){
int eingabe;
int zweieuro = 2;
cin >> eingabe;
if(eingabe < 2)
{
eingabe = eingabe - zweieuro;
cout << eingabe;
}
}
```
The problem is here:
while(input != 0)
{
if(input > two_euro)
{
input = input - two_euro;
If your input is at 2, then the while loop will keep going round, but the if well never be entered. You specifically check if the input is greater than 2, so you never completely reduce the input to 0.
Let's walk through an example:
input is 4
while (input != 0) => true, enter the loop
if (input > 2) => true, enter the reduction step
input = input-2 => input is 2
while (input != 0) => true, continue the loop
if (input > 2) => false, skip the reduction step
while (input != 0) => true, continue the loop
if (input > 2) => false, skip the reduction step
... continue forever
Supposing you fix the above problem by changing > to >=. What will happen if your input is not an even number? Not a whole number? Maybe your while condition shouldn't check for exactly 0, but instead check if the input is greater than 0?
You would need to change your reduction step to always take place while the input is greater than 0 as well, or you would get stuck in an infinite loop with your input at 1 (or any value between 0 and 2).
With floating point computation, some rounding can prevent the result from being
exact.
For example, if you accumulate ten times 0.1 and then test if this result
is exactly 1.0, you will be surprised to see that it is not!
(on my computer I obtain an error of 1.1102230246251565e-16)
So, comparing the consequence of some alteration of input to exactly 0
will probably be incorrect.
Maybe should you consider an error margin.
you need to change your while condition and your if also.
Do some test/debug... check for example input equal to 2, 5...

The right way to use != in a While loop ?...Or ..?

I'm just a beginner in C++ and while making a code to create the TicTacToe game I got stuck at the while statement that will push the game to keep going until winning conditions are fulfilled :
while(((table[0][0]!='X')&&(table[1][1]!='X')&&(table[2][2]!='X')))
This is just the diagonal condition (Putting all the conditions will give you eyesore...).
THE PROBLEM IS that this is not working even if the conditions are fulfilled (I'm sure because I use a cout at the end), however when I change && with || the condition work !
I thought maybe because of the != that affect everything ??
EDIT: Minimal Example (I removed the floating point !) :
#include <iostream>
using namespace std;
int main()
{
int tailleX(3),tailleY(3); //The Size of the table.
char table[tailleX][tailleY]; //TictacToe table.
table[0][0]='N';
table[0][1]='N';
table[0][2]='N';
table[1][0]='N';
table[1][1]='N'; //Randomly filling the array to avoid an error
table[1][2]='N';
table[2][0]='N';
table[2][1]='N';
table[2][2]='N';
int coorP1; //The Coordinate of the square (Exp: x=1 , y=2 will be 1.2)
while(((table[0][0]!='X')&&(table[1][1]!='X')&&(table[2][2]!='X'))) //For the minimal example I made just the diagonal condition
{
cout<<"PLAYER1: Enter the coordination to score: (Exemple: 1, 2, 3..) "<<endl;
cin>>coorP1;
switch(coorP1) //Filling the square depending on the coordinates.//I used If because Switch does not work.
{
case 1:
table[0][0]='X';
break;
case 2:
table[0][1]='X';
break;
case 3:
table[0][2]='X';
break;
case 4:
table[1][0]='X';
break;
case 5:
table[1][1]='X';
break;
case 6:
table[1][2]='X';
break;
case 7:
table[2][0]='X';
break;
case 8:
table[2][1]='X';
break;
case 9:
table[2][2]='X';
break;
}
}
cout<<"You won"<<endl;
return 0;
}
The problem here is your test condition. Your loop repeats if you enter 2, 3, 4, 6, 7, or 8. As soon as you enter 1, 5, or 9, the loop exits. If you enter 1, 5, or 9, then one of the diagonal values is set to 'X'. while loops while the condition is true. As soon as the condition evaluates to false, it exits. When you enter 1, 5, or 9, you cause the condition to be false.
Imagine, for a second, that table[0][0] is 'X', table[1][1] is 'N', and table[2][2] is 'N'. In other words, the board looks like this:
X | N | N
--+---+---
N | N | N
--+---+---
N | N | N
Then your test condition is:
table[0][0] != 'X' && table[1][1] != 'X' && table[2][2] != 'X'
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
false true true
If you logically AND these together (as you are with &&), this evaluates to false (which makes sense: false AND true should evaluate to false; only true AND true should evaluate to true).
So what should your test condition be?
What you really want is to do is loop only if the user doesn't have 3 in a row. In other words, check if the user has 3 in a row; if he does not have 3 in a row, then proceed.
We can construct that logical statement as:
// This checks if the user has 3 in a row
table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X'
// We want to check if the user does NOT have 3 in a row,
// so we can negate the above with !
!(table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X')
// With De Morgan's laws, we can simplify this to:
table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
Thus, your looping condition should be one of (they're both equivalent; pick whichever one makes more sense to you):
!(table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X')
This checks if the user does not have 3 in a row
table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
This checks if the user does not have an 'X' any one of the needed positions. It logically follows that if the user is missing an 'X' in one of these positions, the user cannot have 3 in a row. This is just an application of De Morgan's laws to the previous logical statement.
A critical part of learning to program is learning to avoid doing similar things over and over in your source code. You need to abstract the similar behaviors so they can share one chunk of code. So the computer does all that work, but when writing the source code, you don't do all that work.
Your attempt to build up a giant boolean expression of the game state is an extreme example of how not to program. It is a common beginner mistake (and far from the only example of that beginner mistake in your code). Fixing that giant boolean expression is possible, but it would be terribly counter productive along your path of learning to program. Instead you should take that as an example to learn how to combine and abstract work:
First understand the game concepts: A game state is one of wonX, wonY, draw, inProgress. You could define an enum for those possibilities. Each of the eight lines through the board has the same four possible states, where the game state is wonX or wonY if any line has that state, and the game state is inProgress is no line is wonX or wonY and some line is inProgress.
Because draw combines from individual rline up to board level in the opposite way that wonX or wonY does, the combination operation would be tricky at a high level and easier in the code that also determines line state.
So I suggest writing a function that takes the three values of one line as input and also takes game state accumulator as input, and returns an updated game state. In each round, you would start computing the game state as draw, then call the function for each of 8 lines to update it. If the line is a win for X or Y, then the state would unconditionally change to that. If the line is inProgress, the state would change to that only if the state was draw. If the line is draw, that doesn't change the state (one line in a draw state says nothing about the game state).
Good design would further abstract and combine several more aspects of your code, but the one that is the big problem from your failure to abstract and combine, is as I indicated the step that looks at one line and computes its impact on the state of the whole board.
In general you will find your most powerful tool for abstracting and combining work is to move that chunk of the work into a function (as I described above). Trying to do too much not split out into seperate functions is a major beginner mistake.

Why do we have to assign a value while using while loop, in case of asking user to enter more values?

I saw a C++ program in my C.S. book whose source code is:-
#include <iostream>
using namespace std;
 
int main()
{
char choice=‘y’; //why is this required?
int marks, classx, test;
 
while (choice=='y'||choice==‘Y') {
cout<<"Enter marks:";
cin>>marks;
cout<<"\nEnter class:";
cin>>classx;
cout<<"\nWant to Enter more? (y/n)";
cin>>choice; //Can't understand why **choice** is assigned **'y'** before while loop?
}
return 0;
}
In this code, I can't understand why have we assigned the character 'y' before while loop. I've omitted the value of choice which assigns 'y' in the line 5, but after that it doesn't runs, even without showing any error!
Please explain me why have we assigned 'y' to character choice before while loop.
Please note that I am a newbie to the programming world, and started
off with C++
Because the very beginning condition for the while loop is if choice=='y', if at the very beginning choice doesn't equal 'y' then it will never even enter the loop to begin with.
If you really don't want to initialize choice first, then change your while loop to a do~while instead:
do
{
cout<<"Enter marks:";
cin>>marks;
cout<<"\nEnter class:";
cin>>classx;
cout<<"\nWant to Enter more? (y/n)";
cin>>choice; //Can't understand why **choice** is assigned **'y'** before while loop?
} while (choice=='y'||choice==‘Y');
In this case, the do starts a loop with no condition, your first loop will always happen. At the very end of the loop, it only loops again if the while condition is true.
It's required here only because of how the while loop is constructed.
Note the loop conditionals:
while (choice=='y'||choice==‘Y')
If choice is not set to y or Y before the while is executed the first time, the condition will never be satisfied, and the loop will never begin.
Try it yourself under a debugger and you will see.
The value is assigned in the beginning because only then it will enter the loop or else the condition
while (choice=='y'||choice==‘Y')
fails. So the choice variable is initialised
choice = 'y' make sure that the code in the while loop is done at least 1 time. Else, the loop may be executed once or may not be executed at all, depending on platform/compiler.
Also, using a debugger will help you answer some questions more rapidly.
You asked
But why have we only used 'y' (i.e., the condition value of while
looop) as the initial value for "choice"?
The while loop while (choice=='y'||choice==‘Y') specifies 2 conditions with the || (logical OR operator) between them. That means, that whichever condition is true, the while loop executes.
We needed to set choice to an initial value, to be sure that the loop executes the first time. That initial value could have been either 'Y' or 'y', any of them would have allowed the while loop to run the first time.
Otherwise choice will have a garbage value that may not equals to either 'y' or 'Y' and your loop condition at first time becomes false. If you initialized with y then first time loop will execute for sure (initialized choice with 'y' or 'Y' means code behavior is well defined = always executes for first time).
If you wants to user to enter choice for first time then add extra cin before loop.
// here you may leave choice uninitialized, know behavior is defined
cout<< "\nWant to Enter more? (y/n)";
cin>> choice;
while (choice == 'y' || choice == 'Y'){
cout<< "Enter marks:";
cin>> marks;
cout<< "\nEnter class:";
cin>> classx;
cout<< "\nWant to Enter more? (y/n)";
cin>> choice;
}
Remember: Garbage value derives undefined behavior.
Additionally, its always do practice to initialize a variable in your code with default value.
If you don't assign it a value, it will have an indeterminate value, and the while(choice == 'y' || choice == 'Y') will see a value that is not y or Y, and thus not enter the loop the first time, not allowing the user to enter anything.
By the way, you're mixing backquote (`) and single quote (') in your code, the compiler will not accept that. Use only single quote.
In this program the the While loop fist check the value of 'choice' then the code get executed so it should be initialize first by 'y' or 'Y' to execute the code first time

C++ Do - While loop until a string meets certain criteria

I'm asking the user for an input, but I want the question to stay on screen until the input meets one of the allowed inputs. Here's my code
string input = "";
string departure = "";
cout << "Please enter an airport code: ";
do
{
getline(cin,input);
stringstream(input) >> departure;
} while(departure.compare("MAN") != 0 || departure.compare("EMA") != 0 || departure.compare("LHR") != 0 );
}
I want it to loop until the user enters MAN or EMA or LHR; also if they are lowercase I would like for it to be accepted aswell.
Every time I run this, even if I enter a correct input, it just keeps taking words in and doesn't do anything else.
The condition
departure.compare("MAN") != 0 || departure.compare("EMA") != 0 || departure.compare("LHR") != 0
is always true, regardless of what departure is.
compare returns 0 on equality. So what you're basically telling the compiler is
Run the loop while departure is different than "MAN" OR different than "EMA" OR different than "LHR".
You need && instead of || in your condition.
This condition always returns true since it can't not be all 3 at once.
The && will return false as soon as the input is one of the 3 accepted.
Consider using boost::to_upper to convert the input into upper case before you perform the comparison in the while(...) statment. This will resolve the lowercase/uppercase issue.
http://www.boost.org/doc/libs/1_41_0/doc/html/boost/algorithm/to_upper.html
Also, when dealing with C++ strings, I recommend you simply do
departure == "MAN" || departure == "EMA" || departure == "LHR"
You don't need to do string.compare in C++, unlike some other languages (for example Java), as the == operator is overloaded to compare the /content/ of the string, rather than the string object itself.
Also somebody else beat me to it about the compare method returning 0 when equal.
First Your conditional for the while loop is incorrect. Right now it reads, while departure is not 'MAN' or is not "EMA" or is not "LHR", continue looping. Because departure cannot be all three of them simultaneously, the loop never ends. I would suggest replacing your OR's (||) with AND's (&&)
As well, each execution of the loop you need to clear the value in departure, otherwise the previously entered lines persist and your comparison will fail even when a correct airport code is entered.
our main problem is that the string is being compared incorrectly. Let's say we type in "MAN".
The departure.comare("MAN") != 0 will be true if the string is not "MAN". Fine, we typed in "MAN", so it's false. Now we OR that with departure.compare("EMA") != 0 - which is true, because "MAN" is not equal to "EMA". So you need to combhine your condition with &&, not ||.
To fix for "owercase", there are two choices. Either convert the input string to uppercase, or compare with all different combinations of lower and upper case (Man, MaN, mAn, etc) - the latter gets very tedious very quickly.
Have a look at this one for some options of comparing strings in a case-insensitive way:
Case insensitive string comparison C++