I am working on a program that converts a prefix to a postfix expression. However, when there is an unexpected blank space in an expression such as "$+-ABC+D-E F" instead of "$+-ABC+D-EF" the program doesn't work correctly. How do I write skip to the next character and ignore the whitespace, trying to do it through an if else statement using a boolean isBlank method.
public class PrefixConverter{
// Checks if character is an operator
public boolean isOperator(char c){
switch (c){
case '+':
case '-':
case'*':
case'/':
case'$':
return true;
}
return false;
}
// Ignores white space
public boolean isBlank(char c){
switch (c){
case ' ':
return true;
}
return false;
}
// Method to convert Prefix expression to Postfix expression
public String preToPost (String prefix_exp){
// Create a new stack with length of the prefix string
int size = prefix_exp.length();
Stack expression_stack = new Stack (size);
// Read expression from right to left
for (int i = size -1; i >=0 ; i-- ){
if (isOperator(prefix_exp.charAt(i))){
// Pop two operands from the stack
String op1 = expression_stack.peek();
expression_stack.pop();
String op2 = expression_stack.peek();
expression_stack.pop();
// Concatenate the operands and the operator
String temp = op1 + op2 + prefix_exp.charAt(i);
// Push the result back onto the stack
expression_stack.push(temp);
}
else if(isBlank(prefix_exp.charAt(i))){
// Skip to next character
}
// If the symbol is an operand
else {
// Push the operand onto the stack
expression_stack.push(prefix_exp.charAt(i) + "");
}
}
return expression_stack.peek();
}
}
One way would be to write a continue; in this else if():
else if(isBlank(prefix_exp.charAt(i))){
// Skip to next character
continue;
}
continue will simply move to the next iteration of the loop
However, if you do not need the spaces you can remove them from the prefix_exp String in the beginning by doing this:
prefix_exp = prefix_exp.replaceAll("\\s", "");
Just make sure you do the replaceAll before you call .length() of the String as the size changes.
Just use the continue statement to skip to the end of your for loop.
This will trigger the loop to run with the next character. But since the rest of your code is in if statements anyway, your code should behave well by just doing nothing.
...
else if(isBlank(prefix_exp.charAt(i))){
// Skip to next character
continue;
}
See also https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
Related
I have a task to write a return type method which takes String as an argument and returns boolean. If the String matches with the requirements it returns true else false.
So it should not have any space, and more then 1 '#'and format must be 2>chars#2>chars.2>chars so it should be xyz#xyz.com is true but if any part of it less then 3 it should return to false. I checked so many forums but all i can find regex and we didn't learn anything about it. I could able to do this much but i just couldn't figure out how can i specifically set length of each part and set it as true or false. I'm missing so many and this is all i able to complete;
public static boolean emailAddress(String str) {
if (str.contains(" "))
return false;
boolean flag = true;
if(str3.length()> 11)
for (int i = 0; i < str3.length(); i++) {
for (int j = i + 1; j < str3.length(); j++) {
if (str3.charAt(i) == str3.charAt(j)) {
flag = false;
break;
}
}
if(flag)
return true;
}
return false;
}
This is how I would approach it:
public static boolean isEmailAddress(String str)
{
if(str.trim().equals("")) // Checking if it is an empty string
{
return false;
}
boolean flag = true;
int atIndex = str.indexOf("#"); // Get the index of #
if (atIndex == -1)
{
return false;
}
// Slice your email str and get only the characters before the #
// Check whether the length and the characters are as you want them.
// Do the same thing about the string between # and .
// and then do the same thing about the sliced string after .
}
Check substring() and indexOf().
For anyone who needs it.
This should be one of the Regex to match your requirement:
[a-zA-Z_0-9]{2,}#[a-zA-Z_0-9]{2,}\.[a-zA-Z_0-9]{2,}
[a-zA-Z_0-9] it requires one of the characters, from a-z,A-Z or 0-9
{2,} it requires two or more from one of the characters inside.
A few hints instead of complete solution:
Check if the input string...
has # and . (there could be two or three period's as some domain uses .co.in)
does not have any white spaces (' ')
does not start with special characters ('#', '^')
If possible, do not check for length of each part, as sometimes .in also valid domain.
I have a string like:
If ({{SQL}}.Employee.Title starts with 'Production')
and (substring of {{SQL}}.Employee.Title from '27' for '2' is not '30')
and ({{SQL}}.Employee.HireDate is greater than or equal to '2000-01-01 00:00:00.000')
then Pull {{SQL}}.Title, {{SQL}}.HireDate from Employee
From this expression, I want to find out whether round brackets are properly balanced or not in Java language.
One way is to create a counter variable which will be incremented as soon as I find out the opening bracket and decrement it when closing bracket is encountered. Based on the result, I can decide the result.
But this is not going to help for string like () i.e. not having any alpha numeric character between brackets.
Is there any way in which I can determine whether round brackets are balanced and there should be alpha numeric characters between these brackets.
In case brackets are empty i.e. no character between opening and closing brackets, it should throw an error.
You'll need a code similar to below one. It does use a Stack to track the number of opened/closed parantheses + remembers what was the last char occurence in order to track empty parantheses:
String test = "{TEST}(A){";
Stack<Integer> stack = new Stack<>();
boolean lastCharIsParantheses = false;
for (char c : test.toCharArray()) {
switch (c) {
case '{':
case '(': {
stack.push(1);
lastCharIsParantheses = true;
continue;
}
case '}':
case ')':
stack.pop();
if (lastCharIsParantheses) {
throw new RuntimeException("Empty parantheses");
}
}
lastCharIsParantheses = false;
}
if (!stack.empty()) {
throw new RuntimeException("Not matching number of opened/closed parantheses");
}
I've appropriated and modified the below code which does a pretty good job of tokenizing Java code using Java's StreamTokenizer. Its number handling is problematic, though:
it turns all integers into doubles. I can get past that by testing num % 1 == 0, but this feels like a hack
More critically, a . following whitespace is treated as a number. "Class .method()" is legal Java syntax, but the resulting tokens are [Word "Class"], [Whitespace " "], [Number 0.0], [Word "method"], [Symbol "("], and [Symbol ")"]
I'd be happy turning off StreamTokenizer's number parsing entirely and parsing the numbers myself from word tokens, but commenting st.parseNumbers() seems to have no effect.
public class JavaTokenizer {
private String code;
private List<Token> tokens;
public JavaTokenizer(String c) {
code = c;
tokens = new ArrayList<>();
}
public void tokenize() {
try {
// Create the tokenizer
StringReader sr = new StringReader(code);
StreamTokenizer st = new StreamTokenizer(sr);
// Java-style tokenizing rules
st.parseNumbers();
st.wordChars('_', '_');
st.eolIsSignificant(false);
// Don't want whitespace tokens
//st.ordinaryChars(0, ' ');
// Strip out comments
st.slashSlashComments(true);
st.slashStarComments(true);
// Parse the file
int token;
do {
token = st.nextToken();
switch (token) {
case StreamTokenizer.TT_NUMBER:
// A number was found; the value is in nval
double num = st.nval;
if(num % 1 == 0)
tokens.add(new IntegerToken((int)num);
else
tokens.add(new FPNumberToken(num));
break;
case StreamTokenizer.TT_WORD:
// A word was found; the value is in sval
String word = st.sval;
tokens.add(new WordToken(word));
break;
case '"':
// A double-quoted string was found; sval contains the contents
String dquoteVal = st.sval;
tokens.add(new DoubleQuotedStringToken(dquoteVal));
break;
case '\'':
// A single-quoted string was found; sval contains the contents
String squoteVal = st.sval;
tokens.add(new SingleQuotedStringToken(squoteVal));
break;
case StreamTokenizer.TT_EOL:
// End of line character found
tokens.add(new EOLToken());
break;
case StreamTokenizer.TT_EOF:
// End of file has been reached
tokens. add(new EOFToken());
break;
default:
// A regular character was found; the value is the token itself
char ch = (char) st.ttype;
if(Character.isWhitespace(ch))
tokens.add(new WhitespaceToken(ch));
else
tokens.add(new SymbolToken(ch));
break;
}
} while (token != StreamTokenizer.TT_EOF);
sr.close();
} catch (IOException e) {
}
}
public List<Token> getTokens() {
return tokens;
}
}
parseNumbers() in "on" by default. Use resetSyntax() to turn off number parsing and all other predefined character types, then enable what you need.
That said, manual number parsing might get tricky with accounting for dots and exponents... With a scanner and regular expressions it should be relatively straightforward to implement your own tokenizer, tailored exactly to your needs. For an example, you may want to take a look at the Tokenizer inner class here: https://github.com/stefanhaustein/expressionparser/blob/master/core/src/main/java/org/kobjects/expressionparser/ExpressionParser.java (about 120 LOC at the end)
I'll look into parboiled when I have a chance. In the meantime, the disgusting workaround I implemented to get it working is:
private static final String DANGLING_PERIOD_TOKEN = "___DANGLING_PERIOD_TOKEN___";
Then in tokenize()
//a period following whitespace, not followed by a digit is a "dangling period"
code = code.replaceAll("(?<=\\s)\\.(?![0-9])", " "+DANGLING_PERIOD_TOKEN+" ");
And in the tokenization loop
case StreamTokenizer.TT_WORD:
// A word was found; the value is in sval
String word = st.sval;
if(word.equals(DANGLING_PERIOD_TOKEN))
tokens.add(new SymbolToken('.'));
else
tokens.add(new WordToken(word));
break;
This solution is specific to my needs of not caring what the original whitespace was (as it adds some around the inserted "token")
the code checks if delimiters are balanced in the string or not. I've been using a stack to solve this. I traverse the string to the end, whenever an opening delimiter is encountered I push it into the stack, for each closing delimiter encountered I make a check if the stack is empty (and report error if it is) and then pop the stack to match the popped character and the closing delimiter encountered. I ignore all other characters in the string.
At the end of the traversal I make a check if the stack is empty (that is I check if all the opening delimiters were balanced out or not). If it's not empty, I report an error.
Although I have cross checked many times the code seems to be reporting every string as invaalid(i.e with unbalanced delimiters). Here's the code:
import java.util.*;
public class delimiter {
public static void main(String args[]){
String s1 = "()";
String s2 = "[}[]";
if(delimitercheck(s1)){
System.out.println("s1 is a nice text!");
}
else
System.out.println("S1 is not nice");
if(delimitercheck(s2)){
System.out.println("s2 is a nice text!");
}
else
System.out.println("S2 is not nice");
}
public static boolean delimitercheck(String s){
Stack<Character> stk = new Stack<Character>();
if(s==null||s.length()==0)//if it's a null string return true
return true;
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='('||s.charAt(i)=='{'||s.charAt(i)=='['){
stk.push(s.charAt(i));
}
if(s.charAt(i)==')'||s.charAt(i)=='}'||s.charAt(i)==']'){
if(stk.isEmpty()){
return false;
}
if(stk.peek()==s.charAt(i)){
stk.pop();
}
}
}
if(stk.isEmpty()){
return true;
}
else
return false;
}
}
Can anyone point to me where am I going wrong?
Your error is here :
if(stk.peek()==s.charAt(i)){
stk.pop();
}
The i'th character shouldn't be equal to stk.peek(). It should be closing it. i.e. if stk.peek() == '{', s.charAt(i) should be '}', and so on.
In addition, if the current closing parenthesis doesn't match to top of the stack, you should return false.
You can either have a separate condition for each type of paretheses, or you can create a Map<Character,Character> that maps each opening parenthesis to its corresponding closing parenthesis, and then your condition will become :
if(map.get(stk.peek())==s.charAt(i)){
stk.pop();
} else {
return false;
}
where map can be initialized to :
Map<Character,Character> map = new HashMap<>();
map.put('(',')');
map.put('{','}');
map.put('[',']');
Yes, when encountering a closing bracket, you check if it is similar to the opening bracket which is not correct.
if(stk.peek()==s.charAt(i)){
stk.pop();
}
should be replaced with something similar to
Character toCheck = s.charAt(i);
Character peek = stk.peek();
if (toCheck == ')') {
if (peek == '(') {
stk.pop();
} else {
return false;
}
} else if ( // ... check all three bracket types
And please stick to brackets for every if-statement - there's nothing more tedious then one day encountering an error due to omitted brackets which will cause you more internal pain.
You are checking the stack value which has an opening delimiter with a closing delimiter. So for the first example you are checking '(' with ')'. Instead for every corresponding end delimiter you should check the stack for its starting delimiter i.e., '(' with ')'. Hope that makes sense.
I want to execute a loop as long as a certain condition applies. At the end, I want to return the value that was last being found inside the loop.
Non-realworld example:
teststring = " abcde";
String letter = null;
do {
letter = reader.read(); //reads the teststring char by char
} while (letter.equals(" "));
return letter; //return "a"
Could this be optimized from the coding point of view, eg transform it from a do-while loop to just a while-loop?
If you use Java 1.7 or 1.8, you can do this:
while((letter=reader.read()).equals(" ")){
}
return letter;
if you are reading from a Reader it returns an int which is the char or -1 if at the end of input.
int ch;
while((ch = reader.read()) == ' ');
return ch;
Note: " " is a String and ' ' is a char.
No sure about what is more efficient but you could do something like:
`return teststring.trim().charAt(0);
do {
...
} while (<condition>);
I am going to explain your question on do/while vs while alone.
The do is only a label. It has no impact on efficiency. The while at the bottom is effectively an if(condition) goto line #, where line # is the do. The "do" is simply a way of telling the compiler what number you want in that goto statement at the bottom.
Putting the while statement at the top would actually be less efficient because it means the condition has to be evaluated on the first iteration. Perhaps your reader does need to be checked on the first iteration, then it should be a while statement, but that requires more work, you see?
Second even transforming it to only a while statement, still places an unconditional goto at the bottom, with a conditional goto on the top, so even though it looks like less code, it could possibly be more.
I think it would be easier to just use String.toCharArray() and a For Each loop like
String teststring = " abcde";
for (char ch : teststring.toCharArray()) {
if (ch != ' ') return ch; // <-- 'a'
}
throw new ParseException("Whitespace only");
But, you could use a StringReader and you're using char (a primitive), so I think you've asked for
String teststring = " abcde";
StringReader reader = new StringReader(teststring);
try {
int letter;
do {
letter = reader.read();
} while (letter == ' ');
return ((char) letter);
} catch (IOException e) {
e.printStackTrace();
}
throw new ParseException("Whitespace only");
or return a default value if the character isn't found.