I am pretty sure, that stacks are used for building PRN and '(' are ignored, but it does not seem to be the case. For example:
input 1: 52+(1+2)*4-3
input 2: 52+((1+2)*4)-3
input 3: (52+1+2)*4-3
Input 1 and input 2 output should be the same, and input 1 and input 3 should differ.
output 1: 52 1 2 + 4 3 - * +
output 2: 52 1 2 + 4 * 3 - +
output 3: 52 1 2 + 4 3 - * +
public static String Infix2(String input) {
char[] in = input.toCharArray();
Stack<Character> stack = new Stack<Character>();
StringBuilder out = new StringBuilder();
for (int i = 0; i < in.length; i++)
switch (in[i]) {
case '+':
case '*':
case '-':
out.append(' ');
stack.push(in[i]);
break;
case ' ':
case '(':
break;
case ')':
out.append(' ');
out.append(stack.pop());
break;
default:
out.append(in[i]);
break;
}
while (!stack.isEmpty()) {
out.append(' ');
out.append(stack.pop());
}
return out.toString();
}
Assuming that i want input 1 and 3 also to work, what approach should i use?
edit:
After the changes '+','-','*' and '/' worked for given inputs.
public static String Infix2(String input) {
if (input == null)
return "";
char[] in = input.toCharArray();
Stack<Character> stack = new Stack<Character>();
StringBuilder out = new StringBuilder();
for (int i = 0; i < in.length; i++)
switch (in[i]) {
case '+':
case '-':
while (!stack.empty()
&& (stack.peek() == '*' || stack.peek() == '/'))
out.append(' ').append(stack.pop());
case '*':
case '/':
out.append(' ');
case '(':
stack.push(in[i]);
case ' ':
break;
case ')':
while (!stack.empty() && stack.peek() != '(')
out.append(' ').append(stack.pop());
if (!stack.empty())
stack.pop();
break;
default:
out.append(in[i]);
break;
}
while (!stack.isEmpty())
out.append(' ').append(stack.pop());
return out.toString();
}
The algorithm is pretty simple (and here is a good explanation). Every operation has a binding weight, with + and - being the lowest. There are two rules:
print out numbers immediately
never put a lighter item on a heavier item
left parentheses go on the stack
right parentheses pop off the stack until you hit a left parentheses, and then remove the left parentheses
Given your first example, 52+(1+2)*4-3, here is the stack:
52+ => +
52+( => + (
52+(1+ => + ( +
52+(1+2) => + //right parentheses popped +
52+(1+2)*4 => + *
52+(1+2)*4-3 => + - //can't put - on top of *, so pop off *
... and then pop the stack until it's empty.
Replacing your switch loop with the following (closest analog to what you had) will give correct answers for your three examples. In a real parser you would give each operator a weight and generalize the pop mechanism.
for (int i = 0; i < in.length; i++)
switch (in[i]) {
case '+':
case '-':
while (!stack.empty() && (stack.peek() == '*' || stack.peek() == '/')) {
out.append(' ');
out.append(stack.pop());
}
out.append(' ');
stack.push(in[i]);
break;
case '*':
case '/':
out.append(' ');
stack.push(in[i]);
break;
case '(':
stack.push(in[i]);
break;
case ')':
while (!stack.empty() && stack.peek() != '(') {
out.append(' ');
out.append(stack.pop());
}
stack.pop();
break;
default:
out.append(in[i]);
break;
}
Not an exact answer to the specific question but something I'd recommend for developing these kinds of algorithms: have a look at test driven devlopment (TDD). In brief: write a couple of unit tests - for example with JUnit - for the infix2 method, where you feed the method with test patterns (expressions) and test, if infix2 produces the right output.
Start with easy ones, like
assertequals("1", "1"); // positive number
assertequals("-1", "-1"); // negative number
assertequals("1+1", "1 1 +"); // simple addition
assertequals(" 1 + 1 ", "1 1 +"); // simple addition with whitechars
assertequals(" 1 + +1 ", "1 -1 +"); // simple addition with pos. number & whitechars
assertequals(" 1 + -1 ", "1 -1 +"); // simple addition with neg. number & whitechars
assertequals("(1+1)", "1 1 +"); // simple addition with brackets
and don't forget illegal expressions like
String[] illegalExpressions = {null, "", " ", "1 +", "1 + 1)"};
The test cases for you examples should be
assertequals("52+(1+2)*4-3", "52 1 2 + 4 * 3 -");
assertequals("52+((1+2)*4)-3", "52 1 2 + 4 * 3 -");
assertequals("(52+1+2)*4-3", "52 1 + 2 + 4 * 3 -");
Related
I am learning compiler construction these days, and I am having trouble while making the code for comment in it.
What is actually happening is that when ever I am writing a string in the notepad file such as Hello //World. Then it is printing "/" this div operator which I don't want. What actually I want is that Hello should be printed in the output and World should get commented. I know I have included the code for div operator but it is also necessary to include. Just wanted to know how I can achieve this comment logic while checking the logic for checking the div operator should also be there.
Here is the code!
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class main {
public static void main(String[] args) throws FileNotFoundException{
File newFile = new File("C:/temp/sourcecode.txt");
Scanner scanFile = new Scanner(newFile);
//Scanner scan = new Scanner(System.in);
char ch;
String str;
while(scanFile.hasNextLine()){
str = scanFile.nextLine();
int l = str.length();
if(!str.startsWith("//") && !str.startsWith("/*") && !str.endsWith("*/")) {
for(int i =0; i<l ; i++) {
ch = str.charAt(i);
System.out.println(ch);
if(ch == '*'){
System.out.println("The Operator is MUL");
System.out.println("arop\n");
}
if(ch == '/')
{
System.out.println("The Operator is DIV");
System.out.println("arop\n");
}
}
}
int OP = 0;
switch(OP){
case 0:
if(str.contains("<") && str.contains(">")){
System.out.println("The Operator is NE");
System.out.println("relop\n");
break;
}
case 1:
if(str.contains("<") && str.contains("=")){
System.out.println("The Operator is LE");
System.out.println("relop\n");
break;
}
case 2:
if(str.contains(">") && str.contains("=")){
System.out.println("The Operator is GE");
System.out.println("relop\n");
break;
}
case 3:
if(str.contains("<")){
System.out.println("The Operator is LT");
System.out.println("relop\n");
break;
}
case 4:
if(str.contains(">")){
System.out.println("The Operator is GT");
System.out.println("relop\n");
break;
}
case 5:
if(str.contains("==")){
System.out.println("The Operator is EQ");
System.out.println("relop\n");
break;
}
case 6:
if(str.contains("+")){
System.out.println("The Operator is ADD");
System.out.println("arop\n");
break;
}
case 7:
if(str.contains("-")){
System.out.println("The Operator is SUB");
System.out.println("arop\n");
break;
}
// case 8:
// if(str.contains("*")){
// System.out.println("The Operator is MUL");
// System.out.println("arop\n");
// break;
// }
// case 9:
// if(str.contains("/")){
// System.out.println("The Operator is DIV");
// System.out.println("arop\n");
// break;
// }
case 10:
if(str.contains("=")){
System.out.println("The Operator is ASN");
System.out.println("otop\n");
break;
}
case 11:
if(str.contains("'")){
System.out.println("The Operator is PRN");
System.out.println("otop\n");
break;
}
case 12:
if(str.contains(";")){
System.out.println("The Operator is LTRN");
System.out.println("otop\n");
break;
}
case 13:
if(str.contains("{")){
System.out.println("The Operator is LBRC");
System.out.println("otop\n");
break;
}
case 14:
if(str.contains("}")){
System.out.println("The Operator is RBRC");
System.out.println("otop\n");
break;
}
}
}
}
}
Thank you in advance!
When programming a compiler the different input words in your code are called tokens, and the phase of recognising the role of each token is called the lexical analysis phase.
When trying to recognise tokens usually what is used is regex which is a way of implementing a finite automata.
You can read about it in much more detail here:
https://en.wikipedia.org/wiki/Lexical_analysis
You should replace the usage of contains, and use a lexer, it's the name of the tool that does lexical analysis. It uses regexes because it's not just about / and //, there can be many different situations where your compiler will need to decide which token to choose.
Here's an example of a finite automate for recognising different tokens, notice that for each prefix there can be many options for possible tokens:
In Java you can use jflex which will generate lexer code with your tokens definitions.
When you find a /, you need to check the next character.
if (ch == '/') {
char nextCh = (i + 1 < l ? str.charAt(i + 1) : '\0');
if (nextCh == '/') {
System.out.println("The Operator is EndOfLineComment");
System.out.println("arop\n");
i++;
} else if (nextCh == '*') {
System.out.println("The Operator is TraditionalComment");
System.out.println("arop\n");
i++;
} else {
System.out.println("The Operator is DIV");
System.out.println("arop\n");
}
}
I want to make the code use the stack class (stack of integers), together with a driver program which can handle the operations: 'm' unary minus -- negate the top item, 'r' exchange the top two items, 'd' duplicate top item on the stack, 'p' print (to the screen) the top item, n print and remove the top item, f print all the contents of the stack (leaving it intact), c clear the stack, 'q' quit, 'h' (or ?) print a help message.
import java.util.Scanner;
public class CalculatorDemo {
public static void main(String[] args)
{
String expression;
int result;
Scanner in = new Scanner(System.in);
do
{
calculator evaluator = new calculator();
System.out.println("Enter a valid post-fix expression one token " +
"at a time with a space between each token (e.g. 5 4 + 3 2 1 - + *)");
System.out.println("Each token must be an integer or an operator (+,-,*,/,%)for help(h/?)");
expression = in.nextLine();
result = evaluator.evaluate(expression);
System.out.println();
System.out.println(result);
}
while (result = 'q');
System.exit(0);
}
}
import java.util.*;
public class calculator
{
private Stack<Integer> stack;
public calculator()
{
stack = new Stack<Integer>();
}
public int evaluate(String expr)
{
int op1, op2, result = 0, help;
String key;
Scanner parser = new Scanner(expr);
while (parser.hasNext())
{
key = parser.next();
if (isOperator(key))
{
op2 = (stack.pop()).intValue();
op1 = (stack.pop()).intValue();
result = evaluateSingleOperator(key.charAt(0), op1, op2);
stack.push (new Integer(result));
}
else
stack.push(new Integer(Integer.parseInt(key)));
}
return result;
}
private boolean isOperator(String key)
{
return ( key.equals("+") || key.equals("-") ||
key.equals("*") || key.equals("/") ||
key.equals("h") || key.equals("?") ||
key.equals("p") || key.equals("n") ||
key.equals("d") || key.equals("r") ||
key.equals("c") || key.equals("f") ||
key.equals("%") || key.equals("m") ||
key.equals("q") );
}
private int evaluateSingleOperator(char operation, int op1, int op2)
{
int result = 0;
switch (operation)
{
case '+':
result = op1 + op2;
break;
case '-':
result = op1 - op2;
break;
case '*':
result = op1 * op2;
break;
case '/':
result = op1 / op2;
break;
case 'p':
result = op2;
break;
case '%':
result = op1 % op2;
break;
case 'm':
result = --op1;
break;
case'q':
result = (0);
break;
case'h'|'?':
int help = 0;
result = help;
break;
case 'r':
result = op1 ;//help
break;
case 'd':
result = op1;//help
break;
case 'n':
result = op1;//help
break;
case 'f':
result = op1;//help
break;
case 'c':
result = op1;//help
break;
}
return result;
}
private void help(String string) {
// TODO Auto-generated method stub
System.out.println("+ add the top two items" +
"* multiply the top two items" +
"- subtract the top item from the next item" +
"/ integer divide the second item by the top item" +
"% find the integer remainder when dividing the second item by the top item" +
"m unary minus -- negate the top item" +
"r exchange the top two items" +
"d duplicate top item on stack" +
"p print (to the screen) the top item" +
"n print and remove the top item" +
"f print all the contents of the stack (leaving it intact)" +
"c clear the stack" +
"q quit" +
"h (or ?) print a help message");
}
}
I am trying to make a program that finds a 'profane' word (which is 'cat' in this case) and say how many times it comes up in my input, and it works, except that it will count that profane word when it is embedded in a another word like 'conCATination'. Why is this the case? How can I get it to just count it when the word is by itself?
Edit: I forgot to mention it has to be done using if-else statements as well as using a loop Here is my program so far:
private static Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) {
String sentence = "";
String word1 = "cat";
int indexofSW1 = 0;
int currentlocation = 0;
int sentenceLength = 0;
int word1Count = 0;
int word1Length;
System.out.println("Please enter a sentence.");
sentence = keyboard.nextLine().toLowerCase().trim();
word1Length = word1.length();
indexofSW1 = sentence.indexOf(word1 , indexofSW1);
sentenceLength = sentence.length();
char character1;
if (indexofSW1 >= 0)
do { if (sentenceLength > indexofSW1 + word1Length)
{
character1 = sentence.charAt(indexofSW1 + word1Length);
switch (character1) {
case ' ':
case '\'':
case '\t':
case '\"':
case '.':
case '?':
case '<':
case '>':
case ',':
case '[':
case ']':
case '{':
case '}':
case '(':
case ')':
case '-':
case '_':
case '\\':
case '|':
case '+':
case '=':
case '/':
case '*':
case '&':
case '^':
case '%':
case '$':
case '#':
case '#':
case '!':
}
currentlocation = sentence.indexOf(word1, currentlocation);
}
if (currentlocation == 0 || currentlocation > 0)
{
currentlocation += word1Length;
word1Count++;
}
}while(currentlocation > -1 && currentlocation > sentenceLength);
System.out.printf("You have profane word %s %d times in your sentence." , word1 , word1Count);}}
You might want to consider using regex in this example, as it seems to be much better choice:
String source = "cat at the beginning, in the middle cat too, concatenating at the end cat.";
Pattern p = Pattern.compile("(?<=\\b)+(cat)(?=\\b)+"); // "cat" preceded by one or more whitespace characters or word boundary and followed by this too.
Matcher m = p.matcher(source); // Set matcher to match given pattern
int counter = 0; // to count occurences of "cat" int given String
while(m.find()) { // if match was found...
counter++; // increment counter
System.out.println(m.group(1) + " beginning from index: " + m.start(1)); // print match to the console
}
System.out.println("Number of occurences: " + counter); // print number of occurences of "cat"
Output that you get from this code:
cat beginning from index: 0
cat beginning from index: 36
cat beginning from index: 70
Number of occurences: 3
you can use pattern.matcher with regex
String cat = "cat concatination cat cat. cat";
Pattern pattern = Pattern.compile("cat | cat");
Matcher matcher = pattern.matcher(cat);
int count = 0;
while (matcher.find())
count++;
System.out.println(count); // prints 3
I have the following code:
String everything = sb.toString(); //stores all the data from the input file into a string
String replaceAll = everything.replaceAll("\\s", "");
int charCount = replaceAll.length(); //charCount is 147
char arr[] = replaceAll.toCharArray();
for (int i = 0; i < arr.length; i++) {
switch (arr[i]) {
case 'E': {
fridge[Character.getNumericValue(arr[(i + 1)])].is_empty();
}
break;
case 'F': {
fridge[Character.getNumericValue(arr[(i + 2)])].find_it(Character.getNumericValue(arr[(i + 1)]));
}
break;
case 'C': {
fridge[Character.getNumericValue(arr[(i + 3)])].combineFridge(fridge[Character.getNumericValue(arr[(i + 2)])], fridge[Character
.getNumericValue(arr[(i + 1)])]);
}
break;
case 'M': {
fridge[Character.getNumericValue(arr[(i + 3)])].commonItems(fridge[Character.getNumericValue(arr[(i + 2)])], fridge[Character
.getNumericValue(arr[(i + 1)])]);
}
break;
case 'I': {
fridge[Character.getNumericValue(arr[(i + 2)])].insertItem(Character.getNumericValue((i + 1)));
}
break;
case 'D': {
fridge[Character.getNumericValue(arr[(i + 2)])].delete_item(Character.getNumericValue((i + 1)));
}
break;
case 'O': {
fridge[Character.getNumericValue(arr[(i + 1)])].outputRefrigerator();
}
break;
}
}
The char array has 147 elements, and there's a number after each letter.
Each letter activates a method, followed by 1-3 parameters (numbers).
However, inside the for loop, I am getting a -1 value and sometimes random large numbers (all my numbers are positive and less than 12).
If I manually call any method outside the for loop for example:
fridge[Character.getNumericValue(arr[0].insertItem(Character.getNumericValue(arr[1]);, everything works fine and the value which is at arr[1] (which is 1) is stored at this.fridgeItems (an int[] array).
Why is this happening? I know it's a problem with either the switch statement or the for loop but I can't really tell.
Check your indices. In your code you are accessing elements from arr by i + 1 and i + 2 index. If your loop iterates more than n - 2 times, you will have IndexOutOfBoundException.
By the way, you need to increment i in your switch statement to skip "used" characters from the input array.
Your code is "not increment i correctly", because there is no code in the switch statement to actually increment i.
You should do something like this:
case 'C':
fridge[Character.getNumericValue(arr[i + 3])]
.combineFridge(fridge[Character.getNumericValue(arr[i + 2])],
fridge[Character.getNumericValue(arr[i + 1])]);
i += 3;
break;
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I'm having trouble getting this program to work, can someone take a look at it and give me a clue on what to do? Thanks!
Design and implement an application that reads a string from the user, then determines and prints how many of each lowercase vowel (a, e, i, o, and u) appear in the entire string . Have a separate counter for each vowel. Also count and print the number of nonvowel characters .
SPECIFICATION OF PROMPTS, LABELS AND OUTPUT : Your code should use the prompt "enter string : ". After the input is read, there are six lines of output , each starting with a different label: "a: ", "e: ", "i: ", "o: ", "u: ", "other: " in that order. After each label is the required count.
For example: if "aardvark heebie jeebies" were read in, the output would be:
a: 3
e: 6
i: 2
o: 0
u: 0
other: 12
import java.util.Scanner;
public class VowelAnalyst{
public static void main(String args []){
int a =0, e = 0, x = 0;
int u = 0, o = 0, other = 0;
String text;
Scanner scan = new Scanner(System.in);
System.out.print("enter string: ");
text = scan.nextLine();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c=='a')
a++;
else if( c=='e')
e++;
else if(c=='i')
x++;
else if(c=='o')
o++;
else if (c=='u')
u++;
else
other++;
}
System.out.println("a: " + a + "\n" +
"e: " + e + "\n" +
"i: " + x + "\n" +
"o: " + o + "\n" +
"u: " + u + "\n" +
"other: " + other);
}
}
Your code is correct except for this part:
else if (c != 'a' && 'e' && 'i' && 'o'&& 'u' )
It should be written like this:
else if (c != 'a' && c != 'e' && c != 'i' && c != 'o' && c != 'u')
You could make the code more clear by turning every if you have, except the first one, into an else if, and the last else if, where you check to see if the character isn't any of the vowels, can be simply an else:
if (c == 'a')
{
a++;
}
else if (c == 'e')
{
e++;
}
else if (c == 'i')
{
x++;
}
else if (c == 'o')
{
o++;
}
else if (c == 'u')
{
u++;
}
else
{
other++;
}
Your sequence of if statements is invalid. A meaningful rendition would be something like
if (c == 'a') a++;
else if (c == 'e') e++;
...
else other ++;
However, an even better choice would be to use a switch statement, like so
switch (c) {
case 'a':
a++;
break;
case 'e':
e++;
break;
case 'o':
o++;
break;
case 'u':
u++;
break;
default:
other++;
break;
}
After fixing that, we need look at what you're missing: all uppercase vowels are currently counted as other. We could double up on the conditionals
if (c == 'a' || c == 'A')
...
or
case 'A':
case 'a':
...
But there's an easier way: convert the string to lowercase before the comparison.
for (int i = 0; i < text.length(); i++) {
char c = Character.toLowerCase(text.charAt(i));
switch (c) {
...
I'll do for each char
switch (c)
{
case 'a':
case 'A':
a++;
break;
case 'e':
case 'E':
e++;
break;
case 'i':
case 'I':
i++;
break;
case 'o':
case 'O':
o++;
break;
case 'u':
case 'U':
u++;
break;
default:
other++;
break;
}
It simply counts every vowel and consonants.