Ayuda

Iniciado por agustinp99, 10 Octubre 2019, 15:01 PM

0 Miembros y 1 Visitante están viendo este tema.

agustinp99

Hola buen dia, tengo una duda con un ejercicio que me dieron. Tengo que armar una calculadora de polaca inversa y estoy tratando de, a partir de la ecuación brindada por el usuario, tomar el primer numero, el segundo, luego el signo y asi sucesivamente. El problema es que no logro hacerlo, ya que no encuentro alguna funcion o algo que me detecte si el caracter es un numero o un signo (ya que si es un espacio lo salteo con un if antes). Si alguien puede tirarme algun consejo se lo agradeceria!

agustinp99

Esto es en codigo C

K-YreX

En vez de poner dos mensajes seguidos es mejor que modifiques el primero e incluyas lo que necesites.

Para lo que quieres hacer tienes una librería que es <ctype.h> en la que tienes funciones como <isdigit()>, <isspace()>, <ispunct()>, <isgraph()>, etc. Vamos, para saber qué tipo de carácter tienes.
Te dejo un enlace donde aparecen las funciones que tienes y una tabla para que veas qué caracteres se consideran de puntuación y cuáles se consideran graficables, etc.
http://www.cplusplus.com/reference/cctype/?kw=cctype
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

agustinp99

Uh perfecto, ahora averiguo bien. Muchisimas gracias

agustinp99

#4
Cita de: YreX-DwX en 10 Octubre 2019, 15:09 PM
En vez de poner dos mensajes seguidos es mejor que modifiques el primero e incluyas lo que necesites.

Para lo que quieres hacer tienes una librería que es <ctype.h> en la que tienes funciones como <isdigit()>, <isspace()>, <ispunct()>, <isgraph()>, etc. Vamos, para saber qué tipo de carácter tienes.
Te dejo un enlace donde aparecen las funciones que tienes y una tabla para que veas qué caracteres se consideran de puntuación y cuáles se consideran graficables, etc.
http://www.cplusplus.com/reference/cctype/?kw=cctype
Tengo otra duda, porque yo tengo que ingresar la ecuacion en notacion polaca al programa. Como puedo hacer para ir guardando el primer numero, el segundo y su signo? He visto que lo hacian con pilas pero mi profesor me dijo que lo trate de hacer de otra forma pero no me sale una idea

ESTO ES LO QUE VENIA PENSANDO

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
   char c[100];
   char str[10];
   int i;
   int u;
   printf ("Ingrese notacion polaca inversa: ");
   scanf ("%s",c);
      for (i=0;i<= strlen(c);i++){
         if (isdigit(c) && c!= " "){
         str=c;
         u++;
         }   
   }
   printf ("El numero guardado es %s", str);
   }

K-YreX

No está mal aunque hay que pulir un par de cosas:
Antes de nada, los códigos ponlos entre etiquetas de Código GeSHi porque sino los índices no se ven y la i entre corchetes se convierte en cursiva y la u entre corchetes, en subrayado...
  • Para pedir una cadena al usuario no se usa <scanf()>, se usa <fgets()>

    #define SIZE 100 // definimos un maximo de longitud para la cadena. Esto se pone justo despues de las librerias
    char cadena[SIZE];
    printf("Introduce una cadena: ");
    fgets(cadena, SIZE, stdin);

    El siguiente problema es que al introducir una cadena y pulsar ENTER, el ENTER también se guardará en la cadena. Esto lo arreglamos rápido así:

    cadena[strlen(cadena)-1] = '\0';

  • La segunda condición de tu bucle <while()> es innecesaria. Preguntas si <c> es un dígito Y si no es un espacio... Siempre que se cumpla que es un dígito, se cumplirá también que no es un espacio. Y si no es un dígito, la segunda condición dará igual.

    Si lo que quieres conseguir es el resultado de calcular la expresión en notación polaca inversa, te falta esa parte.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

dijsktra

#6
Cita de: agustinp99 en 10 Octubre 2019, 15:29 PM
Tengo otra duda, porque yo tengo que ingresar la ecuacion en notacion polaca al programa. Como puedo hacer para ir guardando el primer numero, el segundo y su signo? He visto que lo hacian con pilas pero mi profesor me dijo que lo trate de hacer de otra forma pero no me sale una idea


Las pilas por debajo están simuladas con vectores... O sea, que expones los vectores que se ocultarían en la implementación de una pila normalemente...

EDITO
En esta versión implemento un analizador de notación polaca inversa.
Esto es, primero los operandos y después el operador. Como en (3 4 -)


Código (cpp) [Seleccionar]

/*

An stack can be simulated by a vector

+-----+
|     |
+-----+ N
|  2  |
+-----+
|  1  |
+-----+
|  +  |
+-----+ 0


*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>

#define MAX 100000
#define DEBUG

int polish (const char V[][25], const int N)
{
  int n,top;
  int S[MAX];
  for( n=top=0;n<N;n++)
  {
#ifdef DEBUG
    int i;
    for(  i=n ; i < N ; i++) printf("%s ",V[i]);
    printf("\n\n");
#endif

    if (strtol(V[n],NULL,10))
      S[top++]=atoi(V[n]);
    else
      {
assert(top>1);
const int a = S[--top];
const int b = S[--top];
if (!strcmp(V[n],"+"))
  S[top++] = a + b;
else if (!strcmp(V[n],"-"))
  S[top++] = a - b;
else if (!strcmp(V[n],"*"))
  S[top++] = a * b;
else if (!strcmp(V[n],"/"))
       {
assert(!b);
S[top++] = a / b;
       }
      }
#ifdef DEBUG
    for(  i=0 ; i < top-1 ; i++) printf("%d ",S[i]);
    printf("%d\n\n",S[top-1]);
#endif
  };
  assert(top==1);
  return S[--top];
}


int main(int argc, char* args[])
{
  char V[MAX][25];

  int N;
  for(N=0;scanf("%s",V[N])==1 && strcmp(V[N],"\n");N++);
  printf("%d\n",polish(V,N));
  return 0;

}


Y un ejemplo de ejecuci'on. Para la expresi'on en notaci'on polaca

3 4 + 7 * 9 10 5 6 + * - -


En la ejecución se da la evoluición de la cadena de entrada y del estado de la pila...
3 4 + 7 * 9 10 5 6 + * - -

3

4 + 7 * 9 10 5 6 + * - -

3 4

+ 7 * 9 10 5 6 + * - -

7

7 * 9 10 5 6 + * - -

7 7

* 9 10 5 6 + * - -

49

9 10 5 6 + * - -

49 9

10 5 6 + * - -

49 9 10

5 6 + * - -

49 9 10 5

6 + * - -

49 9 10 5 6

+ * - -

49 9 10 11

* - -

49 9 110

- -

49 101

-

52





Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)

agustinp99

#7
Cita de: dijsktra en 11 Octubre 2019, 15:37 PM
Las pilas por debajo están simuladas con vectores... O sea, que expones los vectores que se ocultarían en la implementación de una pila normalemente...

¡Atención ! mi solución entiende que notación polaca es   + 3 4 , en lugar de 3 + 4 o 3 4 +.
(Solo hay que cambiar el orden de lectura de los operandos)

El programa solo evalua una expresion polaca metida correctamente... y sin parantesis...

no se puede + 3 (4+4) , sino que hay que escribir + 3 4 4 +

REPITO, no se si es lo que buscas...

Código (cpp) [Seleccionar]

/*

An stack can be simulated by a vector

+-----+
|     |
+-----+ N
|  2  |
+-----+
|  1  |
+-----+
|  +  |
+-----+ 0


*/


#include <cstdlib>
#include <iostream>
#include <cassert>
#include <cstring>

using namespace std;
int polish(char S[][25],  int N)
{
 for(N; N > 1 ; )
   {
     const int b = atoi(S[--N]);
     const int a = atoi(S[--N]);
     const char op = *S[--N];
     cout << b << " " << a <<  " " << op << endl;
     switch (op) {
     case '+': sprintf(S[N++],"%d",a+b);
break;
     case '-': sprintf(S[N++],"%d",a-b);
break;
     case '*': sprintf(S[N++],"%d",a*b);
break;
     case '/':
assert(b!=0);
sprintf(S[N++],"%d",a/b);
break;
     }
   }
 return atoi(S[N-1]);
}



#define MAX 100000
int main(int argc, char* args[])
{
 char S[MAX][25];
 int top ;
 for(top=0;scanf("%s",S[top])==1 && strcmp(S[top],"\n");top++ );
 printf("%d\n",polish(S,top));
 return 0;
}


Y un ejemplo de ejecuci'on.

Para la expresi'on en notaci'on polaca

- 15 + 1 * 2 + 3 4


el programa da
4 3 +
7 2 *
14 1 +
15 15 -
0



Hola!! Si me sirve un monton, te hago una pregunta nomas, que hace el args en el main? porque yo uso el argv pero nose si es lo mismo

Ademas de que no entiendo que hace el for de esa forma

agustinp99

Cita de: YreX-DwX en 11 Octubre 2019, 01:33 AM
No está mal aunque hay que pulir un par de cosas:
Antes de nada, los códigos ponlos entre etiquetas de Código GeSHi porque sino los índices no se ven y la i entre corchetes se convierte en cursiva y la u entre corchetes, en subrayado...
  • Para pedir una cadena al usuario no se usa <scanf()>, se usa <fgets()>

    #define SIZE 100 // definimos un maximo de longitud para la cadena. Esto se pone justo despues de las librerias
    char cadena[SIZE];
    printf("Introduce una cadena: ");
    fgets(cadena, SIZE, stdin);

    El siguiente problema es que al introducir una cadena y pulsar ENTER, el ENTER también se guardará en la cadena. Esto lo arreglamos rápido así:

    cadena[strlen(cadena)-1] = '\0';

  • La segunda condición de tu bucle <while()> es innecesaria. Preguntas si <c> es un dígito Y si no es un espacio... Siempre que se cumpla que es un dígito, se cumplirá también que no es un espacio. Y si no es un dígito, la segunda condición dará igual.

    Si lo que quieres conseguir es el resultado de calcular la expresión en notación polaca inversa, te falta esa parte.
Voy entendiendo, el problema es que sigo sin poder guardar lo numeros en alguna variable, ya que hago un for que vaya desde 1 hasta el argc y lo que quiero hacer ahora es preguntar si el argv es un digito(que eso sé como se hace) y luego, a partir de ese numero guardarlo en una variable entera, por ejemplo x. Al hacer esta iteracion con la condicion, si yo tengo mas de dos numeros ya la variable x tomaria solamente el ultimo y no se como hacer para poder guardar todo en distintas variables

K-YreX

La función <main()> puede recibir dos parámetros: un <int> y un <char*[]>. El primero indica el número de parámetros que le pasas al programa cuando lo ejecutas desde línea de comandos y el segundo es como una matriz donde cada fila es uno de los parámetros y cada columna es una letra. El nombre que le des da igual, siempre es lo mismo.

Como te han dicho, una pila internamente se puede implementar con un <array>. Entonces lo que tienes que hacer es un <array> de números en donde guardar los números hasta encontrar un operador. Yo estoy hablando para una notación polaca inversa, es decir, 3 4 +.
Te dejo el siguiente pseudocódigo. Esto es para que lo entiendas. Cuando entiendas cómo funciona tienes que pasarlo a C ya que el pseudocódigo no está escrito en C.

INICIO
    posicionActual := 0
    PEDIR expresion
    PARA i := 0 HASTA expresion.longitud - 1 HACER
        SEGUN expresion[i] HACER
            numero:
                numeros[posicionActual++] = expresion[i]
            +:
                numeros[posicionActual - 2] := numeros[posicionActual - 2] + numeros[posicionActual - 1]
                posicionActual := posicionActual - 2
            *:
                numeros[posicionActual - 2] := numeros[posicionActual - 2] + numeros[posicionActual - 1]
                posicionActual := posicionActual - 2

            //...igual para el resto de operadores

        FIN SEGUN
    FIN PARA

    MOSTRAR numeros[0]
FIN
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;