What are the ways of reducing code quantity in a method that contains schematic conditional statements?
What would be a good practice of placing such code. Should it be in a different method/class?
Example code in Java. It contains one scheme repeated twice:
if (calculation[i].equals("*")) {
if (stack.canDoOperation()) {
times();
} else {
operationFailed = true;
}
} else if (calculation[i].equals("+")) {
if (stack.canDoOperation()) {
sum();
} else {
operationFailed = true;
}
}
You could write a helper method, wrapping the given operation method into the commonly required checks. You could also put a try/catch in there, in case the operation can fail.
private boolean tryOperation(Runnable operation) {
if (stack.canDoOperation()) {
operation.run();
return true;
} else {
return false;
}
}
And use like this:
if (calculation[i].equals("*")) {
operationFailed = ! tryOperation(this::times);
} else if (calculation[i].equals("+")) {
operationFailed = ! tryOperation(this::sum);
}
Or, with Java 8, you can put the method references to those operations into a Map:
Map<String, Runnable> operations = new HashMap<>();
operations.put("*", this::times);
operations.put("+", this::sum);
...
Runnable operation = operations.get(calculation[i]);
if (operation != null && stack.canDoOperation()) {
operation.run();
} else {
operationFailed = true;
}
You can also combine the two approaches:
operationFailed = ! tryOperation(operations.get(calculation[i]);
Here is some example of how you can utilize repetitive statements. For more clarity you can extract stack.canDoOperation() to variable if it doesn't break your logic. Also you can consider moving it to assertion in beginning of the method and than put calculation[i] into switch statement.
if (calculation[i].equals("*") && stack.canDoOperation()) {
times();
}
} else if (calculation[i].equals("+") && stack.canDoOperation()) {
sum();
}
} else {
operationFailed = true;
}
You can use a switch statement into an if and maybe in a more logical way : check if you can do an operation, and if so find which one :
if (stack.canDoOperation()) {
switch(calculation[i]){
case "*": times(); break;
case "+": sum(); break;
} else {
operationFailed = true;
}
You can also give the value of operationFailed into the if statement :
operationFailed = !stack.canDoOperation() will be done first (if you cannot do an operation, operationFailed will true;
the value of !operationFailed (!!stack.canDoOperation() = stack.canDoOperation()) will be used in the if test
if (!(operationFailed = !stack.canDoOperation())) {
switch(calculation[i]){
case "*": times(); break;
case "+": sum(); break;
}
Since Java 7, it's possible to switch over Strings.
switch (calculation[i]) {
case "*":
times();
break;
case "+":
sum();
break;
}
Furthermore, for each calculation type, you are repeating the canDoOperation check. It's better that you bubble up this check:
if (stack.canDoOperation()) {
operationFailed = true;
}
else {
switch ... // Your switch statement
}
I suggest you move these operations to a separate method:
/**
* Performs the specified operation.
* #param The operation to perform.
* #return True if the operation was succeeded, false otherwise.
*/
boolean performOperation(String operation) {
if (!stack.canDoOperation()) {
return false;
}
switch (operation) {
case "*":
times();
break;
case "+":
sum();
break;
default:
return false;
}
return true;
}
However, without knowing the rest of your code, it's unclear whether this is a good solution.
Related
So this little function is supposed to check if parentheses and brackets are matched next to each other. I feel like it should work and I've tried it a few different ways but I can't figure out how to check if my next char is what I expect it to be.
class Parenths {
public boolean isValid(String s) {
char[] parens = s.toCharArray();
if (parens.length == 0) return true;
for (int i = 0; i < parens.length; i+=2) {
String curr= String.valueOf(parens[i]);
String next = String.valueOf(parens[i+1]);
// System.out.println(next.equals(")"); --------> false
// System.out.println(Object.equals(next, ")")); ----> error
switch (curr) {
case "(": if (!next.equals(")")) return false;
case "{": if (!next.equals("}")) return false;
case "[": if (!next.equals("]")) return false;
}
}
return true;
}
}
You can see the lines I printed to debug and it seems that .equals is not the right thing to use here? Can anyone explain why this isn't working?
PS. I realize I don't have to convert the string to a char array to compare elements, so unless that's the only fix, please don't point that out to me.
Not tested, but it seems to be a problem of fall through. Try to replace if (boolean) return boolean with return boolean, this should do the trick.
The problem is that you don't have a break at the end of the cases, so if, for example, your first case is true, it will not stop execution and execute the 2nd test, which will be false. If you change your conditional statements to a direct return, you will not have this problem.
EDIT: Sorry, I read too quickly. Doing so will break your loop. Actually, you have to add a break at the end of the cases.
case "(": if (!next.equals(")")) return false; break;
case "{": if (!next.equals("}")) return false; break;
case "[": if (!next.equals("]")) return false; break;
First , you have to add break; after the cases its important to stop seeing the cases
switch (curr) {
case "(": if (!next.equals(")")) return false;
break;
case "{": if (!next.equals("}")) return false;
break;
case "[": if (!next.equals("]")) return false;
break;
}
Secondly , your code doesnt support the confrotation of a closing patenthesis at first , you have to add a default case
switch (curr) {
case "(": if (!next.equals(")")) return false;
break;
case "{": if (!next.equals("}")) return false;
break;
case "[": if (!next.equals("]")) return false;
break;
default :
break;
}
return true;
Also , you have to make sure the next element is not null before comparing to it , and dont increment with 2 , you give a String with a one element and that's why you get the error
public static boolean isValid(String s) {
char[] parens = s.toCharArray();
if (parens.length == 0) return true;
for (int i = 0; i < parens.length; i++) {
String curr= String.valueOf(parens[i]);
String next = "";
try {
next = String.valueOf(parens[i+1]);
switch (curr) {
case "(": if (!next.equals(")")) return false;
break;
case "{": if (!next.equals("}")) return false;
break;
case "[": if (!next.equals("]")) return false;
break;
default :
break;
}
return true;
}catch(Exception e) {}
}
return false;
}
Test :
System.out.println(isValid("()"));
// Output : true
System.out.println(isValid("("));
// Output : false
For an assignment we are creating a java program that accepts a java file, fixes messy code and outputs to a new file.
We are to assume there is only one bracket { } per line and that each bracket occurs at the end of the line. If/else statements also use brackets.
I am currently having trouble finding a way to indent every line after an opening bracket until next closing bracket, then decreasing indent after closing bracket until the next opening bracket. We are also required to use the methods below:
Updated code a bit:
public static void processJavaFile() {
}
}
This algorithm should get you started. I left a few glitches that you'll have to fix.
(For example it doesn't indent your { brackets } as currently written, and it adds an extra newline for every semicolon)
The indentation is handled by a 'depth' counter which keeps track of how many 'tabs' to add.
Consider using a conditional for loop instead of a foreach if you want more control over each iteration. (I wrote this quick n' dirty just to give you an idea of how it might be done)
public String parse(String input) {
StringBuilder output = new StringBuilder();
int depth = 0;
boolean isNewLine = false;
boolean wasSpaced = false;
boolean isQuotes = false;
String tab = " ";
for (char c : input.toCharArray()) {
switch (c) {
case '{':
output.append(c + "\n");
depth++;
isNewLine = true;
break;
case '}':
output.append("\n" + c);
depth--;
isNewLine = true;
break;
case '\n':
isNewLine = true;
break;
case ';':
output.append(c);
isNewLine = true;
break;
case '\'':
case '"':
if (!isQuotes) {
isQuotes = true;
} else {
isQuotes = false;
}
output.append(c);
break;
default:
if (c == ' ') {
if (!isQuotes) {
if (!wasSpaced) {
wasSpaced = true;
output.append(c);
}
} else {
output.append(c);
}
} else {
wasSpaced = false;
output.append(c);
}
break;
}
if (isNewLine) {
output.append('\n');
for (int i = 0; i < depth; i++) {
output.append(tab);
}
isNewLine = false;
}
}
return output.toString();
}
I am new to Java, would appreciate some help.
what I am trying to do here is switch between the cases. However what I also need is to not skip the remaining cases in this procedure.
I mean the code below should output:
two
four
three
four
public class X {
public static void main(String[] args) {
String n = "two";
while(true)
{
switch (n)
{
case "zero":
{
System.out.println("zero");
n="one";
}
case "one":
{
System.out.println("one");
n="three";
}
case "two":
{
System.out.println("two");
if (12>3)
{
n="four";
break;
}
}
case "three":
{
System.out.println("three");
}
case "four":
{
System.out.println("four");
return;
}
}
}
}
}
I have used return to end the while loop. Now I do understand that I have used break in case two which will break the current switch and thereby not complete it. But if i don't, I just can't switch between cases in the first place. So, I need a different solution. And working implementation in java should be helpful. Thanks
You can use Queue for this.
Each case is responsible to add the next one to the queue by the order of expected execution.
Queue q = new LinkedList();
q.add("two");
String n = (String)q.poll();
while(n!=null)
{
switch (n)
{
case "zero":
{
System.out.println("zero");
q.add("one");
break;
}
case "one":
{
System.out.println("one");
q.add("three");
q.add("two");
break;
}
case "two":
{
System.out.println("two");
if (12>3)
{
q.add("four");
}
q.add("three");
break;
}
case "three":
{
System.out.println("three");
q.add("four");
break;
}
case "four":
{
System.out.println("four");
break;
}
}
n=(String) q.poll();
}
The problem does not lie within the switch statement. You simply need to distinguish from where you 'came from'.
To do that you need to remember it, e.g. in a local variable:
String lastN;
and in the loop before the switch:
lastN = n;
Now you can do something like:
case "four":
{
System.out.println("four");
if("three".equals(lastN))
{
return;
}
else
{
n = "three";
break;
}
}
Your code is working as it should, if what you need is a fall through
then consider the fact that case zero and one must be executed first...
on the other hand, you don't need to add { } to the case group
case "zero": {
System.out.println("zero");
n = "one";
}
public static void main(String[] args) {
String n = "two";
while(true)
{
switch (n)
{
case "zero":
{
System.out.println("zero");
}
case "one":
{
System.out.println("one");
}
case "two":
{
System.out.println("two");
}
case "four":
{
System.out.println("four");
if(n=="four"){
return;
}
}
case "three":
{
System.out.println("three");
n="four";
}
}
}
}
I'm working on scanner code. How can I check the file contains number or strings by using switch statement? Here is my switch statement part code
while(st.hasMoreTokens()){
int caret=jTextArea1.getCaretPosition();
switch(st.nextToken()){
case "++": jTextArea1.insert("++"+" "+":Unary Operator "+"\n",caret);
break;
case "--": jTextArea1.insert("--"+" "+":Unary Operator "+"\n",caret);
break;
}
}
Write a method which will return true if the input param is a number other wise it will throw NFE and as a result it will return false
:
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch(NumberFormatException e) {
return false;
}
return true;
}
If I have a switch statement testing the value of integer i, how can I execute the same code once?
For example:
switch(i) {
case 0:
if(j == 2) {
booleanA = true;
booleanB = false;
case 1:
if(j == 4) {
booleanA = true;
booleanB = false;
}
With 5 different cases, instead of me having to type out
booleanA = true;
booleanB = false;
five times, is there a way to say if one of the if statements is true, use this block of code? Is that possible?
Thanks!
You can do it without a switch statement...
int[] requiredJ = {2,4};
if (j == requiredJ[i]) {
booleanA = true;
booleanB = false;
}
I can not understand logic behind your code, but may be this can be done ( Like switch hit in cricket !!! :p).
Assign the values to your booleans, and revert in default case.
booleanA = true;
booleanB = false;
// more code blocks
switch(i) {
case 0:
// Process
break;
case 1:
// Process
break;
default :
booleanA = false;
booleanB = true;
}