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

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...

Related

while loop running for every digit/character from input

Hey guys beginner in C++ and coding in general. I am currently making a tictactoe program. For the part of the program I am validating user input. Since it is a 3x3 table, I want to make sure their input is an integer and that they choose a number between 1~9.
To do this I wrote
//Validating user input
void move() {
std::cout << "It's Player" << player << "'s turn!\n";
while(!(std::cin >> position)){
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(board[position - 1] != " ") {
std::cout << "Already filled please choose another number between 1~9!\n";
std::cin >> position;
}
}
It works but for some reason when I put in an input like 10, it would print Please choose a number BETWEEN 1~9! twice (for each digit) and if I input in for example "apple" it would print Please choose a NUMBER between 1~9! four times (for each character). How do i make it just print out the statement once?
Thank you!
Let me try to explain to you the problem. It is a little bit subtle and not that easy to understand. Both other answers adress only the obvious part.
Then, let us first recap that:
The boolean condition in the while statement is loop invariant. Meaning, it will not be modified within the loop. Whatever it was before the loop, will be the same after the loop body has been executed. The condition will never change.
So, for the case where you enter a wrong number:
If the input number is correct (1..9) and the while statement starts to evaluate the boolean expression, it will be false in this case and the loop will not be entered.
If the number is out of your selected bounds (<1 or >9), then the boolean condition is true. The while loop starts, but the condition relevant variable will not be changed in the loop boody and hence, the boolean expression is always true. The loop will run forever.
Additionally, and now comes the answer to your first question, the following will happen:
The text "Please choose a number BETWEEN 1~9!\n" will be shown (first time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is an unformatted input function. It will actively read the next character from the input buffer, which is the end of line `'\n' character.
We enter again the while statement. The condition is still true (position was not modified in the loop body), and we enter the loop again.
The text "Please choose a number BETWEEN 1~9!\n" will be shown (second time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is a formatted input function. It will actively read the next character from the input buffer. But there is none. So it will wait until a key is pressed. For example "enter". After that, it would go back to number 5.
By the way. If you would now enter "abc" then you would see the text 4 times for a,b,c and enter.
So, please remember: ignore is an input function!
Next. It is important to understand, that if you enter an unexpected value, like "apple" instead of "3", the formatted input function >> can do no conversion and sets the failbit. It will also not extract further wrong characters from the input stream (std::cinis a buffered stream). The characters that could not be converted are still in the buffer and wil be read next time.
Please read here about formatted/unformatted input. And especially read about the extraction operatpr >> here..
There you can read the following:
If extraction fails (e.g. if a letter was entered where a digit is expected), zero is written to value and failbit is set.
OK, understood. Then, what is going on here, if you enter "abc". Basically, the same as above.
Enter abc
The boolean condition !(std::cin >> position)will be evaluated to true, because an 'a' was read and cannot be converted to a number.
The std::cin's failbit will be set. The variable positionwill be set to 0.
"Please choose a NUMBER between 1~9!\n" will be shown
The failbit will be reset
Ignore will extract exactly the one wrong character and discard it
std::cin >> position`` will be called again and extract the next wrong character 'b'. 3., 4., 5., 6. will be done again. Until the last charcter in the buffer, the newline '\n' will be extracted. Then you may enter the next number.
The fix for that problem is simple:
ignore has a parameter, where you can specify, how many characters shall be ignored. So, not only one, but all until the end of line.
You should write:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This will ignore all bad input.
And to fix your whole program, you could write at the top:
while (!(std::cin >> position) or (position < 1 ) or ( position > 9)) {
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
while(position < 1 || position > 9){
This while loop will continue running as long as position is less than 1 or greater than 9, that's what this says.
But there's nothing in the while loop itself that changes the value of position. For that simple reason, if position's value at this point is outside of the range of 1-9, this while loop will execute forever.
You always need to keep in mind The Golden Rule Of Computer Programming: your computer always does exactly what you tell it to do instead of what you want it to do. Here, you told your computer to execute this while loop as long as position is less than 1 or greater than 9, so this is what your computer will do until this is no longer the case.
You can change your code as this. With this you run your while loop ones for every input. Until you get the value as you like. If the value is as you wish, you get out of the loop with break
std::cout << "Please choose a NUMBER between 1~9!\n";
while(std::cin >> position){
std::cin.clear();
std::cin.ignore();
if(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
}else{
break;
}
}

While loop not acting as expected in Dev 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.

Problems with a program to get every number be greater or smaller than the numbers before and after itself

I want to write a program that get the numbers with this rule :
every number be greater or smaller than the numbers before and after itself. like : 3 1 4 2 6 0 8 3 5 16
Whenever this rule was violated, stop getting number.
int a, b, c;
bool flag = true;
cin >> a;
while (flag)
{
cin >> b;
cin >> c;
if ((b < a && b < c) || (b > a && b > c))
{
flag = true;
a = c;
}
else
{
break;
}
}
My code works for some inputs but for this inputs : 3 1 4 6
When i enter 6 the program must be stop, but it continue to input next number. What should i do to fix it?
The solution to this problems involves a lot of logical evaluations. So, we need many boolean expressions and if statements.
One key to the solution, is to keep track of 2 values:
The current read value
The preivously read, old value
We can always compare those values and then make descisions. Problem is that we do not have an "previous" value in the beginning. So, we need to do a special treatment and first read a value from the user, store this as prvious value, and then always read a current value in a loop.
At the end of the loop, we will assign the current value to the "previuosValue". Then in the next loop run, we always need to read only the current value from the user.
Ant those 2 values, we can compare in a while loop.
We compare the current value with the previous value, and, depending of the outcome, define a "direction" flag for further comparisons.
This we do after having read the 2nd number. After that the direction is always defined and will never change.
Example, if the current value is bigger than the previous value, then, in the next loop, the next value must be smaller. And vice versa.
Example:
First value: 2
2nd value: 6
The second value is bigger than the first value. So, for next values we expect
small --> big --> small --> big --> small --> big --> . . .
and so on. This will never change.
Same is valid vice versa.
First value: 9
2nd value: 1
The second value is smaller than the first value. So, for next values we expect
big --> small --> big --> small --> big --> small --> big --> . . .
The direction flag will always be inverted after having processed the "next" number.
We can then evaluate the stop condition in the next loop run. Does the comparision result to a value, to a direction, that we expect?
If not, or if the values are equal, then we stop the input.
Of course, we will not do this evaluation in the first loop, because then, we have always a valid pair and calculate the direction afterwards.
So, you see. We always need only 2 variables.
There are many possible implementations, as always. Please see the below as an example for a solution:
#include <iostream>
int main() {
// Read initial previous number (The first number)
if (int previousNumber{}; std::cin >> previousNumber) {
// Flag that indicates, if we should continue reading new numbers or not
bool continueToRead{ true };
// First number needs special treatment, there is no other number
bool firstCheck{ true };
// The "direction" of the comparison
bool nextNumberMustBeSmaller{false};
// Read numbers in a loop
while (continueToRead) {
// Read current (next) number
if (int currentNumber{}; std::cin >> currentNumber) {
// After heaving read the first value in the loop, we can detect the direction
if (firstCheck) {
// Get the "direction" of the comparison for the next numbers
// If the number is bigger than last number
if (currentNumber > previousNumber)
// Then next value muste be smaller
nextNumberMustBeSmaller = true;
// If this number is smaller
else if (currentNumber < previousNumber)
// then next number must be bigger
nextNumberMustBeSmaller = false;
else
continueToRead = false;
// First check has been done
firstCheck = false;
}
else {
// Find out the stop condition
if (
// Direction is smaller but number is bigger or
(nextNumberMustBeSmaller and (currentNumber > previousNumber)) ||
// Direction is bigger but number is smaller or
(not nextNumberMustBeSmaller and (currentNumber < previousNumber)) ||
// Or numbers are equal
(currentNumber == previousNumber)) {
// Then: Stop reading values
continueToRead = false;
}
nextNumberMustBeSmaller = not nextNumberMustBeSmaller;
}
// Remember the last value. So, for the next loop rund, the current value will become the previous one
previousNumber = currentNumber;
}
else {
std::cerr << "\n\nInvalid input\n\n";
continueToRead = false;
}
}
}
else std::cerr << "\n\nInvalid input\n\n";
return 0;
}
To be compiled with C++17 enabled.
Here are some observations if we take the task as given in your question, but I think you may have misunderstood the task in one way or another.
every number be greater or smaller than the numbers before and after itself
greater or smaller means not equal.
you can't check the next number. You don't even know if there is a next number, so you can only check against the previous number
The final condition then becomes "stop if current and last number are equal"
In code this could look like this:
int a, b;
cin >> a;
while (cin >> b && a != b)
{
a = b; // current number becomes the last number
}
Note that I removed flag, because it was never set to false. The break will be enough. And I moved the cin >> b into the loop condition to validate the input. Then it turned out that we can merge the if-block into the loop condition as well.

While loop fails to exit when a false condition is passed to it

Consider the following code to calculate the sum of numbers which are inputted by user during runtime :
#include <iostream>
using namespace std;
int main()
{
int sum = 0; //stores sum of numbers
int taken; //stores the number inputted by the user
while(cin>>taken)
{
sum += taken;
}
cout<<"The sum is : "<<sum;
return 0;
}
Now, I expect the loop to exit on its own and display the sum of numbers inputted by user as soon as the user enters 0 because while(0) evaluates to false as a result of which the loop terminates and hence the statement printing sum of numbers should be executed.
But this does not occur.
So, why does the while loop does not exit when the user enters 0 as an input ?
Please consider my below sample run of program :
3
2
1
0
5
(Then finally pressing ctrl-z for indicating end-of-file)
The sum is : 11
Here is my doubt in above sample run :
After I had entered 0, I should not be prompted for further inputs because according to me, while(0) should evaluate to false, and therefore the statement telling the sum of numbers entered till 0 should be printed on the screen, which does not happen.
The value of cin>>taken is not the value of taken. That's your misunderstanding.
You could write this code
while (cin >> taken && taken != 0)
{
...
}
which would do what you want.
As a side note the value of cin >> taken reflects the stream state. Normally in a boolean context a stream evaluates to true, but if some kind of error has occured then the stream evaluates to false. This is why while (cin >> taken) effectively means read until no more integers can be read.
So, why does the while loop does not exit when the user enters 0 as an input ?
while (cin >> taken) doesn't evaluate to while (taken) but to while (bool(cin)). After reading into the variable, cin will be casted to bool, which checks if the stream has errors.
From the docs:
Return value
true if the stream has no errors, false otherwise.

C++ reading a sequence of integers

gooday programers. I have to design a C++ program that reads a sequence of positive integer values that ends with zero and find the length of the longest increasing subsequence in the given sequence. For example, for the following
sequence of integer numbers:
1 2 3 4 5 2 3 4 1 2 5 6 8 9 1 2 3 0
the program should return 6
i have written my code which seems correct but for some reason is always returning zero, could someone please help me with this problem.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int x = 1; // note x is initialised as one so it can enter the while loop
int y = 0;
int n = 0;
while (x != 0) // users can enter a zero at end of input to say they have entered all their numbers
{
cout << "Enter sequence of numbers(0 to end): ";
cin >> x;
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
n = n + 1;
y = x;
}
else
{
n = 0;
}
}
cout << "longest sequence is: " << n << endl;
return 0;
}
In your program, you have made some assumptions, you need to validate them first.
That the subsequence always starts at 1
That the subsequence always increments by 1
If those are correct assumptions, then here are some tweaks
Move the cout outside of the loop
The canonical way in C++ of testing whether an input operation from a stream has worked, is simply test the stream in operation, i.e. if (cin >> x) {...}
Given the above, you can re-write your while loop to read in x and test that x != 0
If both above conditions hold, enter the loop
Now given the above assumptions, your first check is correct, however in the event the check fails, remember that the new subsequence starts at the current input number (value x), so there is no sense is setting n to 0.
Either way, y must always be current value of x.
If you make the above logic changes to your code, it should work.
In the last loop, your n=0 is execute before x != 0 is check, so it'll always return n = 0. This should work.
if(x == 0) {
break;
} else if (x > y ) {
...
} else {
...
}
You also need to reset your y variable when you come to the end of a sequence.
If you just want a list of increasing numbers, then your "if" condition is only testing that x is equal to one more than y. Change the condition to:
if (x > y) {
and you should have more luck.
You always return 0, because the last number that you read and process is 0 and, of course, never make x == (y + 1) comes true, so the last statement that its always executed before exiting the loop its n=0
Hope helps!
this is wrong logically:
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
Should be
if(x >= (y+1))
{
I think that there are more than one problem, the first and most important that you might have not understood the problem correctly. By the common definition of longest increasing subsequence, the result to that input would not be 6 but rather 8.
The problem is much more complex than the simple loop you are trying to implement and it is usually tackled with Dynamic Programming techniques.
On your particular code, you are trying to count in the if the length of the sequence for which each element is exactly the successor of the last read element. But if the next element is not in the sequence you reset the length to 0 (else { n = 0; }), which is what is giving your result. You should be keeping a max value that never gets reset back to 0, something like adding in the if block: max = std::max( max, n ); (or in pure C: max = (n > max? n : max );. Then the result will be that max value.