Matching nulls(0) in int [c++] - c++

I have a problem with checking on 0, i trying to get numbers from file(and i get it) but if is 0 then said me >
0 maybe its not found!(0 | 0)
0 maybe its not found!(1 | 1)
0 maybe its not found!(2 | 2)
0 maybe its not found!(3 | 3)
0 maybe its not found!(4 | 4)
if i want 1 and i gets the correct line from line:
0 maybe its not found!(0 | 0)
[Line0]: 1 1 1 200 150 6 1 10000000 1
[Line1]: 1 1 13 14
0 maybe its not found!(2 | 2)
0 maybe its not found!(3 | 3)
0 maybe its not found!(4 | 4)
Check func is :
int myClass = 0; //'\0'
for(int i=0; i < Show.line0 && Show.line1; i++)
{
if( Show.Get[i].m_Class0 && Show.Get[i].m_Class1 == myClass )
{
........
}
else
{
cout << myClass; cout << " maybe its not found!";
cout << "(";
cout << Show.Get[i].m_Class0;
cout << " | ";
cout << Show.Get[i].m_Class1;
cout << ")";
cout << endl;
}
m_class0/1 are int and the value its getted from the loaded file.
in other value on myClass bigger then 0 i gets the same line lines from file begining with wanted number, but doesnt works with 0.

Your error lies in the following line:
if( Show.Get[i].m_Class0 && Show.Get[i].m_Class1 == myClass )
Here, the compiler evaluates:
Show.Get[i].m_class0
If this is true, the compiler goes on to evaluate:
Show.Get[i].m_Class1 == myClass
If this is true (the other one must be true at this point, unless && was overloaded), then the if block executes.
The problem lies within the first condition. It will be true when Show.Get[i].m_Class0 does not equal 0.
What you really want is the opposite in this case (since myClass is 0):
if( Show.Get[i].m_Class0 == myClass && Show.Get[i].m_Class1 == myClass )
Now I mentioned a couple of things in there. The first is that the second part will only be evaluated if the first is true. This is called short circuit evaluation, and is used to save time. However, if one were to overload operator&&, the short circuit no longer kicks in. That is the second, and this is why it's generally a bad idea to do so, as it can give unexpected side effects from the second condition.
For example:
if (false && ++x)
would leave x if the && is native, but increment x if it is an overloaded version.

if( Show.Get[i].m_Class0 && Show.Get[i].m_Class1 == myClass )
As #chris commented, this is not doing what you seem to think.
if (A && B == 0) does not mean "if A and B are both equal to zero"
It means "if A is true, and B is equal to zero" and that fails when A is zero, because zero is false
You want if (A == 0 && B == 0) which means "if A is equal to zero and B is equal to zero"

Related

Why is 'if(1 == 1 == 1 == 1 == 1);' TRUE but 'if(-1 == -1 == -1 == -1 == -1);' FALSE? [duplicate]

This question already has answers here:
Why comparing three variables together with == evaluates to false?
(2 answers)
Closed 2 years ago.
if (1 == 1 == 1 == 1 == 1)
std::cout << "right";
The code above shows 'right'.
if (-1 == -1)
std::cout << "right";
The code above also shows 'right'.
if (-1 == -1 == -1)
std::cout << "right";
The code above shows nothing. (It's because the if statement isn't TRUE I guess?)
I would like to know why this weird thing happens.
Because -1 is equal to -1 and this statement is always TRUE no matter how many times I repeat (as far as I know).
The conditions are evaluated from left to right, hence the following conditional statement
if (-1 == -1 == -1)
std::cout << "right";
is equivalent to
if (true == -1)//since -1 === -1
std::cout << "right";
equivalent to
if (1 == -1) // true is casted to 1
std::cout << "right";
equivalent to
if (false)
std::cout << "right";
So it's normal the statement std::cout << "right"; doesn't execute and you get nothing.
The conditions are done in their order so:
-1 == -1 == -1 == -1 == -1
becomes
true == -1 == -1 == -1 (because the first -1==-1 gives true)
becomes
false == -1 == -1 (because true==-1 gives false)
becomes
false ==-1
becomes
false
The same thing happen with 1==1==1==1==1 because 1==true (but not 1===true).
Let's look at your three examples.
1 == 1 == 1 == 1 == 1 would be equivalent to true == 1 == 1 == 1, since true == 1 is true (since true gets treated as a 1), you'd then get true == 1 == 1 which is then true == 1 and finally just true.
In your second example, -1 == -1, this is simply just true, since obviously -1 equals itself.
Now, for your last example, you have -1 == -1 == -1, which becomes true == -1. true is not equal to -1 since 1 is not equal to -1, so this is therefore false. As a result, the "right" does not get printed.
In C++ the evaluation order of the equality operator == is from left to right:
(-1 == -1) == -1
is evaluated to
1 == -1
which returns false
Your code hits on the rules for casting between int and bool.
Comparisons between int objects return a bool.
Comparisons between an bool and an int upcasts the bool to an int.
false cast to int is 0
true cast to int is usually 1
Your code does (1) for the first comparison and (2) for all comparisons after.
So, if we write your condition and evaluate it step by step:
(1 == 1) // == ... == 1
(true) // == ... == 1
int(true) // == ... == 1
1 // == ... == 1
true
versus if you compare -1:
(-1 == -1) // == ... == -1
(true) // == ... == -1
int(true) // == ... == -1
1 // == ... == -1
false

Issues with commutative property of && operator

The code below that I have been having strange issues with is meant to trim off the unused portion of an integer array, and then convert it into a string.
Ex:
_ABC__DE______ would become _ABC__DE.
The problems show up when the input is filled with the default character. ("_" in the example).
sLength is the length of the integer array chars
The problematic code:
int inputLength = sLength - 1;
while (chars[inputLength] == defaultChar && inputLength >= 0) {
inputLength--;
}
inputLength++;
Serial.println("input length: " + String(inputLength));
// (in)sanity check
Serial.println(inputLength);
Serial.println(String(inputLength));
Serial.println(inputLength <= 0);
Serial.println(0 <= 0);
Serial.println(inputLength == 0);
Serial.println(0 == 0);
if (inputLength <= 0) {
//reset cursor position
Serial.println("index set to 0");
index = 0;
} else {
output = "";
for (int i = 0; i < inputLength; i++) {
char c = charSet[chars[i]];
if (c == '_') {
c = ' ';
}
output += c;
}
done = true;
}
The output when given an array filled with defaultChar:
input length: 0
0
0
0
1
0
1
If I'm interpreting correctly, the output means that 0 > 0 and 0 =/= 0 on even lines, but 0 <= 0 and 0 = 0 on odd lines.
The workaround I've come up with is replacing
while (chars[inputLength] == defaultChar && inputLength >= 0) {
inputLength--;
}
with one of the following
while (inputLength >= 0 && chars[inputLength] == defaultChar) {
inputLength--;
}
.
while (chars[inputLength] == defaultChar) {
inputLength--;
if (inputLength < 0) {
break;
}
}
which both result in an output of:
input length: 0
0
0
1
1
1
1
index set to 0
Why does this change the result?
As far as I knew until now, the && operator was commutative.
Is there something that I am missing that makes
chars[inputLength] == defaultChar && inputLength >= 0
not equal to
inputLength >= 0 && chars[inputLength] == defaultChar?
If It's relevant, this is being run on an 328P Arduino Nano with the old bootloader using IDE 1.8.8
&& is not commutative. It evaluates the left operand first and then stops if the left operand evaluated to 0.
Your original code fails because at some point it evaluates chars[-1] (which causes undefined behaviour if chars is an array). The alternative version does not have that problem because it performs the >= 0 test before using inputLength as an array index.
&& is commutative in the sense that the result of a && b is same as the result of b && a. But the built-in operator && has a short-circuiting behavior. This means that if the result of a && b can be decided by evaluating the first operand alone, the second one is not evaluated.
So when the first operand is chars[inputLength] == defaultChar and inputLength is -1, you enter the territory of undefined behavior which means the behavior of the program is unpredictable. But with the workarounds, you avoid undefined behavior because of the inputLength >= 0 and inputLength < 0 checks and therefore the code works as intended.
As #PeteBecker notes: a() && b() is not commutative if either a() or b() has side effects.

C++: Is there anyway to know what triggered an If-Statement?

Suppose I have an if-statement like this:
if ( x < 0 || y < 0 || z < 0) {
cout << "Something is less than zero!";
}
Is there anyway to know which disjunct in the disjunction triggered the if-statement? Or is it necessary to write three separate if-statements to achieve that end?
EDIT: The goal would be to short-circuit the process. Obviously, writing any more code than three separate if-then statements (for this case) would not work for this goal.
Speaking of convoluted methods that would be stupid:
convoluted_and_stupid( x < 0, y < 0, z < 0 );
void convoluted_and_stupid( bool xlz, bool ylz, bool zyz )
{
if( xlz || ylz || zlz )
cout << "something is less than zero!\n";
if( xlz )
cout << "it is x!\n";
if( ylz )
cout << "it is y!\n";
if( zlz )
cout << "it is z!\n";
}
Just with that context the answer is no, you cannot really tell which of the three variables is < 0 without adding extra nested ifs for each of the variables. All you know is that at least one of them (but maybe more than one) is.

C++ comparison of integers with float [duplicate]

This question already has answers here:
Checking if a value is within a range in if statment [duplicate]
(2 answers)
Closed 6 years ago.
I have the following code.that demonstrates the problem I am having. How come the comparison is not evaluating to true? Is this a limitation of integer and floating point comparisons?
#include <iostream>
int main(){
double m = -0.625;
if((-1)<=m<=0){
std::cout << "Enter here" <<std::endl;
}
return 0;
}
You can't do three way comparison like that in C. Change it to the following and it'll work:
if((-1) <= m && m <= 0){
std::cout << "Enter here" <<std::endl;
}
The condition in this if statement
if( ( -1 ) <= m <= 0 ){
is equivalent to
if( ( -1 <= m ) < = 0 ){
as -1 is less than m then the subexpression ( -1 <= m ) yields 1 in C and true in C++ that then is converted to 1 and the subexpression 1 <= 0 yields 0 in C and false in C++..
To get the expected result you should write instead
if( -1 <= m && m <= 0 ){
In C++ -1 <= m <= 0 is equivalent to (-1 <= m) <= 0.
In this example, -1 is implicitly converted to a float in order to use the <= operator with m. The result of this expression is a bool. This result is then implicitly converted to an int in order to use the <= operator with 0. Since a bool is converted to either 0 or 1 (false or true), this conditional statement will only be true when m is less than -1.
It makes sense from a math standpoint to structure the if statement like that, however you must break it up explicitly so the compiler knows what you want.
Try this
-1 <= m && m <= 0

creating hollow square c++ [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have written this code but somehow when it asks the user to enter a new number to create a square, it doesn't print the square. Could anyone anyone explain / help me please?
// ask user to repeat the process again at end of the first promt
while ( num > 1 || num < 20 )
{
ask user to repeat the process again at end of the first promt
while ( num > 1 || num < 20 )
{
// ask user t enter a square
cout << "Please enter size of square between #1-20: \n";
cin >> buf; num = atoi (buf.c_str());
cin.ignore(1000, 10);
// process of printing square
while ( num >= a)
{
b = 1;
while ( num >= b )
{
if ( a == 1 || a == num || b == 1 || b == num )
cout << "*";
else
cout << " ";
b++;
}
cout << endl;
a++;
}
I see no code where you initialise a to 1 so it may be it has some arbitrary value. If that arbitrary value is greater than num, the outer loop will never start.
For what it's worth, I would be using for loops in this case since you know in advance what the limits are, something like the following pseudo-code:
# Top line
for i = 1 to num (inclusive):
output "*"
output newline
# Middle lines
for i = 2 to num-1:
output "*" # Left char
for j = 2 to num-1: # Middle chars
output " "
output "*" and newline # Right char
# Bottom line
for i = 1 to num (inclusive):
output "*"
output newline
Then you don't have to worry about condition checking within the loop body.
A good rule of thumb is to use for for a known-before-the-start count of iterations, while for a loop where you don't know in advance how often you'll iterate.
Another likely problem is your condition:
while ( num > 1 || num < 20 )
Regardless of the value of num, that is always true, since you're using logical-or ||. Think of the possibilities:
num <= 1 : false or true -> true
num == 2..19 : true or true -> true
num >= 20 : true or false -> true
If you want to continue looping while you have a value outside of the range 1..20, you should use:
while ( num < 1 || num > 20 )
and you then end up with the following:
num <  1     : true or false -> true
num == 1..20 : false or false -> false
num >  20    : false or true -> true
There are quite a few other potential problems with your code, to wit:
You appear to have the outer loop in there twice.
You don't appear to define b or num.
You don't appear to set num before the outer loop (which checks it).
I suspect you meant to close the while ( num > 1 || num < 20 ) loop immediately after the cin.ignore() call since it's meant to keep going until you get a value from 1 to 20 and then draw the square. As it stands, a square will be drawn even if you enter 99.
Probably not the best code - but it can be done in six lines. Here goes.
for (int y = o; y < height; ++ y) {
for (int x = 0; x < width; ++x) {
cout << (y == 0 || y == (height - 1) || x == 0 || x == (width - 1) ? '*' : ' ' );
}
cout << endl;
}