I am quite new to Java and I am making a string parsing calculator. I have a piece of code which has some almost identical fragments which I would like being extracted into some method or so, but I could not come up with an idea how to do it.
Here is a piece of code:
case '+':
current_priority = 1;
if (last_priority < current_priority) {
i++;
first_operand = new Add(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
break;
case '*':
current_priority = 2;
if (last_priority < current_priority) {
i++;
first_operand = new Multiply(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
break;
case '/':
current_priority = 2;
if (last_priority < current_priority) {
i++;
first_operand = new Divide(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
break;
I would like to get a method or something which would copy the behavior of the following fragment:
current_priority = x;
if (last_priority < current_priority) {
i++;
first_operand = new Something(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
The problem is that as far as I'm concerned I can't declare non-initialized objects in Java and for my program it's important not to run the constructor of Something (Add/Multiply/Divide) before making sure it's really needed, so passing an object to this method is not a way, I have to somehow create an object inside this method, but this seems to lead to making two switches with identical cases and I would like more elegant solution if possible. I also don't know how to reproduce the return/assignment behavior depending of a condition inside a method. I would really appreciate any help.
A Use a Factory
current_priority = x;
if (last_priority < current_priority) {
i++;
first_operand = myOperationFactory.createOperand(operation, first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
public class OperationFactory {
public Operand createOperand(char operation, Operand firstOperand, Operand secondOperand) {
switch (operation) {
case '+': return new Add(firstOperand, secondOperand);
case ...
}
B (advanced) use enum and reflection.
public enum Operations {
ADD('+', Add.class),
MULTIPLY('*', Multiply.class)
...;
private char symbol;
private Constructor<? extends Operation> constructor;
public Operations(char symbol, Class<? extends Operation> clazz) {
this.symbol = symbol;
this.constructor= clazz.getConstructor(Operand.class, Operand.class);
}
public Operation create(Operand operan1, Operand operand2) {
return constructor.newInstance(operand1, operand2);
}
public char getSymbol() {
return this.symbol;
}
public static Operations getFromSymbol(char symbol) {
for (Operations op : Operations.values()) {
if (op.getSymbol() == symbol) {
return op;
}
}
}
}
and
current_priority = x;
if (last_priority < current_priority) {
i++;
Operations operation = Operations.fromSymbol(opSymbol);
first_operand = operation.create(first_operand, parse(expression, current_priority));
....
Related
The code:
public class Branches {
public double justOneIf(int a) {
double result;
if (a > 0) {
result = 1.0d;
} else {
result = -1.0d;
}
return result;
}
public String switches(int x) {
String result;
switch (x) {
case 0: {
result = "zero";
break;
}
case 1: {
result = "one";
break;
}
case 2: {
result = "two";
break;
}
default: {
result = "kill all humans";
}
}
return result;
}
public int deepIf(int x) {
int y;
if (x == 0) {
y = 1;
} else {
if (x > 0) {
y = 2;
} else {
y = 3;
}
}
return y;
}
}
In OpenClover (version 4.4.1) report I got metrics for this class:
Code metrics
Branches:6
...
Why six branches here? How does clover count it?
I've got it. It's pretty simple: one "IF" means 2 branches. Just it.
Branch coverage
Branch coverage (or 'decision coverage') is a code coverage metric
that measures which possible branches in flow control structures are
followed. Clover does this by recording if the boolean expression in
the control structure evaluated to both true and false during
execution.
EDIT: I may have fixed it by making the instance variable static? If so, why does this fix it? This was something my prof glossed over in my intro to OOP class, so I never really learned about it.
so, I'm not sure if I'm using terrible coding practice and just don't realize it, but I'm having a single crippling issue with my program, despite this one issue, everything appears to be running fine.
This program takes strings from an argument file and executes the commands based on the instructions. However, when I issue the command "x = x + 5" I experience a crippling issue.
My class titled Work creates another instance of my other class Read. When it does this, the ArrayList that I define at the top of Read is overwritten with a new instance, and thus, deletes the whole list of variables. I'm unable to find a way to make the initialization execute only once. Where am I going wrong?
Work:
import java.util.*;
public class Work {
static int Precedence(char ch){
switch (ch){
case '+':
case '-':
return 1;
case '*':
case '/':
case '%':
return 2;
case '^':
return 3;
}
return -1;
}
String infixConverter(String infix){
Variable tvar = new Variable(); //consider removing these~
Read reader = new Read();
String pfix = new String("");
Stack<Character> stack = new Stack<>();
for (int i=0; i<infix.length(); ++i) {
char curr = infix.charAt(i);
// if (Character.isLetterOrDigit(curr)||curr==' ') {
if (Character.isDigit(curr)||curr==' ') {
pfix += curr;
}
else if (Character.isLetter(curr)){
// Read reader = new Read();
if (reader.varExists(curr)){
// Variable tvar = new Variable();
int n = reader.getIndex(curr);
tvar = reader.vars.get(n);
pfix += tvar.getValue();
}
else{
//error
}
//implement this below
//check for letter within the string, if the string is
}
else if (curr == '('){
stack.push(curr);
}
else if (curr == ')'){
while (!stack.isEmpty() && stack.peek() != '(') {
pfix += stack.pop();
}
if (!stack.isEmpty() && stack.peek() != '(') {
return "Invalid Expression"; // invalid expression
}
else {
stack.pop();
}
}
else {
while (!stack.isEmpty() && Precedence(curr) <=
Precedence(stack.peek())) {
pfix += stack.pop();
}
stack.push(curr);
}
}
while (!stack.isEmpty()) {
pfix += stack.pop();
}
int sol = postfixEvaluation(pfix);
pfix = Integer.toString(sol);
return pfix;
}
Integer postfixEvaluation(String pfix){
Stack<Integer> stack = new Stack<>();
for(int i = 0; i < pfix.length(); i++){
char curr = pfix.charAt(i);
if(curr == ' '){
continue;
}
else if(Character.isDigit(curr)){
int num = 0;
while(Character.isDigit(curr)){
num = num*10 + (int)(curr-'0');
i++;
if (i==pfix.length()){break;}
curr = pfix.charAt(i);
}
i--;
stack.push(num);
//include variables and be able to insert them into here
}
else{
int val1 = stack.pop();
int val2 = stack.pop();
switch(curr){
case '+':
stack.push(val2+val1);
break;
case '-':
stack.push(val2-val1);
break;
case '/':
stack.push(val2/val1);
break;
case '%':
stack.push(val2%val1);
break;
case '*':
stack.push(val2*val1);
break;
}
}
}
return stack.pop();
}
}
Read:
import java.util.*;
public class Read {
ArrayList<Variable> vars = new ArrayList<Variable>();//FIX THIS SHIT AHHHHHHHHH
Variable tempvar = new Variable();
Work eval = new Work();
private int lnNum = 1;
private String arg="";
public void thing() {
String thing,thing2;
if (arg.contains("print")){
String real="";
int i = arg.indexOf('t');
if (i!=4){}//error
thing = arg.substring(0,i);
if (thing!="print"){}//error
thing2 = arg.substring(i+2,arg.length());
real = eval.infixConverter(thing2);
System.out.println(real);
}
else if (arg.contains("read")){
Scanner in = new Scanner(System.in);
int i = arg.indexOf('d');
if (i!=3){}//error
thing = arg.substring(0,i+1);
if (thing!="read"){}//error
thing2 = arg.substring(i+2,arg.length());
char c2 = thing2.charAt(0);
if (thing2.length()>1){}//error
System.out.println("Enter a value for "+thing2+": ");
String vv = in.nextLine();
vv = eval.infixConverter(vv);
int vvv = Integer.parseInt(vv);
tempvar.setValue(c2, vvv);
vars.add(tempvar);
}
else if (arg.contains("=")){
int i = arg.indexOf('=');
int tempval;
thing = arg.substring(0,i-1);
thing2 = arg.substring(i+2,arg.length());
if(thing.length()>1){}//error
thing2=eval.infixConverter(thing2);
char c = thing.charAt(0);
if (vars.contains(thing)){
tempval = Integer.parseInt(thing2);
tempvar.setValue(c,tempval);
int f = vars.indexOf(thing);
}
else if(Character.isLetter(c)){
tempval = Integer.parseInt(thing2);
tempvar.setValue(c,tempval);
vars.add(tempvar);
}
else{
//error
}
}
else{
}
}
boolean varExists(char c){
for (int i = 0; i<vars.size(); i++){
tempvar = vars.get(i);
if (tempvar.getTitle()==c){
return true;
}
}
return false;
}
int getIndex(char c) {
for (int i = 0; i <= vars.size(); i++) {
tempvar = vars.get(i);
if (tempvar.getTitle() == c) {
return i;
}
}
return -1;
}
int inLineNum(){
lnNum++;
return lnNum;
}
void setArg(String c){
arg=c;
}
}
So I was assigned to create an method which takes in a string in infix notation as a parameter and returns a string in postfix notation.
My code seems to work for most examples I throw at it, but a few inputs cause wacky results.
public class Operations<T> {
public int value(char c){
switch(c){
case '(':
case ')':
return 3;
case '*':
case '/':
case '%':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}
public String infixToPostfix(String infix){
//Operator stack
myStack<Character> ops = new myStack<Character>();
//Postfix string
String postfix = "";
//Current char being read
char c;
//Marks if paranthesis are being passed in
boolean flag = false;
//Iterate through each character to find operators
for(int i=0; i<infix.length(); i++){
c = infix.charAt(i);
//Add operand to postfix and operator to stack
if(value(c)==0){
postfix+=c;
} else if(ops.isEmpty() || (value(c)>value(ops.getTop()) && c!=')') || c=='(') {
ops.push(c);
} else if(value(c)<value(ops.getTop()) && c!=')') {
if(ops.getTop()=='(' || flag) {
ops.push(c);
flag = true;
} else {
postfix+=ops.pop();
while(!ops.isEmpty() && value(c)<value(ops.getTop())) {
postfix+=ops.pop();
}
ops.push(c);
}
} else if(c==')') {
while(ops.getTop()!='('){
postfix+=ops.pop();
}
ops.pop();
flag = false;
} else {
postfix+=ops.pop();
ops.push(c);
}
}
while(!ops.isEmpty()){
postfix+=ops.pop();
}
return postfix;
}
}
for example, the equation:
- A * B + (C/D*7) – ( (A%C-8) / (H+F-D))
outputs:
ABCD/7+AC8-%HF+D-/-
while the correct answer is:
ABCD/7+AC%8-HF+D-/
What is causing the problem? Thanks
This question already has answers here:
How to convert a char array back to a string?
(14 answers)
Closed 9 years ago.
i am doing a porter stemmer.....the code gives me output in char array....but i need to convert that into string to proceed with futher work.....in the code i have given 2 words "looking" and "walks"....that is returned as look and walk(but in char array)...the output is printed in stem() function
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package file;
import java.util.Vector;
/**
*
* #author sky
*/
public class stemmer {
public static String line1;
private char[] b;
private int i, /* offset into b */
i_end, /* offset to end of stemmed word */
j, k;
private static final int INC = 50;
/* unit of size whereby b is increased */
public stemmer()
{
//b = new char[INC];
i = 0;
i_end = 0;
}
/**
* Add a character to the word being stemmed. When you are finished
* adding characters, you can call stem(void) to stem the word.
*/
public void add(char ch)
{
System.out.println("in add() function");
if (i == b.length)
{
char[] new_b = new char[i+INC];
for (int c = 0; c < i; c++)
new_b[c] = b[c];
b = new_b;
}
b[i++] = ch;
}
/** Adds wLen characters to the word being stemmed contained in a portion
* of a char[] array. This is like repeated calls of add(char ch), but
* faster.
*/
public void add(char[] w, int wLen)
{ if (i+wLen >= b.length)
{
char[] new_b = new char[i+wLen+INC];
for (int c = 0; c < i; c++)
new_b[c] = b[c];
b = new_b;
}
for (int c = 0; c < wLen; c++)
b[i++] = w[c];
}
public void addstring(String s1)
{
b=new char[s1.length()];
for(int k=0;k<s1.length();k++)
{
b[k] = s1.charAt(k);
System.out.println(b[k]);
}
i=s1.length();
}
/**
* After a word has been stemmed, it can be retrieved by toString(),
* or a reference to the internal buffer can be retrieved by getResultBuffer
* and getResultLength (which is generally more efficient.)
*/
public String toString() { return new String(b,0,i_end); }
/**
* Returns the length of the word resulting from the stemming process.
*/
public int getResultLength() { return i_end; }
/**
* Returns a reference to a character buffer containing the results of
* the stemming process. You also need to consult getResultLength()
* to determine the length of the result.
*/
public char[] getResultBuffer() { return b; }
/* cons(i) is true <=> b[i] is a consonant. */
private final boolean cons(int i)
{ switch (b[i])
{ case 'a': case 'e': case 'i': case 'o': case 'u': return false;
case 'y': return (i==0) ? true : !cons(i-1);
default: return true;
}
}
/* m() measures the number of consonant sequences between 0 and j. if c is
a consonant sequence and v a vowel sequence, and <..> indicates arbitrary
presence,
<c><v> gives 0
<c>vc<v> gives 1
<c>vcvc<v> gives 2
<c>vcvcvc<v> gives 3
....
*/
private final int m()
{ int n = 0;
int i = 0;
while(true)
{ if (i > j) return n;
if (! cons(i)) break; i++;
}
i++;
while(true)
{ while(true)
{ if (i > j) return n;
if (cons(i)) break;
i++;
}
i++;
n++;
while(true)
{ if (i > j) return n;
if (! cons(i)) break;
i++;
}
i++;
}
}
/* vowelinstem() is true <=> 0,...j contains a vowel */
private final boolean vowelinstem()
{ int i; for (i = 0; i <= j; i++) if (! cons(i)) return true;
return false;
}
/* doublec(j) is true <=> j,(j-1) contain a double consonant. */
private final boolean doublec(int j)
{ if (j < 1) return false;
if (b[j] != b[j-1]) return false;
return cons(j);
}
/* cvc(i) is true <=> i-2,i-1,i has the form consonant - vowel - consonant
and also if the second c is not w,x or y. this is used when trying to
restore an e at the end of a short word. e.g.
cav(e), lov(e), hop(e), crim(e), but
snow, box, tray.
*/
private final boolean cvc(int i)
{ if (i < 2 || !cons(i) || cons(i-1) || !cons(i-2)) return false;
{ int ch = b[i];
if (ch == 'w' || ch == 'x' || ch == 'y') return false;
}
return true;
}
private final boolean ends(String s)
{
int l = s.length();
int o = k-l+1;
if (o < 0)
return false;
for (int i = 0; i < l; i++)
if (b[o+i] != s.charAt(i))
return false;
j = k-l;
return true;
}
/* setto(s) sets (j+1),...k to the characters in the string s, readjusting
k. */
private final void setto(String s)
{ int l = s.length();
int o = j+1;
for (int i = 0; i < l; i++)
b[o+i] = s.charAt(i);
k = j+l;
}
/* r(s) is used further down. */
private final void r(String s) { if (m() > 0) setto(s); }
/* step1() gets rid of plurals and -ed or -ing. e.g.
caresses -> caress
ponies -> poni
ties -> ti
caress -> caress
cats -> cat
feed -> feed
agreed -> agree
disabled -> disable
matting -> mat
mating -> mate
meeting -> meet
milling -> mill
messing -> mess
meetings -> meet
*/
private final void step1()
{
if (b[k] == 's')
{ if (ends("sses")) k -= 2; else
if (ends("ies")) setto("i"); else
if (b[k-1] != 's') k--;
}
if (ends("eed")) { if (m() > 0) k--; } else
if ((ends("ed") || ends("ing")) && vowelinstem())
{ k = j;
if (ends("at")) setto("ate"); else
if (ends("bl")) setto("ble"); else
if (ends("iz")) setto("ize"); else
if (doublec(k))
{ k--;
{ int ch = b[k];
if (ch == 'l' || ch == 's' || ch == 'z') k++;
}
}
else if (m() == 1 && cvc(k)) setto("e");
}
}
/* step2() turns terminal y to i when there is another vowel in the stem. */
private final void step2() { if (ends("y") && vowelinstem()) b[k] = 'i'; }
/* step3() maps double suffices to single ones. so -ization ( = -ize plus
-ation) maps to -ize etc. note that the string before the suffix must give
m() > 0. */
private final void step3() { if (k == 0) return; /* For Bug 1 */ switch (b[k-1])
{
case 'a': if (ends("ational")) { r("ate"); break; }
if (ends("tional")) { r("tion"); break; }
break;
case 'c': if (ends("enci")) { r("ence"); break; }
if (ends("anci")) { r("ance"); break; }
break;
case 'e': if (ends("izer")) { r("ize"); break; }
break;
case 'l': if (ends("bli")) { r("ble"); break; }
if (ends("alli")) { r("al"); break; }
if (ends("entli")) { r("ent"); break; }
if (ends("eli")) { r("e"); break; }
if (ends("ousli")) { r("ous"); break; }
break;
case 'o': if (ends("ization")) { r("ize"); break; }
if (ends("ation")) { r("ate"); break; }
if (ends("ator")) { r("ate"); break; }
break;
case 's': if (ends("alism")) { r("al"); break; }
if (ends("iveness")) { r("ive"); break; }
if (ends("fulness")) { r("ful"); break; }
if (ends("ousness")) { r("ous"); break; }
break;
case 't': if (ends("aliti")) { r("al"); break; }
if (ends("iviti")) { r("ive"); break; }
if (ends("biliti")) { r("ble"); break; }
break;
case 'g': if (ends("logi")) { r("log"); break; }
} }
/* step4() deals with -ic-, -full, -ness etc. similar strategy to step3. */
private final void step4() { switch (b[k])
{
case 'e': if (ends("icate")) { r("ic"); break; }
if (ends("ative")) { r(""); break; }
if (ends("alize")) { r("al"); break; }
break;
case 'i': if (ends("iciti")) { r("ic"); break; }
break;
case 'l': if (ends("ical")) { r("ic"); break; }
if (ends("ful")) { r(""); break; }
break;
case 's': if (ends("ness")) { r(""); break; }
break;
} }
/* step5() takes off -ant, -ence etc., in context <c>vcvc<v>. */
private final void step5()
{ if (k == 0) return; /* for Bug 1 */ switch (b[k-1])
{ case 'a': if (ends("al")) break; return;
case 'c': if (ends("ance")) break;
if (ends("ence")) break; return;
case 'e': if (ends("er")) break; return;
case 'i': if (ends("ic")) break; return;
case 'l': if (ends("able")) break;
if (ends("ible")) break; return;
case 'n': if (ends("ant")) break;
if (ends("ement")) break;
if (ends("ment")) break;
/* element etc. not stripped before the m */
if (ends("ent")) break; return;
case 'o': if (ends("ion") && j >= 0 && (b[j] == 's' || b[j] == 't')) break;
/* j >= 0 fixes Bug 2 */
if (ends("ou")) break; return;
/* takes care of -ous */
case 's': if (ends("ism")) break; return;
case 't': if (ends("ate")) break;
if (ends("iti")) break; return;
case 'u': if (ends("ous")) break; return;
case 'v': if (ends("ive")) break; return;
case 'z': if (ends("ize")) break; return;
default: return;
}
if (m() > 1) k = j;
}
/* step6() removes a final -e if m() > 1. */
private final void step6()
{ j = k;
if (b[k] == 'e')
{ int a = m();
if (a > 1 || a == 1 && !cvc(k-1)) k--;
}
if (b[k] == 'l' && doublec(k) && m() > 1) k--;
}
/** Stem the word placed into the Stemmer buffer through calls to add().
* Returns true if the stemming process resulted in a word different
* from the input. You can retrieve the result with
* getResultLength()/getResultBuffer() or toString().
*/
public void stem()
{
// step1();
// System.out.println("hello in stem");
// step2();
// step3();
// step4();
// step5();
// step6();
//
// i_end = k+1;
// i = 0;
System.out.println(i);
k = i - 1;
if (k > 1)
{
step1();
step2();
step3();
step4();
step5();
step6();
}
for(int c=0;c<=k;c++)
System.out.println(b[c]);
i_end = k+1; i = 0;
}
public static void main(String[] args)
{
stemmer s = new stemmer();
s.addstring("looking");
s.stem();
s.addstring("walks");
s.stem();
//System.out.println("Output " +s.b);
}
}
- Use Character class method toString();
Eg:
class Test
{
public static void main (String[] args) throws java.lang.Exception
{
char c = 'a';
String s = Character.toString(c);
System.out.println(s);
}
}
- Now use this above explained method to convert all the character array items into String.
char[] data = new char[10];
String text = String.valueOf(data);
to convert a char[] to string use this way
String x=new String(char[])
example
char x[]={'a','m'};
String z=new String(x);
System.out.println(z);
output
am
char[] a = new char[10];
for(int i=0;i<10;i++)
{
a[i] = 's';
}
System.out.println(new String(a));
or
System.out.println(String.copyValueOf(a));
Can you explain how can I Add?
My Infix is: 1^2+3/3
Prefix expression is: +1^2/33 (which is wrong)
Postfix expression is: 1^233/+ (which is wrong)
the Prefix will be: +^12/33
and the Postfix will be: 12^33/+
My Code:
import java.io.*;
class Stack
{
private char[] a;
private int top,m;
public Stack(int max)
{
m=max;
a=new char[m];
top=-1;
}
public void push(char key)
{
a[++top]=key;
}
public char pop()
{
return(a[top--]);
}
public char peek()
{
return(a[top]);
}
public boolean isEmpty()
{
return (top==-1);
}
}
class Evaluation
{
private Stack s;
private String input;
private String output="";
public Evaluation(String str)
{
input=str;
s=new Stack(str.length());
}
public String inToPre()
{
for(int i=input.length()-1;i>=0;i--)
{
char ch=input.charAt(i);
**switch(ch)
{
case '+':
case '-':gotOperator(ch,1,')');
break;
case '*':
case '/':gotOperator(ch,2,')');
break;
case ')':s.push(ch);
break;
case '(':gotParenthesis(')');
break;
default:output=ch+output;
}
}
while(!s.isEmpty())
output=s.pop()+output;
return output;
} // End to inToPre
public String inToPost()
{
for(int i=0;i<input.length();i++)
{
char ch=input.charAt(i);
switch(ch)
{
case '+':
case '-':gotOperator(ch,1,'(');
break;
case '*':
case '/':gotOperator(ch,2,'(');
break;
case '(':s.push(ch);
break;
case ')':gotParenthesis('(');
break;
default:output=output+ch;
}
}
while(!s.isEmpty())
output=output+s.pop();
return output;
} // End inToPost**
private void gotOperator(char opThis,int prec1,char x)
{
while(!s.isEmpty())
{
char opTop=s.pop();
if(opTop==x)
{
s.push(opTop);
break;
}
else
{
int prec2;
if(opTop=='+'||opTop=='-')
prec2=1;
else
prec2=2;
if(prec2<prec1&&x=='(')
{
s.push(opTop);
break;
}
else if(prec2<=prec1&&x==')')
{
s.push(opTop);
break;
}
else
{
if(x==')')
output=opTop+output;
else
output=output+opTop;
}
}
} // End While gotOperator
s.push(opThis);
} // End gotOperator
private void gotParenthesis(char x)
{
while(!s.isEmpty())
{
char ch=s.pop();
if(ch==x)
break;
else
{
if(x==')')
output=ch+output;
else
output=output+ch;
} // End Else
} // End While gotParenthesis
} // End gotParenthesis
} // End Class Evaluation
Just looking at your code quickly I can see that in the InFix analysis you are not considering a new level for the ^ operator.
The groups should be +-, */, ^. Since the ^ has higher priority.
Regards