elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  ayuda!! infijo a postfijo con 1 o mas digitos.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: ayuda!! infijo a postfijo con 1 o mas digitos.  (Leído 3,831 veces)
isaaclm

Desconectado Desconectado

Mensajes: 1


Ver Perfil
ayuda!! infijo a postfijo con 1 o mas digitos.
« en: 31 Mayo 2017, 20:22 pm »

hola amigos, buen dia. alguien me podria ayudar a modificar un codigo de infijo a postfijo con pilas. son 2 cosas que necesito hacer:
1.-ejemplo  : Entrada : (100+5.75) + 100 -> salida : 100 5.75 + 100 +.
el problema es que solo acepta caracteres de 1 solo digito.

2.- la segunda modificacion es evaluar la raiz cuadra representado por el caracter '$' con un prioridad maxima. ejemplo Entrada : $(10*10) -30 ->salida 1 :  10 10 * $ 30 -  salida2 : -20 que es el resultado de la evalucacion.

de antemano les agradeceria su ayuda.

el codigo es el siguiente:

Código
  1. class InToPost // infix to postfix conversion
  2. {
  3.    private StackX theStack;
  4.    private String input;
  5.    private String output = "";
  6.    //--------------------------------------------------------------
  7.    public InToPost(String in) // constructor
  8.    {
  9.        input = in;
  10.        int stackSize = input.length();
  11.        theStack = new StackX(stackSize);
  12.    }
  13.    //--------------------------------------------------------------
  14.    public String doTrans() // lo traduce a postfijo
  15.    {
  16.        for(int j=0; j<input.length(); j++)
  17.        {
  18.            char ch = input.charAt(j);
  19.            theStack.displayStack("For "+ch+" "); // *diagnostico*
  20.            switch(ch)
  21.            {
  22.                case '+': // es + o -
  23.                case '-':
  24.                gotOper(ch, 1); // apila operadores
  25.                break; // (precedence 1)
  26.                case '*': // it's * or /
  27.                case '/':
  28.                gotOper(ch, 2); // apila operadores
  29.                break; // (precedence 2)
  30.  
  31.                case '$':
  32.                gotOper(ch, 3); // apila operador raiz cuadrada
  33.                break; // (precedence 3)
  34.  
  35.                case '(': // parentesis izquierdo
  36.                theStack.push(ch); // apilarlo
  37.                break;
  38.                case ')': // parentesis derecho
  39.                gotParen(ch); // apila
  40.                break;
  41.                default: // debe ser un operando
  42.                    output = output + ch; // escribiendo ala salida
  43.                    break;
  44.            } // fin del switch
  45.        } // fin del for
  46.        while( !theStack.isEmpty() ) // apila los restantes operadoeres
  47.        {
  48.            theStack.displayStack("While "); // *diagnostico*
  49.            output = output + theStack.pop(); // escribe la salida
  50.        }
  51.        theStack.displayStack("End "); // *diagnostico*
  52.        return output; // retorna el postfijo
  53.    } // fin de doTrans()
  54.    //--------------------------------------------------------------
  55.    public void gotOper(char opThis, int prec1)
  56.    { // Obtuvo el operador de la entrada
  57.        while( !theStack.isEmpty() )
  58.        {
  59.            char opTop = theStack.pop();
  60.            if( opTop == '(' ) // if es un '('
  61.            {
  62.                theStack.push(opTop); // restaura '('
  63.                break;
  64.            }
  65.            else // es un operador
  66.            {
  67.                int prec2; // precedencia de nuevo operador
  68.                if(opTop=='+' || opTop=='-') //encuentra nuevo operador de precedencia
  69.                prec2 = 1;
  70.                else
  71.                prec2 = 2;
  72.                if(prec2 < prec1) // if precedencia de nuevo operador es menor
  73.                { // que precedencia del viejo operador
  74.                    theStack.push(opTop); // guarda el nuevo operador
  75.                    break;
  76.                }
  77.                else // precedencia de nuevo operador no es menor
  78.                    output = output + opTop; // que prec del viejo operador
  79.            } // fin del else (es un operador)
  80.        } // fin while
  81.        theStack.push(opThis); // apila nuevo operador
  82.    } // fin gotOp()
  83.    //--------------------------------------------------------------
  84.    public void gotParen(char ch)
  85.    { // obtuvo parentesis derecho de la entrada
  86.        while( !theStack.isEmpty() )
  87.        {
  88.            char chx = theStack.pop();
  89.            if( chx == '(' ) // si es extraido '('
  90.            break; // esta listo
  91.            else // si es extraido el operador
  92.            output = output + chx; // output it
  93.        } // fin while
  94.    } // fin popOps()
  95.    //--------------------------------------------------------------
  96. } // fin de la clase InToPost
  97.  

clase evaluacion postfija
Código
  1. class ParsePost
  2. {
  3.    private StackX theStack;
  4.    private String input;
  5.    //--------------------------------------------------------------
  6.    public ParsePost(String s)
  7.    { input = s; }
  8.    //--------------------------------------------------------------
  9.    public int doParse()
  10.    {
  11.        theStack = new StackX(20); // crea una nueva pila
  12.        char ch;
  13.        int j;
  14.        int num1, num2, interAns;
  15.        for(j=0; j<input.length(); j++) // for para cada caracter (char),
  16.        {
  17.            ch = input.charAt(j); // lee la entrada
  18.            theStack.displayStack(""+ch+" "); // *diagnostico*
  19.            if(ch >= '0' && ch <= '9') // if es un numero
  20.            theStack.push((char) (ch-'0')); // lo  apila
  21.            else // es operador
  22.            {
  23.                num2 = theStack.pop(); // extrae operandos
  24.                num1 = theStack.pop();
  25.                switch(ch) // hace la evaluacion aritmetica
  26.                {
  27.                    case '+':
  28.                    interAns = num1 + num2;
  29.                    break;
  30.                    case '-':
  31.                    interAns = num1 - num2;
  32.                    break;
  33.                    case '*':
  34.                    interAns = num1 * num2;
  35.                    break;
  36.                    case '/':
  37.                    interAns = num1 / num2;
  38.                    break;
  39.                    case '$':
  40.  
  41.                    default:
  42.                        interAns = 0;
  43.                } // end switch
  44.                theStack.push((char) interAns); // apila el resultado
  45.            } // fin del  else
  46.        } // fin del for
  47.        interAns = theStack.pop(); // devuelve respuesta
  48.        return interAns;
  49.    } // fin doParse()
  50. } // fin de la clase ParsePost
  51.  

este es el codigo de la clase pila

Código
  1. class StackX
  2. {
  3.    private int maxSize;
  4.    private char[] stackArray;
  5.    private int top;
  6.    //--------------------------------------------------------------
  7.    public StackX(int s) // constructor
  8.    {
  9.        maxSize = s;
  10.        stackArray = new char[maxSize];
  11.        top = -1;
  12.    }
  13.    //--------------------------------------------------------------
  14.    public void push(char j) // pone un elemento en el tope de la pila
  15.    { stackArray[++top] = j; }
  16.    //--------------------------------------------------------------
  17.    public char pop() // toma un elemento del tope de la pila
  18.    { return stackArray[top--]; }
  19.    //--------------------------------------------------------------
  20.    public char peek() // obtiene el tope de la pila
  21.    { return stackArray[top]; }
  22.    //--------------------------------------------------------------
  23.    public boolean isEmpty() // verdadero si la pila westa vacia
  24.    { return (top == -1); }
  25.    //-------------------------------------------------------------
  26.    public int size() // regresa el tamano
  27.    { return top+1; }
  28.    //--------------------------------------------------------------
  29.    public char peekN(int n) // regresa el elemento al indice n
  30.    { return stackArray[n]; }
  31.    //--------------------------------------------------------------
  32.    public void displayStack(String s)
  33.    {
  34.        System.out.print(s);
  35.        System.out.print("Stack (bottom-->tope): ");
  36.        for(int j=0; j<size(); j++)
  37.        {
  38.            System.out.print( peekN(j) );
  39.            System.out.print(' ');
  40.        }
  41.        System.out.println("");
  42.    }
  43.    //--------------------------------------------------------------
  44. } // fin de la clase StackX
  45.  

y por ultimo la clase principal la cual testea el programa.

Código
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4.  
  5. class InfixApp {
  6.    public static void main(String[] args) throws IOException {
  7.        String input, output;
  8.        int eval;
  9.  
  10.        while(true) {
  11.            System.out.print("introduce el infijo: ");
  12.            System.out.flush();
  13.            input = getString(); // lee un string de kbd
  14.            if( input.equals("") ) // sale del programa si es [Enter]
  15.                break;
  16.            // crea la traduccion
  17.            InToPost theTrans = new InToPost(input);
  18.            output = theTrans.doTrans(); // hace la traduccion
  19.            System.out.println("Postfix is " + output + '\n');
  20.            ParsePost aParser = new ParsePost(output);
  21.            eval = aParser.doParse(); // hace la evaluacion
  22.            System.out.println("Evaluates to " + eval);
  23.        } // fin del while
  24.    } // fin del  main()
  25.    //--------------------------------------------------------------
  26.    public static String getString() throws IOException
  27.    {
  28.        InputStreamReader isr = new InputStreamReader(System.in);
  29.        BufferedReader br = new BufferedReader(isr);
  30.        String s = br.readLine();
  31.        return s;
  32.    }
  33.    //--------------------------------------------------------------
  34. } // fin de la clase InfixApp
  35.  








En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: ayuda!! infijo a postfijo con 1 o mas digitos.
« Respuesta #1 en: 1 Junio 2017, 16:39 pm »

modificar un codigo de infijo a postfijo con pilas. son 2 cosas que necesito hacer:
1.-ejemplo  : Entrada : (100+5.75) + 100 -> salida : 100 5.75 + 100 +.
el problema es que solo acepta caracteres de 1 solo digito.
El primer fallo, es que pretendes operar con 1 dígito... eso esta bien en la fase de análisis léxico, para determinar correctamente los identificadores.
Pero en una etapa superior (cuando tratas la semántica), ya debe existir una separación clara, y aunque para un sencillo problema quizás pueda no parecer adecuado tener una tabla de símbolos, lo cierto es que resuelve el problema. simplemente para casos sencillos la tabla de símbolos puede ser un simple array.

En resumen (  :silbar: :silbar: :silbar: :silbar: ) :
- 1º Añade una etapa a modo de analizador léxico, donde reconoces y separas convenientemente cada identificador, y donde
- 2º Añadas luego el identificador a un array. Como hablamos de que es un problema sencillo, y que por ello nos basta con un usar un array, no es descabellado en estos casos, proveer un array estático, lo suficientemente grande, como albergar la expresión más compleja que pueda esperarse tratar... quizás un tamaño de 64 sea suficiente, tú decides ese tamaño.
- 0º Para simplificar el analizador léxico, es adecuado anotar (crear el minilenguaje admitido) las diferentes producciones que pueden darse... es bastante sencillo, si usas BNF o alguna modificación particular.
Básicamente describe que es un número, (que SIEMPRE empieza por un dígito y que está formado por 1 o más digitos y el número acaba cuando aparece un carácter distinto de dígito, dígito, operador, identificador, char, etc...
numero = digito | digito || numero     <--- las dos barras juntas '||' indica concatenación
digito = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"    <---- la barra '|' indica opcion.
operador = " + "|" - "|" * "|" / "|" $ "  
 

En este ejemplo: digito es cualquiera de los números (caracteres) en el rango 0-9
y número es un digito, o un digito + un número (esto expresa recusividad, ya que número puede expresarse nuevamente con cualquiera de las dos opciones previas, esto es un digito, o un digito + otro número, etc...).

Y operador es cualquiera de los caracteres indicados (inclusído tu 'raíz cuadrada'). fíjate la obligación de estar separado por espacios, es decir un operador son 3 caracteres, el que se reconoce + un espacio acada lado. Así tu analizador léxico, puede indicar error cuando no tenga un espacio a cada lado. El número no exige espacio, gracias a la última producción que falta por definir... expresión, y se define como:


expresion = numero || operador || numero | numero || operador || expresion
id = char | char || id  <---- identificador
char = "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"| ... |"y"|"z"|
 <---- carácter, ojo, veáse que son minúsculas, por tanto debiera generarse error en el analizador léxico, si aparece mayúsculas, ya que no se ha definido su uso en para generar los identificadores...

formula =  id || " = " || expresion <---- una producción sería la fórmula entera (la expresión entera, más la asignación a un identificador).

A veces la 'formula' es fácil confundirlo con las producciones, debido al '=', en realidad para las producciones suele usarse el símbolo: ":=" o también "::=", yo los he usado indistintamente " = ", para explicar una producción (cualquier combinación del 'lenguaje' como una formula (una combinación específica del lenguaje que hemos llamado 'formula', espero que se sepa distinguir cuando hablo de una cosa y cuando de otra.

Claramente se ve, que a una 'formula' se le asigna una expresión y es reconocida por un identificador.
Por su parte una expresión consiste de una lista de números separados por un operador. Igual que número tiene 2 opciones de ser definido, se podría decir que una expresión es simple si consta de solo dos números y un operador, y una expresión es compleja si consta de una lista de números (mayor de 2), donde siempre empieza con un número y a cada número excepto al último le sigue un operador.

Tu analizador léxico puede optar por indicar fallo cuando falta espacios a ambos lados del operador, o dada la simplicidad de la expresión, puedes modificarlo y añadirlo tú mismo por código (autocorreción).

Nota como id (un identificador) es uno o más caracteres y que una 'formula' requiere el identificador y luego el símbolo "=", también con espacios a ambos lados.

Nota que hay otra forma de expresar opciones (de una producción). Y es, usar varias líneas en vez de reunirlas en solo una, para los dígitos, los operadores y los caracteres es bastante claro el modelo de una sola línea, pero para otras, a veces queda más entendible si se usa como varias líneas, donde en cada línea se pone una sola de las opciones posibles. Un ejemplo para número (que valdría igualmente para expresión)

Producción multilínea para número y expresion (es idéntico al anterior)
numero = digito <--- ejemplo: 5
numero = digito || numero   <---- ejemplo: 53456

expresion = numero || operador || numero <---- ejemplo: x = 5 + 3
expresion = numero || operador || expresion
<---- ejemplo: y = 7 + ( 3 - 1 ) <---no hemos definido los paréntesis (en el ejemplo) como operadores, pero los he puesto para diferenciar la parte 'expresión' de esta producción.

Otro ejemplo: valor = 9 - 2 + 16
Estos ejemplos en cambio actualmente darían error:
valor = 44
suma = valor + 12 - 7
...porque no hemos definido lo siguiente para formula:

formula = id | id ||" = "|| expresion <--- --->ejemplos:
valor = 5
h = valor
total = h * cantidad
total = (total + 21)
preciolatas = 12
preciounitario = 32
total = total + (preciolatas * preciounitario)

Este otro ejemplo daría error léxico:
Valor = 5   <---- identificador no admite mayúsculas, tal como está actualmente descrito identificador.
valor = 5H  <---- número solo lleva dígitos, no se ha previsto diferencia de números decimales, hexadecimales, octales, binarios,etc...
valor10 = 23  <--- identificador secompone solo de caracteres en el rango a-z, no puede llevar números (ni menos empezar por él), tal como está actualmente definido identificador.


Hasta aquí el analizador léxico. Éste si debe operar con caracteres hasta ir formando los números (no dígitos), que deben ser añadidos a la tabla de símbolos (un array para algo sencillo basta).

Si quieres profundizar en el asunto, vuelve a leer todo lo previo las veces que haga falta, si solo quieres 'aprobar el examen', te bastaba con leer este párrafo que sigue (y aplicalro bien, obviamente)  :laugh: :laugh: :laugh: :laugh:
Luego en la siguiente fase de análisis se puede operar ya con los tokens que contiene la tabla de símbolos. Pero ahora ya, no opera con 'chars' si no con 'strings'... sólo así, puedes hacer: valor = 534 + 723

Te recuerdo, que una de las ventajas de la notación postfija es que no exige el uso de paréntesis. y por si al final has profundizado, y le has leído varias veces, te aclaro que puede simplificarse mucho, cuando uno acaba por entender que una expresión (como la descrita, básicamente matemática) es una lista, ya que se alternan números y operadores... ..y ahí lo dejo.

Te he dejado como ejercicio optimizar: expresion, formula, numero ...una de ellas es redundante, pero es ideal para ayudar a entenderlo, y una vez entendido puede ser suprimido.

2.- la segunda modificacion es evaluar la raiz cuadra representado por el caracter '$' con un prioridad maxima. ejemplo Entrada : $(10*10) -30 ->salida 1 :  10 10 * $ 30 -  salida2 : -20 que es el resultado de la evalucacion.
Como puedes ver, en ese mismo problema, usando la notación de postfijo (polaca inversa), no requiere el uso de paréntesis, ya que el orden en que se usan los operadores no da lugar a dudas.

Ayuda mucho construir un árbol de análisis sintáctico, no es obligado, pero sí para acabar de entenderlo bien.

p.d.: Nota: Se deja como ejercicio, dónde colocarías (que producción debería llevar los paréntesis y cómo sería esa producción), los paréntesis. En los operadores no se incluye paréntesis... para indicar prioridad/precedencia. Aunque la notación postfija, no requiere de paréntesis, si el analizador léxico.


« Última modificación: 1 Junio 2017, 17:15 pm por NEBIRE » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Prefijo – Postfijo – Infijo (C#)
.NET (C#, VB.NET, ASP)
ahome31 0 6,588 Último mensaje 2 Noviembre 2009, 06:37 am
por ahome31
Ayuda con número de dígitos.
Programación C/C++
Jaraysedal 1 2,955 Último mensaje 2 Noviembre 2010, 20:32 pm
por Littlehorse
!Ayuda! Reemplazar un Texto por Digitos
PHP
Brian1511 0 1,583 Último mensaje 22 Junio 2013, 18:55 pm
por Brian1511
Proyecto calculadora: Convertir infijo a posfijo.
Programación C/C++
Yoel Alejandro 9 30,915 Último mensaje 25 Marzo 2014, 22:34 pm
por amchacon
Operadores incremento/decremento en prefijo y postfijo. « 1 2 »
Programación C/C++
K-YreX 15 6,340 Último mensaje 6 Octubre 2019, 02:40 am
por Loretz
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines