Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Serapis

#1341
En tiempo de diseño ya debes tener definido el evento (lo que tenga que hacer)... simplemente crea la función que actúa como evento y que reciba los parámetros que recibiría si lo definieras sobre el tipo de control que creas dinámicamente.

Luego al momento de crear el control, lo enganchas al controlador (AddHandler... ) de eventos que creaste durante diseño...
#1342
Cita de: string Manolo en 15 Octubre 2019, 21:57 PM
No es gratuito, o sí?
Todos esos números son gratuitos... son a los que puedes llamar incluso aunque tu tf. no tuviere saldo o tuvieres deudas con tu empresa de telefonía...
#1343
Son niñatos al 90-95% (basta ver las imágenes)... es decir los adolescentes y posadolescentes adoctrinados.

Para mi no cuenta como protesta, cuando procede de niñatos, no se han ganado aún el derecho a protestar por ciertas cosas en la vida. Eso sí, el daño físico a personas infraestructuras o mobiliario urbano, resulta inevitable venga de quien venga y saldrá del bolsillo de todos, como elllos son niñatos, no sale del suyo (a lo sumo del de sus padres)...

...como decía en un vídeo un tipo que iba en su vehículo, retenido por estas inútiles acciones: "...luego les quitan las pensiones y ninguno sale a protestar...". y lastimosamente así es de verdad. Si les quitan o restringen sus derechos se callan como g1l1p0y@s, pero si trata sobre algún político o asunto independentista, explotan como energúmenos... ejemplo clarísimo de lo que se logra con un lavado de cerebro.

...lo más penoso es que dicho lavado se aplica a estos que se creen la generación "más nosequé de la Historia de la Humanidad"...
Precisamente en estos tiempos que la información está más al alcance de la mano que nunca (esto si es cierto), parece inpensable que esto ocurra. Nunca hay que olvidar, que el el 'factor humano', suele ser siempre el más débil, sin importar los avances que se produzcan en cualquier momento de la Historia...
#1344
De entrada el color rosa, míralo como el color chicle, es decir un valor como:
Verde = 0
Rojo = 255
Azul = 255

Tomando una foto, es muy probable que ese color se difumine en varios sonos similares, mejor si se escanea, aunque el resultado tampoco será perfecto.

Lo que se pide básicamente es obtener los colores de la hoja que no sean rosa, esto es el rosa se trata como si fuera un color transparente. Sin embargo, resulta ambiguo... no se aclara como debe ser el formato devuelto (aparte de que debe ser en hexadecimal)... ni si basta indicar una sola vez cada color o no.

Así que supondremos que se pide obtener todos los colores que no sean rosa, y que no se guarda posición del píxel para dicho color, y que se guarda para cada color píxel, haya aparecido previamente dicho color o no.






constantes byte RosaR=255, RosaA=255, RosaV=0  // valor canales del rosa-chicle
byte nivSimil  // nivel de similitud
byte r, a, v   // canal de cada colores
int f, p     // num filas y valor píxel
string hexColor  // color en hexadecimal.
int ancho, alto  // medidas d ela imagen
array int Imagen(,)   // array de dos dimensiones o unidimensional si se calcula fila a fila la posición absoluta del píxel...

fichero fiI  // fichero de entrada (Input), el de la imagen
fichero fio  // fichero  de salida (output), el del resultado

fiI.Abrir(rutaImagen) // se abre el fichero de entrada
fio.Abrir(ruta)   // se abre el fichero de salida.

alto = fiI.LeerEnCabecera(alto)
ancho = fiI.LeerEnCabecera(ancho)

// solo la que proceda... se leen los píxeles desde final de cabecera...
//    se supone que la imagen está descomprimida, sino es así, se precisa
//    el decodificador del formato de imagen para obtener el array de píxeles...
//    se da por supuesto conocer tal circunstancia.
Imagen(alto * ancho) = fiI.LeerPixeles  //lectura unidimensional
Imagen(alto, ancho) = fiI.LeerPixeles  // lectura bidimensional
fiI.Cerrar

nivSimil  = 16
bucle f por cada fila en la imagen  //imagen sería un array de píxeles, por ejemplo.
   bucle p por cada pixel en f          // p es el enésimo píxel en la f (fila) actual.
       // 1 obtener los canales del pixel.
       r  = (p and 255)
       v = ((p \ 256) and 255)
       b = (p \ 65536)
       
       // 2 descartar si es rosa o similar... vamos a suponer algún grado de similitud
       //   si, el color está 16 valores a un lado u otro por canal consideramos que es similar... y en tal caso se descarta, si no, se acepta.
      //  como dicho rosa está en los extremos, basta mirar hacia el otro extremo.
      Si (((v > = (RosaV + nivSimil  )) y ((R <= (RosaV - nivSimil)) y  ((a <= (RosaA - nivSimil)) )
          // formato: AAVVRR  (esto es primero azul, luego verde, luego rojo)
          // el operador '+' actúa como un concatenador de caracteres...
          hexcolor = (((a\16).ToChar) + ((a and 15).ToChar) + ((v\16).ToChar) + ((v and 15).ToChar)  + ((r\16).ToChar) + ((r and 15).ToChar)) + " "
          fiO.SaveToFile(appendtofinal, hexcolor)
      Sino
          fiO.SaveToFile(appendtofinal, "------ ")   // color rosa se guarda así, necesario si
          // ...se quiere mantener posición relativa de cada color que no sea rosa.
          // cada clor va separado por un espacio, para facilitar su 'lectura', visualmente...
      fin si
   siguiente
siguiente

fiO.Cerrar


Se puede optimizar, si al canal de rosa, ya se le aplica antes del bucle, el valor de similitud, en vez de ecalcularlo por cada píxel... como los valores de rosa son constantes, se rquerirán sendas variables, para ello.
Sería aún más útlil, si en vez del rosa, fuera cualquier otro color recibido por parámetro, tal color se descomprondría e sus canales, aunque en tal caso, la verificación para descartar, es más larga pues hay que descartar también los valores al otro lado del límite de cada canal, actualmente se aprovecha que el rosa, tiene sus tres canales en valores que a un lado son límite...


Falta obtener la forma... Ahora nos ocupamos de ella...
La forma es un contorno. Un contorno, es el recorrido perimetral de la forma.
Sea una imagn de X*Y medidas, podemos saber que el controno, será como máximo (X+Y) * 2 de tamaño... que es el perímetro de un rectángulo, en este caso del rectángulo que forma la imagen. Nótese que solo consideramos la forma externa, si por ejemplo la hoja tuviera uno o más rotos internos, esas formas no quedan detectadas... Eso es una fase posteiror, para aplicar una vez se entienda al menos la primera, detectar la forma externa.

Cómo se obtiene?. Básicamente definimos dos arrays uno del vertical y otro del horizontal, de una estructura que para el vertical define izquierdo y derecho y para el horizontal superior e inferior... una simple abstración, nos permite resumir ambas en inicio y fin. Cada una define un punto, una posicion, el par X,Y.


Estructura Posicion
   int X
   int Y
Fin estructura

Estructura Extremo
   posicion Inicial         // izquierda o superior
   posicion Final           // derecha o inferior
fin estructura

Array de Extremo PerimVertical(alto)
array de Extremo PerimHorizontal(ancho)

Array Extremo NumPuntos(0 a 1)  // 0 refiere vertical, 1 refiere horizontal, cantidad de puntos que cvontiene el array (el resto sobra)

int x, y, n   // punteros de avance para cada array...

Nótese que el contorno, será la línea que una dichos puntos... como también resulta ambiguo la forma en que deba ser devuelto, baste estos dos arrays y luego haz con ellos lo que quiera, posiblemente escribirlos a fichero o sarlo para dibujar en algún lienzo... y luego guardar la imagen resultante a fichero.

Aunque los siguientes bucles parezcan mucha sobrecarga de trabajo, en realidad, solo se recorre hasta encontrar un pixle que no sea similar al rosa.

// obtener la parte vertical izquierda...
n=0
bucle para y desde 0 hasta Alto-1  
   bucle para x desde 0 hasta Ancho-1  
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimVertical(n).Inicial.X = x
            PerimVertical(n).Inicial.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(0).Inicial = n   // solo los primeros 'n' puntos dle array PerimVertical son válidos

// obtener la parte vertical derecha...
n=0
bucle para y desde 0 hasta Alto-1  
   bucle para x desde Ancho-1 hasta 0 retrocediendo
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimVertical(n).Final.X = x
            PerimVertical(n).Final.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(0).Final = n  // solo los primeros 'n' puntos dle array PerimVertical son válidos

// obtener la parte horizontal superior...
n=0
bucle para x desde 0 hasta Ancho-1  
   bucle para y desde 0 hasta Alto-1  
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimHorizontal(n).Inicial.X = x
            PerimHorizontal(n).Inicial.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(1).Inicial = n   // solo los primeros 'n' puntos dle array PerimHorizontal son válidos

// obtener la parte horizontal inferior...
n=0
bucle para x desde Ancho-1 hasta 0 retrocediendo
   bucle para y desde 0 hasta Alto-1  
        Si (Similar(Rosa, imagen(y, x), 16) = FALSE)
            PerimHorizontal(n).Final.X = x
            PerimHorizontal(n).Final.y = y
            n = (n +1)
            Salir del bucle
        fin si
   siguiente
siguiente
NumPuntos(1).Final = n   // solo los primeros 'n' puntos dle array PerimHorizontal son válidos


y listo, lo que hagas luego con dichos arrays ya es cosa tuya, pués no queda definido... Como dije antes, se puede guardar a fichero, o genera la imagen de la forma, recoriendo los 4 arrays para pintar el píxel que refieren sus cordenadas... y quizás luego guardarla la imagen resultante a fichero.

Similar ahora la definimos como una función, para dejar más claro la funcionalidad de obtener el contorno.
Esta función hace lo que ya hemos hecho antes en código, pero integrado en la misma funcion.
Rosa lo pasamos entero, es más rentabale pasar los canales ya descompuestos... (para hacelro una sola vez, no con cada color).

Buleano = ColorSimilar(int Color, int colCandidato, int nivel)
   int r1, v1, a1, r2, g2, a2, r3, g3, a3

   // Descomponer el color base a comparar aplicado sus niveles máximo y minimo a cada canal...
   r1= fixToRangoByte((color and 255) + nivel)
   r2 =fixToRangoByte((color and 255) - nivel)

   g1= fixToRangoByte(((color \ 256) and 255) + nivel)
   g2 =fixToRangoByte(((color \ 256) and 255) - nivel)

   a1= fixToRangoByte((color \ 65536) + nivel)
   a2 =fixToRangoByte((color \ 65536) - nivel)

   // Descomponer el color candidato en sus canales...
   r3 = (colCandidato and 255)
   g3 = ((colCandidato\ 256) and 255)
   a3 = (colcandidato \ 65536)

   // Comparación:
   //    ejemplo para canal rojo: r= 45;  r1=(45+16) = 61;  r2= (45-16) = 29
   //        si r3 cae ente 29 y 61 el rojo es similar... igual para el resto de canales.
   Si ((r3 <= r1) y (r3 >= r2))
       Si ((g3 <= g1) y (g3 >= g2))
           Si ((a3 <= a1) y (a3 >= a2))
               devolver TRUE
           fin si
       fin si
   fin si
fin funcion

Byte = fixToRangoByte(int Valor)
   Si (valor < 0 )
      valor = 0
   osi (Valor > 255)
      valor = 255
   fin si

   devolver Valor
Fin funcion


Si en vez de hablar de similitud, pudiéramos hablar de igualdad, es decir que el rosa, no tuviera variedad tonal, el cálculo se aceleraría, pués bastaría comparar el píxel 'p', con rosa , en vez de calcular si es similar... pero sacando fotos, o escaneos, no habrá un color puro... la luminosidad del ambiente y los reflejos marcarán variaciones tonales.
#1345
Foro Libre / Re: Scooter (patinete) para adultos
15 Octubre 2019, 15:49 PM
En casa tengo una como esta...


https://www.carrefour.es/mini-bike-e3-negro/VC4A-8671997/p

Se pliega el manillar y cabe perfectamente dentro del maletero del coche. Pesa 12kg. Es eléctrica sin pedales, tiene una autonomía de alrededor de 25-30km... y la velocidad máxima también anda en esos límites 25-30km/h, aunque depende del peso que se suba a ella.

Una eléctrica, ofrece la ventaja de que incluso puedes dejar el coche en casa, salvo que debas ir bastante más lejos, o debas cargar cosas... pero si es solo para ir y volver al trabajo en la propia ciudad, es un sustituto perfecto... no tardas más que en coche en llegar a donde vayas, eso sí, requiere que la ciudad tenga una buena dosis de carriles bici, si no... estás metido al tráfico de carburantes, tragando humo, y sujeto al parapeto de los semáforos...
#1346
Bajo mi punto de vista, la condena quizás resulta excesiva... Más que nada, porque para los independentistas ahora serán mártires de la 'causa'...

Desde luego lo que me parecerá inaceptable es cualquier intento de indulto, porque sería reírse del resto de la gente. Mandaría el mensaje de que si eres puede saltarte la ley, porque que al final te indultan... que están por encima d ela ley... mientras en la cárcel hay gente cumpliendo condenas nada despreciables por delitos a veces ridículos, injustos o incluso después de haber 'reformado' (rehabilitado en la sociedad)...

La ley es la misma para todos o para ninguno.
#1347
Fantástico...

Ya no solo un problema nuclear focalizado en un territorio, puede afectarte solo si estás a cierta distancia menor de... ahora además puede caerte directamente en cabeza sin importar la parte del planeta donde vivas... y como quiera que un satélite no cae de la noche a la mañana, ni a plomo, la contaminación puede arrastrarla miles de kilómetros, incluso todo el perímetro terrestre si tarda tiempo en perder la órbita, pues probablemente le diera tiempo a dar varias decenas de vueltas  al Planeta Azul marrón.

Siento, que a los pollíticos, se les va de las manos esto de la 'guerra'... creo que al final, los ciudadanos tendrán que quitarse la zapatilla y sacudir fuertemente con ella el culo de cada político y cada militar... parecen empeñados a destruir a todo el resto del planeta para 'vivir' solo ellos, ignorando que cuando algo así suceda, todo el planeta será un desierto, no quedarán supervivientes (tal vez alguna cucaracha mutante).
#1348
Ains, eso de: "es más mayor."... hace pensar que lo escribe un niño de 12 años.

La huída hacia adelante que impulsa Google, no es ninguna solución, eso de actualizar cada semana, pondrá difícil incluso imposible a terceros vulnerar, o violar el sistema (que tampoco es determinante, si no solo probable), pero rompe la estabilidad que espera un usuario.

Un usuario, no puede perder 1 hora cada día de su vida, para 'actualizar' sus sistemas y asegurarse que las actualizaciones proceden de lugares de descarga de confianza. digamos que básicamente, un sistema que se actualiza permanentemente, añade un vector a ser atacado... la transmisión, un sistema que se actualiza una vez al año, en fecha imprevista, díficilmente pueda ser atacado durante dicha transmisión. El usuario (doméstico) se ve incapaz de, garantizar que una descarga o una actualización no haya sido violada, solo porque Google diga que 'es seguro'.

Es obligación de la empresas ofrecer servicios seguros, y es obligación de los gobiernos, exigir que así sea. Pero ni lo uno ni lo otro, hay una dejadez de funciones total y absoluta, dejándolo clgaod al aire, con ...en la próxima actualización...
Francamente una empresa como Google, que basa su seguridad prácticamente en actualizar semanalmente sus productos, lo que deja constancia es que no tienen ideas (si, ya sé que ellos siempre caracrean innovación, pero actualizar es modificar, no innovar), no tienen ideas...

La actualización constante es un sistema de seguridad frágil, pero además deprimente para los usuarios, porque una aplicación que te funcionaba perfectamente, con la nueva actualización deja de hacerlo, o añade funcionalidad indeseada o elimina funcionalidad que a uno le resultaba muy útil, o elimina parte o todo el historial o la configuración (además sin previo aviso)... en fin, decepcionan constantemente a sus usuarios, así que me temo que cuando surja una nueva empresa, que ofrezca seguridad y estabilidad (seguridad no basada en actualizaciones), una gran parte de usuarios tendrá motivos para hacer el cambio de empresa.
Mocosoft, actualmente está más empeñada en seguir los pasos de google que en buscar su propio camino, luego en ese camino, se encontrará los mismos obstáculos que Google, así que me temo que Mocosoft (con sus actuales dirigentes y mediocres programadores), tampoco serán la solución 'salvadora'... y si la solución ha de venir de mano de Rusia o China, como que muchos no estaríamos dispuestos a fiarnos (no lo hacmeos con empresa USA, menos con empresas de países donde el gobierno tiene tentáculos en todas las empresas).

...en definitiva estamos J0D1D05.
#1349
Programación C/C++ / Re: Ayuda
13 Octubre 2019, 20:16 PM
En efecto, el cambio a la notación polaca inversa, es resolver la precedencia de la evaluación de la expresión debida por un lado a los paréntesis, y por otro al resto de  operadores que con distinta precedencia aparecen incluso sin paréntesis, y paliar por tanto el tiempo que se pierde en evaluar la precedencia de la expresión cada vez que deba ser ejecutada. Además simplifica el uso de la pila... pués tiene acciones muy sencillas para efectuar el cálculo.

Tampoco hay que olvidar que el código máquina/ensamblador suele ser notación prefija:
Mov  AX, 5
Add  BH, AH
Jmp  800
...
por lo que los compiladores, usan como código intermedio lo que se llama 'código de 3 direcciones', para finalmente compilar al sistema destino de una forma sencilla y rápida, precisamente teniendo en mente estas cuestiones.
#1350
Programación C/C++ / Re: Ayuda
13 Octubre 2019, 08:46 AM
No entiendo por qué (los profesores) se empeñan en intentar profundidar en teoría de compiladores en el primer año, cuando el alumno, todavía está demasiado verde... Una introducción estaría bien, pero sin profundizar.

La notación polaca inversa, tiene bastante trabajo incluso en su forma más simple...
Al lío...

La notación que usamos 'humanamente' se llama infija, esto es el operador aparece en medio de los operandos...
Siguiendo la idea, es fácil entender que el operador puede aparecer también al inicio o al final de ambos operandos, lo que da nombre a la notación prefija (o polaca) y la postfija (o polaca inversa).

Se usa bastante en los compiladores, porque simplifica las expresiones de cara a poder usarlos de forma cómoda y rápida desde la pila, aunque no siempre resulta eficiente.
...Tu caso (crear una calculadora que opere así), entra en el caso de los intérpretes, no será compilado, pero todavía puede resultar útil...

La forma de hacerlo eficiente, es diseñado a bajo nivel, no delegando a funciones, la ventaja es que puedes acomodar el algoritmo al completo según tus necesidade,s lo cual es siempre más eficiente que tener que diseñar y luego adaptar tu algoritmo, a lo que te dejen hacer las funciones que disponga tu lenguaje...

en esta implementación como tiene más propósito ilustrativo de cara a aprender, vamos a considerar que cada token se compone de solo 1 carácter (para no perdernos en detalles más alejados), una vez se comprenda y domine el tema, puede ampliarse, para reconocer números incluso en  diferentes bases numéricas...

Así de entrada hay que definir alguna enumeración y algún array, para mantener dicha eficiencia arriba...

Enumeracion AtributosChar
   ATRIBCHAR_ERROR = -1                        // cualquier otro carácter (no considerado a continuación)...
   ATRIBCHAR_IGNORA = 0                        // espacios
   
   ATRIBCHAR_OPERADOR_PRECEDENCIA_1 = 1        //  */
   ATRIBCHAR_OPERADOR_PRECEDENCIA_2 = 2        //  +-
   ATRIBCHAR_OPERADOR_MAX = 2                  // Valor mayor de la precedencia (no precedencia mayor, pués están en orden inverso).
   // Este valor se consigna desde NextToken, pero no se asigna en la tabla.
   ATRIBCHAR_OPERADOR_UNARIO = 3               // +- (pero cuando va delante de otro operador o de un paréntesis de apertura,o al comienzo.
   
   ATRIBCHAR_DELIMITADOR_ABRE = 5              // (
   ATRIBCHAR_DELIMITADOR_CIERRA = 6            // )
   ATRIBCHAR_OPERANDO = 7                      // [±] (A-Z|a-z|0-9) ...aunque solo operamos con dígitos, porque luego quieres calcular resultados...
fin Enumeracion

Estructura RegistroTblSimb
   string Valor                      
   AtributosChar Token
   //real Calculo                    
End Type

La enumeración la usaremos para identificar cada tipo de carácter derivándolo a nuestras necesidades...
La estructura, dispuesta en un array hará las veces de la tabla de símbolos que será usada  para almacenar los tokens cuando sean analizados.

Ahora procede crear los arrays estáticos con sus valores...
Esto típicamente se hace en el Main...

Primero declaramos los arrays que vamos a usar como apoyo...

Array de Atributoschar s_Tabla(0 a 255)
array de RegistroTblSimb s_TblSimb(0 a 79)      
//80 parece un número suficiente para probar la calculadora, será raro que en una calculadora sencilla haya expresiones con más de 80 tokens...
//pero vamos si se espera que suceda, basta ampliar el número a lo que se considere adecuado.

// y rellenamos ya el array de atributos de los caracteres...
funcion Main
   llamada a CrearTabla
fin funcion

// se deja en una función aparte para mantener despejado 'main', y para centrar la función a lo que dice su nombre y hace.
funcion CrearTabla
   int k
   
   // Todos se marcan como error, luego los válidos con su valor adecuado...
   Bucle para k desde 0 hasta 255
       s_Tabla(k) = ATRIBCHAR_ERROR                // todos excepto los que siguen.              
   Siguiente

   // Digitos:
   Bucle para k desde 48 hasta 57
       s_Tabla(k) = ATRIBCHAR_OPERANDO             // 0-9
   siguiente
   
   // Caracteres:
   Bucle para k desde 65 hasta 90
       s_Tabla(k) = ATRIBCHAR_OPERANDO             // A-Z
       s_Tabla(k + 32) = ATRIBCHAR_OPERANDO        // a-z
   siguiente
   
   // Separador:
   s_Tabla(32) = ATRIBCHAR_IGNORA                  // el espacio (también se podría poner l espacio duro)

   // Delimitadores:
   s_Tabla(40) = ATRIBCHAR_DELIMITADOR_ABRE        //  (
   s_Tabla(41) = ATRIBCHAR_DELIMITADOR_CIERRA      //  )
   
   // Operadores:
   s_Tabla(42) = ATRIBCHAR_OPERADOR_PRECEDENCIA_1  //  *
   s_Tabla(43) = ATRIBCHAR_OPERADOR_PRECEDENCIA_2  //  +
   s_Tabla(45) = ATRIBCHAR_OPERADOR_PRECEDENCIA_2  //  -  
   s_Tabla(47) = ATRIBCHAR_OPERADOR_PRECEDENCIA_1  //  /
fin funcion


Nos bastan esos 4 operadores y los paréntesis, para ejemplificar...
Ahora lo siguiente será una simple función que será el analizador léxico...
Su función es pedir tokens que se extraen d ela entrada y los guarda en la tabla de símbolos. es una función muy simplificada dado que para el caso, los tokens se limitan a:
Operando, Operador, ParentesisAbre, ParentesisCierra

// El scan léxico: Debe reconocer cada tipo de token válido.
//  que almacena en el array s_TblSimb
// Devuelve la cantidad de tokens hallados, si devuelve 0, es que hubo algún problema:
//   1 - El string de entrada estaba vacío: ""
//   2 - Hay caracteres 'raros' no considerados en nuestra tabla: 5+3-6+?*@   (? y @ no sons ímbolos admitidos en 'nuestra gramática').
//   3 - La expresion está mal formada (error sintáctico):  5****3;   4+345;  5+(((3-2)
int = Funcion ScanLex(string Expr )
   int k, n
   string st
   AtributosChar tk  
   
   // n = 1 ciertos lenguajes considera el primer carácter de un string, como el 1, no el 0, descomentar en tal caso...
   Hacer mientras (n <= Expr.Size)
       st = NextToken(Expr, n, tk)

       Si (tk = ATRIBCHAR_ERROR)
           devolver 0
       Osi (tk = ATRIBCHAR_OPERADOR_UNARIO)
           // Un operador unario solo afecta a un operando, simulamos que el otro es 0
           // y lo encerramos entre paréntesis, para forzar la precedencia dentro.
           // ejemplo: 5*-1 = -5  ó -1*5 = -5   También si se usa el signo +   5*+7
           // queda como si fuera: 5*(0-1)   (0-1)*5    5*(0+7)
           // la misma técnica vale para otros operadores unarios como not(x), cos(x), Abs(x), etc...  
           s_TblSimb(k).Valor = "("
           s_TblSimb(k).Token = ATRIBCHAR_DELIMITADOR_ABRE
           k = (k + 1)
           s_TblSimb(k).Valor = "0"
           s_TblSimb(k).Token = ATRIBCHAR_OPERANDO
           k = (k + 1)
           s_TblSimb(k).Valor = st
           s_TblSimb(k).Token = ATRIBCHAR_OPERADOR_PRECEDENCIA_2
           k = (k + 1)
           // y ahora pedimos el operando suelto, para luego cerrar el paréntesis, antes de seguir...
           st = NextToken(Expr, n, tk)
           
           s_TblSimb(k).Valor = st
           s_TblSimb(k).Token = tk
           k = (k + 1)
           s_TblSimb(k).Valor = ")"
           s_TblSimb(k).Token = ATRIBCHAR_DELIMITADOR_CIERRA
       YSiNo
           // introduccir los datos del token en la tabla de símbolos.
           s_TblSimb(k).Valor = st
           s_TblSimb(k).Token = tk
       Fin si

       k = (k + 1)
   Siguiente
   
   devolver k
fin Funcion


Ahor aprocede poner como sería la función para obtener el siguiente token... es también muy simple, ya que de entrada cada token ocupa un único carácter... y tenemos pocos tokens distintos.

// NOTA: Se considera token de 1 solo carácter
//    operando:     [±] A-Z|a-z|0-9
//    operador:     *|/|+|-
//    parentesis:    (|)
//  Para algo más exahustivo, habría que reconocer:
//    - identificador y número
//    - operadores de 1 o más símbolos (como en '>=')
// OJO: No se verifica si se alcanza el límite de la expresión,
//   lo cual puede suceder con expresiones mal formadas
//   (con caracteres no esperados a la derecha del último caracter válido).
// Los 3 parámetros son pasados por referencia...
string = funcion NextToken(string Expr, int Index, AtributosChar tkUltimo)
   string s
   AtributosChar ac
   
   Hacer
       s = Expr.Substring(Index, 1)   // tomamos el carácter en la posición index
       ac = s_Tabla(s.toByte)    // Evaluamos de qué tipo es el caracter.
       // en ciertos lenguajes caracter y byte se usan indistintamente, en otros marca error,
       // luego exige una conversión a bytes implícita, explícita, por casting o por coerción...
       Index += 1
   repetir mientras (ac = ATRIBCHAR_IGNORA) // saltar espacios
    // cualquier otro carácter no aceptado será detectado como error, tras la devolución.
   
   // Detectar si es un operador unario... Esto se sabe si hay otro operador delante.
   //  casos: *+2,  /-2,  +-4,  -+4,  (-1, +1    (total: 6 casos distintos)
   // es decir aparece un ± detrás de otro operador, de un paréntesis de apertura, o al comienzo de expresión.
   Si (ac = ATRIBCHAR_OPERADOR_PRECEDENCIA_2)  // solo signos +- que son los posibles unarios en esta implementación.
       Si ((tkUltimo <= ATRIBCHAR_DELIMITADOR_ABRE)  // es posible hacerlo así de simple,
            // porque se ha estudiado el orden de los tipos en la enumeración. Así acepta los 6 casos.
           ac = ATRIBCHAR_OPERADOR_UNARIO  
           //marcamos temporalmente como un token de operador unario,
       Fin si
   fin Si
   
   tkUltimo = ac
   Devolver s
Fin Funcion


Ahora toca hacer la función que implementa el algoritmo de la notación polaca inversa.
Para qien tenga bien a fondo conocimeinto en teoría de compiladores, básicamente puede lograr lo mismo mediante la técnica de 'compilación recursiva descendente'... que eso sería una analizado sintáctico...
Pero dado la sencillez d ela gramática usada, aquí se deja constancia de una sencilla implementación del algoritmo de Dijkstra (de Edsger Dijkstra, no nuestro forista: Dijsktra)

Como bien te han dicho una pila puede implementarse con un array, lo mismo que una cola, aquí incluso en un string... fíjate al caso que la diferencia entre pila y cola así usados será que la pila añade en orden inverso:
// cola: "A      ";  "An     "; "Ant    "; "Anti   "; "Antig  "; "Antigu "; "Antiguo"
// pila: "      A"; "     nA"; "    tnA"; "   itnA"; "  gitnA"; " ugitnA";  "ougitnA"

// Ini y fin, son el punto de la tabla de símbolos entre los que queramos analizar.
// Si siempre va a ser desde el comienzo, ini puede dejar de ser un parámetro para ser una variable interna de la función con valor 0.
// Fin en cualquier caso, indica el final, o para la situación anterior la cantidad-1 de tokens almacenados durante el análisis léxico.
string = Funcion DijkstraRPN(int Ini, int Fin)
   AtributosChar AtChar As , PrevTkChar         // tipo de token.
   string cola, int ixCola                                // cola de operandos (y operadores) y su puntero.
   string pila, int ixPila                                  // pila de operadores y su puntero
   int IxMax =   (Fin - Ini + 1)
   
   ixPila = (IxMax + 1)
   ixCola = 0  // 1, si el lenguaje considera el primer carácter de un string, como 1.
   // creamos el espacio máximo de cada string, en realidad cola, nunca crece mucho...
   // Si se opera con arrays de chars, incluso mejor, cuando el lenguaje no supone pérdida de eficiencia en conversiones 'tontas' entre char y byte.
   // la reserva de espacio en el string, al giaul que en un array, previene que la modificación de su tamaño exija contruir y copiar el contenido en otro, como sucede con append, etc...
   pila = Espacios(IxMax)
   cola = espacios(IxMax)
   
   Hacer mientras (Ini <= Fin)
       AtChar = s_TblSimb(Ini).Token
       Seleccionar  Caso para AtChar
           Caso ATRIBCHAR_OPERANDO   // accion: añadir a la cola
               cola.Replace(ixCola, 1) = s_TblSimb(Ini).Valor   // remplaza el carácter en la posición indicada.
               ixCola += 1                
           Caso ATRIBCHAR_DELIMITADOR_ABRE  // accion: Añadir a la pila.
               ixPila -= 1
               pila.Replace(ixPila, 1) = s_TblSimb(Ini).Valor
           Caso ATRIBCHAR_DELIMITADOR_CIERRA
               // Accion: mover operadores de la pila a la cola, hasta que
               //   se encuentre el paréntesis de apertura de su mismo anidamiento.
               Hacer mientras (s_Tabla(pila.Substring(ixPila, 1).ToByte) <> ATRIBCHAR_DELIMITADOR_ABRE)
                   cola.Replace(ixCola, 1) = pila.Substring(ixPila, 1)  // mover elemento a la cola
                   ixCola += 1
                   pila.Replace(ixPila, 1) = " "   // eliminar de la pila (basta poner un espacio)
                   ixPila += 1
                   si (ixPila = IxMax) Salir del bucle
               Repetir
               
               pila.replace(ixPila, 1) = " "          // eliminar paréntesis de apertura encontrado.
               ixPila += 1
           Resto de casos // operadores: considerar precedencia.
               // Accion: Mover a la cola, mientras el operador en la pila siendo examinado
               // sea de menor o igual precedencia que el operador actual.
               Si (ixPila <= IxMax)  // es habitual que la pila quede vacía...
                   PrevTkChar = s_Tabla(pila.Substring(ixPila, 1).ToByte)

                   Hacer mientras (PrevTkChar <= AtChar)  // y (PrevTkChar <> ATRIBCHAR_DELIMITADOR_ABRE)), pero el diseño en la enumeración ya considera esto, con la previa condición.
                       cola.Replace(ixCola, 1) = pila.Substring(ixPila, 1)  // mover elemento a la cola
                       ixCola += 1
                       pila.Replace(ixPila, 1) = " " // eliminar de la pila (basta poner un espacio)
                       ixPila += 1
                       si (ixPila > IxMax) Salir del bucle
                       PrevTkChar = s_Tabla(pila.Substring(ixPila, 1).ToByte)
                   Repetir  // el bucle se parece bastante al anterior, pero no llegan a ser iguales...
               Fin si
               
               ixPila -= 1   // la pila crece hacia abajo...
               pila.Replace( ixPila, 1) = s_TblSimb(Ini).Valor
       Fin seleccion de casos
       imprimir cola tabulador pila  // solo para ver como evoluciona...
       Ini += 1
   Repetir
   
   // Pasar contenido restante de la pila a la cola (pero si quedan paréntesis = error).
   //   En realidad, no se espera este error, toda vez que pasó un scan léxico.
   //   Sin embargo se deja por si se decide modificar el algoritmo para aceptar directamente
   // el texto de la expresión como parámetro, e ignorar el scan léxico previo....
   pila = pila.Right(IxMax - ixPila + 1)  // la pila descarta los espacios a la izquierda...
   Si (pila.Contiene( "(")) = FALSE)
       cola.Replace(ixCola) = pila    // copia el contenido de la pila en la cola, a partir de la posición indicada.
       ixCola += pila.Size
       imprimir cola tabulador pila  // solo para ver el resultado final ...
       devolver cola.Left(ixCola - 1)   // devuelve el contenido de la cola, descartando los espacios a su derecha.
   fin si
fin funcion


Y finalmente como lo que se te pide es una calculadora, y no solo la conversión de la notación, pués hale esto completa el intérprete...

// Calcula el valor de una expresión postfija.
//   A - Se supone que es una expresión aritmética, donde todos los operandos son números.
//   B - Si se admite que fueran identificadores, se supone que estos o bien refieren direcciones de memoria o bien su valor se haya en una tabla hash (por ejemplo),
//     luego antes de guardar a la 'pila' se debe dereferenciar el identificador. Por ejemplo:   s_Temp(i) = tHash(identificador)
//     Por eso si el propósito es meramente un ejercicio, es preferible ceñirse al caso 'A', exclusivamente y usar solo dígitos.
// devuelve el valor calclado, como puede tener decimales... el array temporal conviene que así sea...
real = Funcion CalcularRPN(string RPN)
   int k, i, X, Y
   AtributosChar  tk
   string s
   real Temp(0 a 79) // mismo tamaño que dejamos para la tabla de símbolos, adaptar según necesidades..
   // incluso conviene mover este array al nivel del módulo...
   
   bucle para k desde 0 hasta RPN.Size-1   // nuevamente si el lenguaje trata el primer char de la cadena , como 1, ira de 1 a rpn.size
       s = RPN.Substring( k, 1)   // toma el enésimo carácter de la cadena (o array)
       tk = s_Tabla(s.ToByte)
       // Mientras se obtengan operandos se guardan en temp
       // cuando aparece un operador se toma los dos últimos operandos guardados y se opera con ellos
       Si (tk <= ATRIBCHAR_OPERADOR_MAX)
           // sacar dos últimos operandos de la pila
           i -= 2
           X = Temp(i)
           Y = Temp(i + 1)
           
           // calcular y almacenar en la pila.
           Seleccionar Caso para s
               Caso "*"
                   Temp(i) = (X * Y)
               Caso "/"
                   Temp(i) = (X / Y)
               Caso "+"
                   Temp(i) = (X + Y)
               Caso "-"
                   Temp(i) = (X - Y)
           fin seleccion casos
       Ysino // Osi (tk = ATRIBCHAR_OPERANDO)
           //  una expresión RPN (bien formada) solo tiene operandos y operadores.
           // leer y almacenar operandos hasta encontrar un operador...
           Temp(i) = s
       // YSiNo
        //  solo si se espera errores en caso de expresion malformada... activar el 'Osi' del caso anterior y activar este 'YSino'
       Fin Si
       i += 1
   Siguiente
   
   devolver Temp(0)  // i acabará valiendo 1
Fin funcion


Se invocaría como:

funcion Main (string command)
   string rpn
   real valor
   llamada a CrearTabla

   rpn = ExpToRPN(command)
   Si (rpn.size > 0)
       valor = CalcularRPN(rpn)
       imprimir rpn tabulador valor
   Ysino
       Mensaje "el texto de la expresion no es correcto..."
   fin si
fin funcion

string = Function ExpToRPN(string Expr )
   int k As Integer
   
   
   k = ScanLex(Expr)
   si (k = 0) devolver ""
   devolver DijkstraRPN(0, k - 1)
fin Funcion


Y solo resta algún ejemplo:
Expr Infija: 3+6*2
Expr Postfija: 362*+   Valor: 15

Expr Infija: 3+(6*2)
Expr Postfija: 362*+   Valor: 15

Expr Infija: (3+6)*2
Expr Postfija: 36+2*   18

Expr Infija: 9*3+2-5-4*3
Expr Postfija: 93*2+5-43*-  Valor: 12

Expr Infija: 3+4-5*7-(4/2)*3
Expr Postfija: 34+57*-42/3*-   valor: -34

Expr Infija: 5-3*8/2+(5-4/2)+(8+(5*3)-1+(6/3))+5*3
Expr Postfija: 538*2/-542/-+853*+1-63/++53*+   Valor: 35

Y un ejemplo con un operador unario (la misma expresión previa vale)
--------------------------------------------!!-3!!--------- (se ha añadido un signo - delante del 3.
Expr Infija: 5-3*8/2+(5-4/2)+(8+(5*-3)-1+(6/3))+5*3
Expr Postfija: 538*2/-542/-+8503-*+1-63/++53*+  Valor: 5

Y un ejemplo de la evolución, para que al iplementarlo, puedas ir verificando cada cosa:
Expr Infija: 5-3*8/2+(5-4/2)+(8+(5*3)-1+(6/3))+5*3

--- Cola ------------------------------------------------ Pila ---
-------------------------------------------------------------------
5                                                                        
5                                                                        -
53                                                                       -
53                                                                      *-
538                                                                     *-
538*                                                                    /-
538*2                                                                   /-
538*2/-                                                                  +
538*2/-                                                                 (+
538*2/-5                                                                (+
538*2/-5                                                               -(+
538*2/-54                                                              -(+
538*2/-54                                                             /-(+
538*2/-542                                                            /-(+
538*2/-542/-                                                             +
538*2/-542/-+                                                            +
538*2/-542/-+                                                           (+
538*2/-542/-+8                                                          (+
538*2/-542/-+8                                                         +(+
538*2/-542/-+8                                                        (+(+
538*2/-542/-+85                                                       (+(+
538*2/-542/-+85                                                      *(+(+
538*2/-542/-+853                                                     *(+(+
538*2/-542/-+853*                                                      +(+
538*2/-542/-+853*+                                                     -(+
538*2/-542/-+853*+1                                                    -(+
538*2/-542/-+853*+1-                                                   +(+
538*2/-542/-+853*+1-                                                  (+(+
538*2/-542/-+853*+1-6                                                 (+(+
538*2/-542/-+853*+1-6                                                /(+(+
538*2/-542/-+853*+1-63                                               /(+(+
538*2/-542/-+853*+1-63/                                                +(+
538*2/-542/-+853*+1-63/+                                                 +
538*2/-542/-+853*+1-63/++                                                +
538*2/-542/-+853*+1-63/++5                                               +
538*2/-542/-+853*+1-63/++5                                              *+
538*2/-542/-+853*+1-63/++53                                             *+
538*2/-542/-+853*+1-63/++53*+             *+
538*2/-542/-+853*+1-63/++53*+   35

Y bueno, como cada lenguaje tiene sus pecualiaridades, cualquiere que lo implemente en el de su interés, que considere que a veces hay siempre un ± 1 bailando por ahí...