Autor
|
Tema: Ayuda Calculadora (Leído 2,742 veces)
|
vhh70
Desconectado
Mensajes: 6
|
Buen dia, espero puedan ayudarme estoy haciendo un programa de Notacion Polaca, mi problema es que me hace falta una funcion que al leer la cadena esta funcion realice la operacion (como una calculadora). Por ejemplo: (2+6)*10= 80Tengo esta funcion pero solo es para numeros de un digito, tengo pensado usar apuntadores pero no se como. //MOSTRAMOS EL RESUTALTADO DE LA OPERACION void resultado(char cadena[100]){ char operador, operandoX, operandoY; //VARIABLES PARA PODER OPERAR int resultado, pilaResultado[100]; //PILA PARA GUARDAR LOS RESULTADOS printf("\n\nSolucion"); for(int i = 0, j = -1; i < strlen(cadena); i++){ //RECORREMOS LA CADENA if((((int(cadena[i])) > 47) && ((int(cadena[i])) < 58))){ //SI SE LEE UN NUMERO ENTONCES SE AGREGA A LA PILA DE RESULTADOS j++; //AUMETAMOS EL TOPE DE LA PILA pilaResultado[j] = (int)cadena[i] - 48; //SE CASTEA EL CARECTER Y SE LE RESTAN 48 PARA PODER GUARDAR EL NUMERO QUE SE LEE COMO CARACTER }else if(cadena[i] == '!'){ //SI SE LEE UNA OPERACION DE NEGACION operandoX = pilaResultado[j]; //SE TOMA EL ULTIMO VALOR DE LA PILA DE OPERACION resultado = operandoX * (-1); //SE MULTIPLICA POR -1 pilaResultado[j] = resultado; //SE GURADA EL RESULTADO EN EL TOPE DE LA PILA DE RESULTADOS printf("\n\t!%i = %i", operandoX, resultado); }else if(cadena[i] == '+'){ //SI SE LEE UNA OPERACION DE SUMA operandoX = pilaResultado[j]; //SE EXTRAE EL TOPE DE LA PILA Y SE GUARDA EN OPERANDOX j--; //SE DISMINUYE EL TOPE DE LA PILA operandoY = pilaResultado[j]; //SE EXTRAE EL TOPE DE LA PILA Y SE GUARDA EN OPERANDOY resultado = operandoX + operandoY; //RE OPERAN LAS VARIABLES OPERANDOX Y OPERANDOY pilaResultado[j] = (int)resultado; //SE GUARDA EL RESULTADO printf("\n\t%d + %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '-'){ //EN CASO DE QUE SE LEA UNA OPERACION DE RESTA operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = operandoY - operandoX; pilaResultado[j] = resultado; printf("\n\t%d - %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '*'){ //EN CASO DE QUE SE LEA UNA OPERACION DE MULTIPLICACION operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = operandoY * operandoX; pilaResultado[j] = resultado; printf("\n\t%d * %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '/'){ //EN CASO DE QUE SE LEA UNA OPERACION DE DIVISION operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; if(operandoX == 0) resultado = 0; else resultado = operandoY / operandoX; pilaResultado[j] = resultado; printf("\n\t%d / %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '^'){ //EN CASO DE QUE SE LEA UNA OPERACION DE EXPONENTE operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = pow(operandoY,operandoX); pilaResultado[j] = resultado; printf("\n\t%d ^ %i = %i", operandoY, operandoX, resultado); } } printf("\nResultado: %i", pilaResultado[0]); //SE MUESTRA EL RESULTADO FINAL } Nota:No puedo subir el codigo de notacion porque aun no me califican pero en cuanto me califique lo subire.
|
|
|
En línea
|
|
|
|
SrMcLister
Desconectado
Mensajes: 35
|
Buenas! Por favor, justifica mejor tu código, leer ese maraña de letras es imposible
|
|
|
En línea
|
return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());
|
|
|
vhh70
Desconectado
Mensajes: 6
|
Este es solo para una cifra, lo que necesito es que reciva mas de una cifra pero si lo hago con este necesiraria mas arreglos / void resultado(char cadena[100]){ char operador, operandoX, operandoY; int resultado, pilaResultado[100]; printf("\n\nSolucion"); for(int i = 0, j = -1; i < strlen(cadena); i++){ if((((int(cadena[i])) > 47) && ((int(cadena[i])) < 58))){ j++; //AUMETAMOS EL TOPE DE LA PILA pilaResultado[j] = (int)cadena[i] - 48; }else if(cadena[i] == '!'){ operandoX = pilaResultado[j]; resultado = operandoX * (-1); pilaResultado[j] = resultado; printf("\n\t!%i = %i", operandoX, resultado); }else if(cadena[i] == '+'){ operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = operandoX + operandoY; pilaResultado[j] = (int)resultado; printf("\n\t%d + %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '-'){ operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = operandoY - operandoX; pilaResultado[j] = resultado; printf("\n\t%d - %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '*'){ operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = operandoY * operandoX; pilaResultado[j] = resultado; printf("\n\t%d * %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '/'){ operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; if(operandoX == 0) resultado = 0; else resultado = operandoY / operandoX; pilaResultado[j] = resultado; printf("\n\t%d / %i = %i", operandoY, operandoX, resultado); }else if(cadena[i] == '^'){ operandoX = pilaResultado[j]; j--; operandoY = pilaResultado[j]; resultado = pow(operandoY,operandoX); pilaResultado[j] = resultado; printf("\n\t%d ^ %i = %i", operandoY, operandoX, resultado); } } printf("\nResultado: %i", pilaResultado[0]); }
|
|
|
En línea
|
|
|
|
Serapis
|
.... quedó duplicado, al tratar de modificarlo.
|
|
« Última modificación: 2 Junio 2018, 04:05 am por NEBIRE »
|
En línea
|
|
|
|
Serapis
|
Es que has ido a lo fácil... operar con bytes (chars), resulta cómodo... Bueno, la solución es que precisas una pequeña función que es un analizador léxico (en inglés lo suelen llamar scanner)... para ir leyendo la cadena de entrada y reconocer los números... Te aproximo al resultado de lo que necesitas... Se necesita unos estados para saber por donde andamos...y qué hacer a cada momento. Nota como los valores constantes con más de 1 bit, su nombre cambia a ES_.... aunque luego no los usamos... enumeracion AtributosDeCaracteres ATRIB_CHAR_DESCONOCIDO = 0 ATRIB_CHAR_DIGITO = 1 ATRIB_CHAR_OPERADOR_ASIGNA = 2 ATRIB_CHAR_OPERADOR_ARIT = 4 ' aritmético... si incluyes buleanos, o comparadores, añade las constantes antes de parentesis (y desplaza esos con sus valores más abajo) ES_ATRIB_CHAR_OPERADOR = (ATRIB_CHAR_OPERADOR_ASIGNA or ATRIB_CHAR_OPERADOR_ARIT) ATRIB_CHAR_PARENTESIS_ABRE = 8 ATRIB_CHAR_PARENTESIS_CIERRA = 16 ES_ATRIB_CHAR_PARENTESIS = (ATRIB_CHAR_PARENTESIS_ABRE or ATRIB_CHAR_PARENTESIS_CIERRA) ATRIB_CHAR_ESPACIO = 99 // espacio o tabulador... espacio duro, va hacer difícil que aparezca. fin enumeracion Se precisa un array que contendrá los atributos (que nos interesan) de todos los caracteres (que nos interesan). array bytes Atributos[0 a 255] Y rellenar el array de atributos... (el resto de operadores te lo dejo para ti). funcion Main // empezamos borrando la basura... bucle para k desde 0 a 255 Atributos[k] = ATRIB_CHAR_DESCONOCIDO siguiente
// los dígitos... bucle para k desde 48 a 57 Atributos[k] = ATRIB_CHAR_DIGITO siguiente
// operadores... Atributos[43] = ATRIB_CHAR_OPERADOR_ARIT // '+' Atributos[45] = ATRIB_CHAR_OPERADOR_ARIT // '-' Atributos[42] = ATRIB_CHAR_OPERADOR_ARIT // '*' ... el resto de operadores a considerar
Atributos[61] = ATRIB_CHAR_OPERADOR_ASIGNA // '='
// paréntesis... Atributos[40] = ATRIB_CHAR_PARENTESIS_ABRE // '(' Atributos[41] = ATRIB_CHAR_PARENTESIS_CIERRA // ')'
// espacios... Atributos[09] = ATRIB_CHAR_ESPACIO // tab Atributos[32] = ATRIB_CHAR_ESPACIO // spc fin funcion
Ya tenemos la base, va faltando la función para obtener los tokens con el analizador léxico. enumeracion TiposDeToken TOKEN_ERROR = 0 TOKEN_NUMERO =1 TOKEN_ASIGNA = 2 TOKEN_OPERADOR =3 TOKEN_PARENTESIS = 4 TOKEN_IGNORA_ESPACIOS = 9 fin enumeracion
// devuelve el tipo de token hallado y por referencia un string con el valor del token, y el índice (se va actualizando) // Parámetros: // Entrada: es el array de caracteres que se reciben... // Indice: es el índice actual siendo analizado. Es un parámetro por referencia. // Limite: es el tamaño del array (para no andar preguntando cada vez que se entra a la funcion). // Token: el valor a devolver para almacenar... puedes devolver un entero si lo prefieres... // Devuelve: el tipo de token hallado. Error si el carácter no pertenece a ningún tipo de token que el programa reconoce. TiposDeToken = funcion GetToken(array chars Entrada[], entero (ref) Indice, entero limite, string (ref) Token) AtributosDeCaracteres ch entero j, k
Token = Entrada(indice) ch = Atributos[entrada[indice]] indice +=1 Seleccionar caso ch caso ATRIB_CHAR_DIGITO Hacer mientras (indice < limite) Si (Atributos[entrada[indice]] != ATRIB_CHAR_DIGITO ) // empieza otro token, devolver el número hallado. devolver TOKEN_NUMERO fin si Token += Entrada(indice) // concatena otro dígito... indice +=1 repetir devolver TOKEN_NUMERO // fin del array. caso ATRIB_CHAR_OPERADOR_ARIT devolver TOKEN_OPERADOR caso ATRIB_CHAR_OPERADOR_ASIGNA //token = "=" devolver TOKEN_ASIGNA caso ATRIB_CHAR_PARENTESIS_ABRE //token = "(" devolver TOKEN_PARENTESIS caso ATRIB_CHAR_PARENTESIS_CIERRA //token = ")" devolver TOKEN_PARENTESIS caso ATRIB_CHAR_ESPACIO // es idéntico a dígitos, salvando las distancias, y que aquí, no precisa devolver el string del Token Token = "" Hacer mientras (indice < limite) Si (Atributos[entrada[indice]] != ATRIB_CHAR_ESPACIO) // [s]TOKEN_IGNORA_ESPACIOS )[/s] // fin de espacios... devolver TOKEN_IGNORA_ESPACIOS fin si indice +=1 repetir devolver TOKEN_IGNORA_ESPACIOS resto casos // ATRIB_CHAR_DESCONOCIDO Token = "" devolver TOKEN_ERROR fin seleccion fin funcion
Y ahora falta la función general que recibe la entrada, genera los tokens partiendo de la entrada recibiday que manda almacenar... buleano = funcion CalcularExpresion(char Cadena[100] entero j, k string Token TiposDeToken tTok
k= tamaño de Cadena j=0 Hacer mientras (j<K) tTok = GetToken(cadena, j, k,Token) Si (tTok = TOKEN_ERROR) mensaje de error devolver FALSE Sino Si (tTok != TOKEN_IGNORA_ESPACIOS) GuardarTokenEnPila(Token, tTok) // entrar Token para meter en la pila en la notación elegida (polaca, polaca inversa, etc...) fin si fin si Repetir
// la función que toma la pila y evalúa la expresión... si la haces sobre la marcha, // si no hay otra precedencia en operadores que el orden de entrada, // esto sobraría... sino, no puede evaluarse hasta procesar toda la entrada. Calcular Devolver True fin funcion
No he revisado tu código, pero a simple vista, parece subóptimo, de todos modos si dices que te funciona, pués listo... Añade lo señalado y actualiza como convenga... Ahora te llega un array de bytes-caracteres y el analizador va hallando los números (múltiples dígitos), operadores y parentesis, además ignora espacios y tabuladores y chequea por caracteres no admitidos... Nota que es solo un analizador léxico, de expresiones aritméticas numéricas, si metes demasiados dígitos que superen el entero generará error, esa comprobación realmente corresponde al analizador semántico, pero para lo sencillo que es el programa, lo puedes verificar justo antes de llamar a almacenar en la pila... antes de "GuardarTokenEnPila", si es un token numérico. Nota que te falta rellenar datos... en el array los valores de otros operadores... en Main
P.d.: Fe de erratas (la constante tachada no procede, si no la que se ha puesto a en su sitio): Si (Atributos[entrada[indice]] != ATRIB_CHAR_ESPACIO) TOKEN_IGNORA_ESPACIOS ) // fin de espacios...
|
|
« Última modificación: 3 Junio 2018, 17:11 pm por NEBIRE »
|
En línea
|
|
|
|
vhh70
Desconectado
Mensajes: 6
|
Muchas gracias. Voy a checar pero como decia antes creo que seria mas sencillo si utilizo apuntadores o estoy equivocado. Lo que se me complica con los apuntadores es como recorrerlo y luego hacer las operaciones.
|
|
|
En línea
|
|
|
|
Serapis
|
creo que seria mas sencillo si utilizo apuntadores o estoy equivocado. mmm... no sabes lo que dices. Tu dices sencillo, por ver 60 líneas de código, con las que no contabas?. Es el código mínimo, escueto... 2 enumeraciones para saber con que se opera y qué se devuelve (aunque inicialmente son muy parecidas, cuando añades más tokens empieza a distanciarse el parecido) y 2 funciones (4 si se incluye la de meter tokens en la pila, y la última de efectuar el cálculo). La primera función es la general, la que recibe la entrada chequea el carácter inicial y deriva hacia (la segunda función) el reconocimiento del token según dicho carácter (estado inicial). A su vuelta si no hubo errores y el reconocimiento fue efectivo, se invoca la 3ª función para almacenar el token, y finalmente cuando se termina de reconocer la entrada, toca realizar los cálculos. Una calculadora la puedes hacer más simple si quieres: Con la 'pantalla vacía', cuando empiece a escribir dígitos (basta 1 solo), está introduciendo el operando1, luego apenas el usuario introduzca un operador (pulsando la tecla, o escribiendo el carácter si no hay interfaz gráfica), almacenas el lo entrado como primer operando, cuando escriba otro dígito, almacenas el operador, y cuando de nuevo escriba otro operador efectúas la operación con los operandos previos, y el resultado se deja en el operando1... si el segundo operador era el símbolo "=", además muestras el resultado al usuario. (nota que con la pantalla vacía ambos operandos tienen valor 0, luego si empieza introduciendo un operador, se considera almacenado como operando1 el valor 0). Si no, cuando de nuevo introduzca un dígito, vuelves a guardar el operador, y tras un nuevo operador, los digitos recién metidos quedan almacenados como el 2º operando, y de nuevo se procesa ambos operandos con el operador introducido, y de nuevo el resultado se queda como el operando 1. El defecto de este modelo, son 2: - El primero defecto: el usuario debe introducir las operaciones en orden, ya que la precedencia seguida es 'se ejecuta inmediatamente', luego obliga al usuario a introducir ordenadamente o el resultado final puede ser errado... 5+2*3=, con este diseño de calculadora arrojaría: opn1 = 5 opr = "+" si opr = "=" mostrar opn1 opn2 = 2 oprtemp = "*" opn1 = opn1 opr opn2 = 5 + 2 = 7 opr= oprtemp si opr = "=" mostrar opn1 opn2 = 3 oprtemp = "=" opn1 = opn1 opr opn2 = 7 * 3 = 21 opr = oprtemp si opr = "=" mostrar opn1 mostrar 21 Por comodidad al operando1 sería mejor llamarlo acumulador, y al operando2, simplemente operando. Con precedencia de operadores sería opn1 = 5+(2*3) = 11 - El segundo defecto: Al ser ejecutado de modo inmediato, (carece de memoria, solo mantiene 3 datos). El usuario no puede ver que ha escrito más allá de lo último entrado, es fácil equivocarse y repetir un operando ya escrito con anterioridad, tampoco puede hacer nada más complejo, le exige pensarlo antes de introducir datos, ni puede hacer modificaciones sobre la marcha... Luego proveer que pueda entrar una expresión completa, es mucho más efectivo, una línea de texto con una expresión donde pueda modificar, añadir, verificar antes de procesar, es un diseño más 'potente' de calculadora... Al tiempo, si de nuevo te vas conformas con +-*/=, no te compliques más... Esto es, si es un tarea escolar... ...pero desde el momento en que a futuro quieras añadir operandos más complejos (números reales, en diferentes bases numéricas) ú operadores más complejos (como seno, coseno, tangente, random, media aritmética, raíz cuadrada, raíz cúbica, Xor, And, etc... tendrás que permitir operadores en la forma: 'sin', 'cos', 'atn', 'rnd', 'mod' 'sqr', 'sq3', 'xor', 'and'...), sí o sí, vas a necesitar un analizador de tokens... esto será tanto más cierto, cuanto más complejo haya de ser... y cuanto más complejo haya de ser, proveer el mecanismo (el diseño) más eficaz será lo mejor para poder ampliarlo, sin dejarse los sesos en ello... ergo, ahí te he mostrado el camino a seguir... listo para ampliar cuando se precise, falta básicamente proveer un analizador de "identificador" (cuyo código es casi idéntico al de número), junto con algún token alfabetico-alfanumerico, etc... Lo que se me complica con los apuntadores es como recorrerlo y luego hacer las operaciones. Para manejar los datos, elige estructuras que sobretodo seas capaz de manejar, porque las conoces y entiendes, aunque no sea del todo óptimo. En primer lugar uno debe lograr que funcione, luego es tiempo de hacer optimizaciones... no tiene sentido que pretendas usar por ejemplo una tabla hash, si no sabes como usarla y menos como coinstruírla o mantenerla. Primero logra que te funciones y luego ya mirarás de intentar optimizarlo... Ten en cuenta que la entrada recibida es en un array de bytes-caracteres, realmente al caso es lo más óptimo.
|
|
« Última modificación: 3 Junio 2018, 17:00 pm por NEBIRE »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Ayuda con calculadora
Multimedia
|
fitipal
|
6
|
2,885
|
10 Junio 2005, 16:35 pm
por fitipal
|
|
|
ayuda con calculadora en vb
« 1 2 »
Programación Visual Basic
|
tisan77
|
11
|
3,966
|
28 Octubre 2005, 02:05 am
por Leoj90
|
|
|
Ayuda calculadora.
Programación Visual Basic
|
Goldmoon
|
7
|
3,799
|
27 Diciembre 2007, 17:36 pm
por Goldmoon
|
|
|
Ayuda con calculadora
Java
|
painkillerpucela
|
3
|
3,076
|
19 Diciembre 2008, 21:40 pm
por Sk9ITk5Z
|
|
|
ayuda con una calculadora
Programación Visual Basic
|
andrer03
|
3
|
2,251
|
16 Enero 2009, 16:38 pm
por andrer03
|
|