Google javaparser IfStmt not counting consequent <else-if> - java

I am using Google javaparser to parse the java file, when I try to count the "If" statement, it seems like I can not get the number of "else-if" statement.
For example, I want to parse the following code:
if(i>1){
i++;
}else if(i>2){
i++;
}else if(i>3){
i++;
}else{
i++;
}
I want to get the Cyclomatic complexity so that I need to count the number of "if" and "else-if".
When I use Visitor pattern, I can only visit the "IfStmt" defined in the API, the code looks like:
private static class IfStmtVisitor extends VoidVisitorAdapter<Void> {
int i = 0;
#Override
public void visit(IfStmt n, Void arg) {
//visit a if statement, add 1
i++;
if (n.getElseStmt() != null) {
i++;
}
}
public int getNumber() {
return i;
}
}
There is no way to get "else-if" but the Visitor pattern with "IfStmt" treats the whole code block as one "if" Statement.So, I expect the number to be 4, but it is 2.
Anyone have some idea?

A if-statement only contains one "then Statement" and one "else Statement". The else Statement can be a hidden if statement. So there is a recursivity. To track your needed complexity the following recursive method may help:
private static class IfStmtVisitor extends VoidVisitorAdapter<Void> {
int i = 0;
#Override
public void visit(IfStmt n, Void arg)
{
cyclomaticCount(n);
}
private void cyclomaticCount(IfStmt n)
{
// one for the if-then
i++;
Statement elseStmt = n.getElseStmt();
if (elseStmt != null)
{
if ( IfStmt.class.isAssignableFrom(elseStmt.getClass()))
{
cyclomaticCount((IfStmt) elseStmt);
}
else
{
// another for the else
i++;
}
}
}
public int getNumber() {
return i;
}
}
Hope that helps.

Related

Studying if/else vs if/if statement

I was trying to write a code where all the 0s will be moved to the right of the array. I just used a left and a right pointer.
public class Solution {
public int[] moveZero(int[] array) {
// Write your solution here
if (array.length==0) {
return array;
}
int left=0;
int right=array.length-1;
while (left<=right) {
if (array[left]!=0) {
left+=1;
}
if (array[right]==0) {
right-=1;
} else {
int temp = array[left];
array[left] = array[right];
array[right] = temp;
left+=1;
right-=1;
}
}
return array;
}
}
I know here I should use the if/else if instead of if/if, that's why I have the index out of the bound error. But I don't understand why? If I have the if/if statement, what's the difference does that make rather than using if/else if in this question?
if (condition1) {
a();
} else if (condition2) {
b();
} else {
c();
}
means the same as
if (condition1) {
a();
} else {
if (condition2) {
b();
} else {
c();
}
}
So else if is just shorthand for an else with an if inside.
To understand why your code throws an ArrayIndexOutOfBoundsException, the easiest way is stepping through the code in a debugger (consult the documentation of your development environment for how to do this).
Alternatively, you can pretend you are a computer, and execute the program with pen and paper to figure out where your program goes off the rails. However, using a debugger is easier once you know how to use one.
I don't think there's any reason to use if/else instead of if/if, they both have their place. In an if/if statement, if the second if statement relies on the previous being false, then it should be converted to an if/else statement. If the else statement in an if/else statement has nothing to do with the if statement before it, then it should be converted into two separate if statements.
As an example of when to use an if/else statement (to do the same thing yours does):
public class Solution {
public int[] moveZero(int[] inputArray) {
int[] outputArray = new int[inputArray.length];
int left = 0;
int right = inputArray.length - 1;
for (int num : inputArray) {
if (num == 0) {
outputArray[right] = num;
right --;
} else {
outputArray[left] = num;
left ++;
}
}
return outputArray;
}
}

Getting previous return value with new value concatenated using recursion

I'm working a problem on recursion. After writing the code requested, the site I'm working from runs the code with different values as input. However, the first run works properly, but all subsequent runs concatenate the return value of the first run with the values of each of the subsequent runs.
I am also getting a stack overflow error at the end.
I need help!
Here is the code:
package com.company;
import static java.lang.System.*;
public class Main {
public static String returnValue="";
public static void main(String[] args) {
repeat("this is fun", 1);
out.println(returnValue);
}
public static String repeat(String s, int i){
if (i==0) {
return returnValue;
}
else{
returnValue+=s;
repeat(s,i-1);
}
return returnValue;
}
}
Any help is greatly appreciated.
You need to move the static returnValue into the method. You then need to control the result by capturing the string returned by the inner recursive call.
Something like:
public static String repeat(String s, int i){
String returnValue="";
if (i==0) {
return returnValue;
}
else{
returnValue+=s + repeat(s,i-1);
}
return returnValue;
}
NB: This may not be the equivalent algorithm to what you intend but it should demonstrate the technique.
If that is the correct solution then you can tidy up with:
public static String repeat(String s, int i){
if (i==0) {
return "";
} else {
return s + repeat(s,i-1);
}
}
If you are comfortable with expressions:
public static String repeat(String s, int i) {
return i <= 0
? ""
: s + repeat(s, i - 1);
}
and you can get rid of the static attribute!

calculate the number of characters in a string recursively

I am trying to calculate the number of characters in a string by using recursive method. here is my code in java
public class MainClass {
public int length(String str) {
if (str == null) {
return 0;
} else {
return length(str.substring(1))+1; // in eclipse it says : at MainClass.length(MainClass.java:12)
}
}
public static void main(String args[]) {
MainClass m = new MainClass();
System.out.println(m.length("ali"));
}
}
This line does not work : return length(str.substring(1))+1;
How can I correct the code?
Thanks
You forgot the case when your String argument is an empty string, include that in your check:
if (str == null || str.length()==0) {
return 0;
} else {
[...]
Please note that the Exception that you get contains valuable information about what's going wrong, in this case it's probably a StringIndexOutOfBoundsException because you call substring(1) on an empty String object.
It should be
public int length(String str) {
if (str==null||str.isEmpty()) {
return 0;
}else {
return length(str.substring(1))+1
}

Syntax errors in parametrizing stacks

I'm a computer science student that just started my sophomore programming class and I'm having some real issues with a project that deals with Stacks and collections.
Basically, this is a project that relies on the ArrayStack Class(ArrayStack, to be specific) to convert mathematical expressions between postfix and infix forms.
Basically, ArrayStack is used to take in an expression like 45 * (26 - 5) / 54, turn it into a collection, then rewrite in a postfix form like 45 26 5 - * 54 /
The problem is, first of all, whenever I try to substitute with Character in the main method(since the stack needs to store both operators and operands, maybe there's a better data type I'm missing here), I get some strange syntax error, usually involving the program thinking that ArrayStack.System is somehow a statement(System.out.println is right below an ArrayStack statement, which suggests there's some kind of syntax problem)
Here's the code I have so far:
public class ArrayStack<T> implements StackADT<T>
{
private static final int DEFAULT_CAPACITY = 100;
private int top;
private T[] stack;
public ArrayStack() {
top = -1;
stack = (T[]) (new Object[DEFAULT_CAPACITY]);
}
public void push(T element) {
stack[top+1] = element;
top++;
}
public T pop() {
T element = stack[top];
stack[top] = null;
top--;
return element;
}
public T peek() {
return stack[top];
}
public boolean isEmpty() {
if(stack[0]==null)
return true;
else{
return false;
}
}
public int size() {
int length = 0;
for(int count=0;count<stack.length;count++) {
if(stack[count]!=null) {
length++;
}
else if(stack[count]==null) {
break;
}
}
return length;
}
public String toString() {
String array = "";
for(int count=0;count<stack.length;count++) {
array = array+stack[count]+" ";
}
return array;
}
}
And for the main method:
public class StackTester {
public static void main(String[] args) {
boolean quit = false;
int input;
String expression;
do {
System.out.println("1. Convert infix to postfix");
System.out.println("2. Convert postfix to infix");
System.out.println("3. Exit.");
java.util.Scanner keyboard = new java.util.Scanner(System.in);
input = keyboard.nextInt();
switch(input) {
case 1:
//ArrayStack stack = new ArrayStack();
//System.out.println("Enter an infix expression: ");
expression = keyboard.next();
for(int count=0;count<expression.length();count++) {
Character a = expression.charAt(count);
stack.push(a);
}
for(int count=stack.size()-1;count>=0;count--) {
if(stack.peek()=='+') {
}
}
}
break;
}
while(!quit);
}
}
The error usually occurs at the lines marked with //, every time I try to insert something like or otherwise, the program gives some weird syntax error like its trying to read it together with the line below it. Any ideas what's going on here?

Keeping count in a recursive Java method

Here's what I'm trying to accomplish with this program: a recursive method that checks if the number of instances of a substring matches a specified amount of instances, returning a boolean.
Here's the issue I'm having with this particular recursive method: I'd like to be able to move the counter inside the recursive method body, however, I ran into the issue that the counter resets at each recursive call when it is in the method body. The only way I have been able to make it work is through the use of a static counter variable declared outside of the function body. Is there any other technique I can marshall in order to be able to situate the counter of the method in the method body so that this method may act as a "black box"?
Thanks for any advice or insights you can provide.
public class strCopies {
//count instances of part and whole equality
static int count = 0;
public static boolean copies(String whole, String part, int check)
{
//check if current string length is valid
if(whole.length() < part.length())
{
//check if check parameter equals part instances
if(count == check)
{
return true;
}
else
{
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part))
{
count++;
}
//recursive call
return copies(whole.substring(1), part, check);
}
public static void main(String[] args)
{
System.out.println(copies("dogcatdog", "cat", 2));
}
}
You are almost there: you should change the meaning of the check variable to the remaining number of matches, rather than the original number requested. Then you can rewrite the method without keeping an additional count at all, as follows:
public static boolean copies(String whole, String part, int check)
{
//check if current string length is valid
if(whole.length() < part.length())
{
//check if check parameter equals part instances
if(check == 0)
{
return true;
}
else
{
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part))
{
check--;
}
return return copies(whole.substring(1), part, check);
}
You can pass the count as an argument to the recursive function, this way it will not be "reset" when the method is called.
public static boolean copies(String whole, String part, int check, int count)
{
//check if current string length is valid
if(whole.length() < part.length())
{
//check if check parameter equals part instances
if(count == check)
{
return true;
}
else
{
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part))
{
count++;
}
//recursive call
return copies(whole.substring(1), part, check, count);
}
public int countRecursive(String whole, String part){
if(whole.length() < part.length()) return 0;
if(part.length()==0) return -1; // ints can't express "Infinity"
// maybe you want to return -1 only if whole is not null, and something else if it is.
int count = 0;
if(whole.substring(0, part.length()).equals(part))
count = 1;
return countRecursive(whole.substring(1), part) + count;
}
public boolean count(String whole, String part, int check){
return countRecursive(whole, part) == check;
}
Note that this does away with the counter at the expense of creating a whole bunch of strings for each state. (You replace a single int with the length of each string given.) But then again, if you want performance then you shouldn't be using recursion for something like this. A simple for loop would do much nicer.
You could add the counter to the method parameters as follows:
public class strCopies {
public static boolean copies(String whole, String pargs, int check){
return copies(whole, pargs, check, 0);
}
public static boolean copies(String whole, String part, int check, int count)
{
//check if current string length is valid
if(whole.length() < part.length()) {
//check if check parameter equals part instances
if(count == check) {
return true;
}
else {
return false;
}
}
//check if current string value is an instance of part
if(whole.substring(0, 3).equals(part)) {
count++;
}
//recursive call
return copies(whole.substring(1), part, check, count);
}
public static void main(String[] args) {
System.out.println(copies("dogcatdog", "dog", 2));
}
}
The simple version:
Create a class that contain the counter.
Initialize it on your main.
Pass its reference to the function.
Another idea:
Create a singleton class with a static counter and your function X.
Inside its constructor add one to its counter and call function X.
Then instead of running your function like you did before, "create" that class, thus increasing the counter and calling the function.
The neat thing is you can inherit that class and redefine X to whatever you choose at a latter stage, so you get this general class that counts on each activation of a function.
Not sure what is your recursive method doing. However, to maintain a counter, you can pass it as an argument to your recursive method.
public boolean copies(String whole, String part, int check, int count) {
// your code here....
if(whole.substring(0, 3).equals(part))
{
count++;
}
//recursive call
return copies(whole.substring(1), part, check, count);
}
When you make first call to your copies method, you'll need to pass 0 to your count.

Categories