How does the Java compiler, and other compilers, handle the following scenario; where there is a nested if with no curly brackets?
// In Java, to which of the 'if's does this 'else' belong?
// If bOne=false and bTwo=true, will the println run?
boolean bOne = false;
boolean bTwo = true;
if (bOne)
if (bTwo)
bTwo = bTwo; // do nothing
else
System.out.println("bOne:" + bOne + ". bTwo:" + bTwo);
The else clause applies to the second if statement. At first, it should be read as:
if (bOne)
if (bTwo)
bTwo = bTwo; // do nothing
else
System.out.println("bOne:" + bOne + ". bTwo:" + bTwo);
And then the code should be rewritten to use curly braces.
This applies to many imperative programming languages, one notable exception being Python which has significant indentation instead of curly braces.
This is known as the dangling else problem. The rule that solves this is that the else belongs to the closest if. So in that example, the else belongs to if (bTwo).
It does, as some others have already said, belong to the "nearest preceding if". However, to AVOID this problem always use braces (and proper indentation), so that there's no need to try to figure this out by understanding how the compiler works.
By the way, the compiler solves this in this way (pseudo-code):
process_if()
{
expect_token("if");
next_token();
expect_token("(");
next_token();
condition = parse_expression();
expect_token(")");
next_token();
then_part = parse_statement_or_block();
if (current_token == "else")
else_part = parse_statement_or_block();
else
else_part = nothing;
}
parse_statement_or_block()
{
if (current_token() == "{")
do
{
statements += parse_statement();
} while(current_token() != "}");
else
statements = parse_statement();
}
parse_statement()
{
switch(current_token())
{
case "while":
process_while();
break;
case "for":
process_for();
break;
case "if":
process_if();
break;
....
}
}
The way this parser works is that it reads the first if, and the statement inside that is another if, so it goes to process_if, takes the condition, the then_part and then checks for an else and takes that as the else_part for that if. Then goes back to the first if-statement and finds "no else there" (because it has already been consumed).
Actual compiler code that does exactly this:
https://github.com/Leporacanthicus/lacsap/blob/master/parser.cpp#L1854
Related
I'm a beginner in coding. I was recently working with to create a chatting programme where a user will chat with my computer. Here is a part of the code:
System.out.println("Hello, what's our name? My name is " + answer4);
String a = scanner1.nextLine();
System.out.println("Ok, Hello, " + a + ", how was your day, good or bad?");
String b = scanner2.nextLine();
**if (b.equals("good"))** { //1
System.out.println("Thank goodness");
} else **if (b.equals("it was good"))** { //2
System.out.println("Thank goodness");
} else **if (b.equals("bad"))** { //3
System.out.println("Why was it bad?");
String c = scanner3.nextLine();
System.out.println("Don't worry, everything will be ok, ok?");
String d= scanner10.nextLine();
} else **if (b.equals("it was bad"))**{ //4
System.out.println("Why was it bad?");
String c = scanner3.nextLine();
System.out.println("Don't worry, everything will be ok, ok?");
String d= scanner10.nextLine();
}
if(age<18){System.out.println("How was school?");}
else if (age>=18){System.out.println("How was work?");}
The conditions of the if statements are in Bold (surrounded with **). In case of first and the second condition I want my application to do same thing. Similarly third and fourth condition. I thought it was possible to somehow group them in if statement.
I tried with below code but it doesn't compile:
if (b.equals("good"), b.equals("it was good")) {
System.out.println("Thank goodness");
} else if (b.equals("bad"),(b.equals("it was bad"))) {
System.out.println("Why was it bad?");
String c = scanner3.nextLine();
System.out.println("Don't worry, everything will be ok, ok?");
String d= scanner10.nextLine();
}
Can someone correct it for me?
You can use logical operators to combine your boolean expressions.
&& is a logical and (both conditions need to be true)
|| is a logical or (at least one condition needs to be true)
^ is a xor (exactly one condition needs to be true)
(== compares objects by identity)
For example:
if (firstCondition && (secondCondition || thirdCondition)) {
...
}
There are also bitwise operators:
& is a bitwise and
| is a bitwise or
^ is a xor
They are mainly used when operating with bits and bytes. However there is another difference, let's take again a look at this expression:
firstCondition && (secondCondition || thirdCondition)
If you use the logical operators and firstCondition evaluates to false then Java will not compute the second or third condition as the result of the whole logical expression is already known to be false. However if you use the bitwise operators then Java will not stop and continue computing everything:
firstCondition & (secondCondition | thirdCondition)
Here are some common symbols used in everyday language and their programming analogues:
"," usually refers to "and" in everyday language. Thus, this would translate to the AND operator, &&, in Java.
"/" usually refers to "or" in everyday language. Thus, this would translate to the OR operator, ||, in Java.
"XOR" is simply "x || y but both cannot be true at the same time". This translates to x ^ y in Java.
In your code, you probably meant to use "or" (you just used the incorrect "incorrect solution" :p), so you should use "||" in the second code block for it to become identical to the first code block.
Hope this helped :)
You're looking for the "OR" operator - which is normally represented by a double pipe: ||
if (b.equals("good") || b.equals("it was good")) {
System.out.println("Thank goodness");
} else if (b.equals("bad") || b.equals("it was bad")) {
System.out.println("Why was it bad?");
String c = scanner3.nextLine();
System.out.println("Don't worry, everything will be ok, ok?");
String d= scanner10.nextLine();
}
This is probably more answer than you need at this point. But, as several others already point out, you need the OR operator "||". There are a couple of points that nobody else has mentioned:
1) If (b.equals("good") || b.equals("it was good")) <-- If "b" is null here, you'll get a null pointer exception (NPE). If you are genuinely looking at hard-coded values, like you are here, then you can reverse the comparison. E.g.
if ("good".equals(b) || "it was good".equals(b))
The advantage of doing it this way is that the logic is precisely the same, but you'll never get an NPE, and the logic will work just how you expect.
2) Java uses "short-circuit" testing. Which in lay-terms means that Java stops testing conditions once it's sure of the result, even if all the conditions have not yet been tested. E.g.:
if((b != null) && (b.equals("good") || b.equals("it was good")))
You will not get an NPE in the code above because of short-circuit nature. If "b" is null, Java can be assured that no matter what the results of the next conditions, the answer will always be false. So it doesn't bother performing those tests.
Again, that's probably more information than you're prepared to deal with at this stage, but at some point in the near future the NPE of your test will bite you. :)
You can have two conditions if you use the double bars(||). They mean "Or". That means only ONE of your conditions has to be true for the loop to execute.
Something like this:
if(condition || otherCondition || anotherCondition) {
//code here
If you want all of conditions to be true use &&. This means that ALL conditions must be true in order for the loop to execute. if any one of them is false the loop will not execute.
Something like this:
if(condition && otherCondition && anotherCondition) {
//code here
You can also group conditions, if you want certain pairs of them to be true. something like:
if(condition || (otherCondition && anotherCondition)) {
//code here
There is a simpler way.
if (b.contains("good")) {
...
}
else if (b.contains("bad")) {
...
}
I need to know if this:
return someBooleanRecursiveMethod(n) || someBooleanRecursiveMethod(n-1);
is equivalent to:
if (someBooleanRecursiveMethod(n))
return true;
else if (someBooleanRecursiveMethod(n - 1))
return true;
return false;
if anyone can solve this question fast I'll be very thankful.
Yes, Definitely, Saying || is the same as saying OR. Your example does the same thing, it just breaks the two statements apart. They essentially are the same.
For example:
if (I like apples) {
System.out.println("I like a fruit")
} else if (I like bananas) {
System.out.println("I like a fruit")
}
Now, I can clean up these two lines of code in two ways. I could make a switch statement, or, I can use the or operator:
if (I like bananas OR I like apples) {
System.out.println("I like a fruit")
}
AKA
if (x = 7 || x = 8) {
System.out.println("Either 7 OR 8")
}
The other way I mentioned is called a switch statement. It's slightly more advanced, but it just says,
I have this condition, I have multiple options, do this on this option
switch(x) {
case 6:
System.out.println("It is 6");
break;
case 7:
System.out.println("Either 7 OR 8")
break;
case 8:
System.out.println("Either 7 OR 8")
break;
case 9:
System.out.println("It is 9")
break;
}
Basically, in the end you are just doing the same thing. Either you are doing it all in one line of code, or you are splitting it up, and doing it in multiple lines of code. If you want specific outputs for each input, split it up. Otherwise, you're good either way.
They are not equivalent, since someBooleanRecursiveMethod returns a boolean (presumably), the first expression can evaluate to false || false which is false.
The second expression can never return false, unless you specify it.
if (someBooleanRecursiveMethod(n))
return true;
else if (someBooleanRecursiveMethod(n - 1))
return true;
else
return false;
In this case yes, both expressions are the same, either the method applied to n or n - 1 will return true, otherwise, when both are false returns false(same behaviour as or operator).
I am really confused by a CodingBat Java exercise. It's suppose to return true if the given string contains an appearance of "xyz" where the xyz is not directly preceeded by a period (.). So "xxyz" counts but "x.xyz" does not.
xyzThere("abcxyz") → true
xyzThere("abc.xyz") → false
xyzThere("xyz.abc") → true
I couldn't figure this out for the life of me so I just looked up a solution online and I'm so confused why this works. Any wanna help clarify? I added some comments on the code as to what I am having trouble with.
public boolean xyzThere(String str) {
int pos =0;
while ((pos = str.indexOf("xyz")) >= 0) { `
The while ((pos = str.indexOf("xyz")) >= 0) { confuses me here. I tried this without the double brackets and it didn't work. Does the double brackets do some kind of casting to an int or something? Also how does pos even get assigned to something in a while statement, does it run the part on the right first then assigns it?
if (pos == 0)
return true;
if (str.charAt(pos-1) != '.')
return true; // found it
// xyz was preceded by a period so skip over this match
str = str.substring(pos+1);
I am so confused how it can even reach str = str.substring(pos+1); I thought I could just take this out entirely but it broke the entire program. Since it's an if statement and it has no brackets to make it a block statement, how or when is this reached, and what is the logic behind it? What the purpose of this statement, as it seems so pointless to me. Even if it does get reached in the code, what does it do?
}
return false; // no luck
}
For any readers, here's the xyzThere problem: http://codingbat.com/prob/p136594
Since you were initially looking for any solution, here's a non-looping solution:
public boolean xyzThere(String str) {
return str.replaceAll("\\.xyz", "").contains("xyz");
}
Regarding double parens: if you remove the double parens, then it won't compile, because the compiler interprets that as trying to assign str.indexOf("xyz") >= 0 to the pos variable, and the types, boolean and int respectively, don't match.
You will notice that assignment is at the bottom of java operator precedence - without the extra parens, it will occur last: http://www.cis.upenn.edu/~palsetia/java/precedenceTable.html
unle
Regarding assignment in a loop - yes this is valid. The value assigned to pos is then compared with 0.
Regarding str = str.substring(pos+1);. This is how the posted solution is removing ".xyz" from the string which finally determines whether the string still contains "xyz".
Regarding the if statement
if (str.charAt(pos-1) != '.')
return true; // found it
Without brackets, the implied scope of the if statement if the next statement. The style here is generally considered back practice for just the reason you've found and should be rewritten as either:
if (str.charAt(pos-1) != '.') {
return true;
}
or
if (str.charAt(pos-1) != '.') return true;
while ((pos = str.indexOf("xyz")) >= 0) {
indexOf returns -1 if the string is not found so this is going to continue looking so long as an "xyz" is found in the string. See later for how it makes sure this is another occurrence rather than the same one again.
The extra bracket is to stress that there is also an assignment going on here. pos is being updated to the start of the "xyz" that was found (or -1 if no more).
if (pos == 0)
return true;
It is allowed at the start - I guess.
if (str.charAt(pos-1) != '.')
return true;
If there is not a "." just before it then we're done.
str = str.substring(pos+1);
Throw away everything up to and including the "x" of the discovered "xyz". Makes sure that next time around we don't find the same one again.
return false;
We got to the end without finding one - it must not be there.
The following code snippet needs "double brackets" (really double parentheses -- it pays to be precise because brackets are a different character) because the parens group different parts of what amounts to a mathematical expression. What you think are double brackets are actually single parens grouping different parts of the expression from what you probably think they're grouping.
while ((pos = str.indexOf("xyz")) >= 0)
^-----^
^------------------------^
^-------------------------------^
If you switch to an IDE instead of the simple text editor that you're probably using, the IDE will highlight matching parentheses so you can see which opening paren is related to which closing paren. There's no casting or other magic going on. Parentheses, brackets, angle brackets, and curly braces. are just there to show the beginning and end of particular groups of things, whether it's an expression, an expression within an expression, a data set, etc.
I'm writing an android app that does a lot of stuff. I recently refactored my code to have a better structure, but suddenly I'm getting a very strange problem.
handleRequest(String str)
{
boolean foo = executeCommand(str);
this.publishProgress("FOO1: " + foo);
if (foo == false);
{
this.publishProgress("FOO2: " + foo);
sendString("Failed to execute: " + str);
}
this.publishProgress("FOO3: " + foo);
sendEOM();
}
The code above should execute a command, and store 'foo' with if the command was executed correctly. This code is inside an Android AsyncTask (thread) so I use 'publishProgress' to show a toast.
I've been flipping through the debugger and FOO is true! The toasts show FOO to be true the entire way through as well. However, it goes ahead and jumps inside the IF block and executes that too. I've never seen this before, I think its a problem with Java. I was stepping though the function 'executeCommand' and it looks like it is skipping return statements too.
I've ran the code on a virtual device and a real one and they both do this.
Any ideas? I'm completely at a loss here.
You said
if (foo == false);
remove the semicolon, it should be
if (foo == false) {//your code}
Remove the semicolon: if (foo == false); -> if (foo == false)
You put a semicolon after if statement.
That way, your if statement is there on its own, and the following block of code is always running.
Modify your code like this:
handleRequest(String str) {
boolean foo = executeCommand(str);
this.publishProgress("FOO1: " + foo);
if (foo == false) {
this.publishProgress("FOO2: " + foo);
sendString("Failed to execute: " + str);
}
this.publishProgress("FOO3: " + foo);
sendEOM();
}
N.B.
Keeping your block-opening braces in the same line as the function definition/loop condition makes these kinds of mistakes much less frequent, IMO.
There will be no ";" semicolon after if statement.
So instead of if (foo == false); it should be if (foo == false){}
If you write semicolon (;) after if statement it ends the if condition there!
you need to start a block of code after writing if condition i.e.
if(foo == false){
// block of Code
} //end of if condition
I don't know how this line compiles if (foo == false);, but evidently it does. You need to remove the semicolon at the end of the line as others have mentioned. With the ; there it means do nothing if foo is false. Then the program goes into the next block between the two curly braces.
You need to install findbugs or PMD to warn against this kind of typos.
How come this is not possible? I am getting illegal start of expression.
(s1.charAt(i) == ' ') ? i++ : break;
The thing to understand here is that the ?: operator is used to return a value. You're basically calling a function that looks like this in that line:
anonymous function:
if(s1.charAt(i) == ' '):
return i++;
else:
return break;
Makes no sense, right? The ?: operator was only designed as a shorthand for if/else return statements like the above, not a replacement of if/else altogether.
You cannot use break in part of a ternary conditional expression as break isn't an expression itself, but just a control flow statement.
Why not just use an if-else construct instead?
if (s1.charAt(i) == ' ') {
i++;
} else {
break;
}
The ternary operator is an expression, not a statement. Use if ... else ... for this.
Of course it works. But it's an operator. Since when was a statement such as 'break' an operand?
I recommend avoiding the ternary (?:) operator EXCEPT for simple assignments. In my career I have seen too many crazy nested ternary operators; they become a maintenance headache (more cognitive overload - "don't make me think!").
I don't ban them on my teams, but recommend they are used judiciously. Used carefully they are cleaner than a corresponding if/else construct: -
public int ifFoo() {
int i;
if( isSomethingTrue()) {
i = 5;
}
else {
i = 10;
}
return i;
}
Compared to the ternary alternative: -
public int ternaryFoo() {
final int i = isSomethingTrue()
? 5
: 10;
return i;
}
The ternary version is: -
Shorter
Easier to understand (my opinion, of course!)
Allows the variable to be "final"; which simplifies code comprehension; in a more complex method, someone reading the code knows no further code will try and modify the variable - one thing less to worry about.