Foros del Web » Programación para mayores de 30 ;) » Programación General »

Ayuda con funcion C++

Estas en el tema de Ayuda con funcion C++ en el foro de Programación General en Foros del Web. Hola necesito q alguien me ayude, tengo una cadena de caracteres de la siguiente forma "f(X,Y,h(Y))" (por ejemplo) y necesito contar el número de elementos ...
  #1 (permalink)  
Antiguo 28/12/2005, 17:07
 
Fecha de Ingreso: septiembre-2005
Ubicación: en el mundo
Mensajes: 41
Antigüedad: 18 años, 7 meses
Puntos: 0
Ayuda con funcion C++

Hola necesito q alguien me ayude, tengo una cadena de caracteres de la siguiente forma "f(X,Y,h(Y))" (por ejemplo) y necesito contar el número de elementos q forman esa funcion f, en este ejemplo serian 3; X, Y y h(Y). A ver si alguien pudiera echarme una mano.
Gracias.
  #2 (permalink)  
Antiguo 28/12/2005, 18:05
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 10 meses
Puntos: 2
Exclamación contar caracteres

Hola.

Espero te sirva mi consejo. Al parecer estas programando funciones matematicas o algo asi.

como sea, siempre vas a tener el problema de reconocer los elementos anidados entre parentesis.

Yo en tu lugar programaria varias funciones dedicadas al manejo de expresiones entre parentesis.

Una de tales funciones seria por ejemplo:

int detectbrackets(char s[], int &A, int &B)

Esta funcion deberia tomar una cadena s, y reconocer el primer parentesis que aparece en ella, y escribir la posicion de dicho caracter en la variable A.
cada parentesis que se ''abre'' '(' está apareado con uno que se ''cierra'' ')'.
La posicion donde se ''cierra'' el parentesis que se abrió en la posicion A, debe reconocerse, y ponerse en la posicion B.
La cuestione s como reconocer correctamente dicha posicion.

Lo que se puede hacer es definir una variable llamada 'nivel', en la cual se guarda la informacion del nivel de anidamiento de parentesis sn la cadena s, a medida que vamos recorriendo la cadena s.

Cuando encuentras el primer parentesis abierto '(', el nivel se pone a '1',
y se almacena la posicion del caracter '(' en A.
Luego se sigue inspeccionando la cadena s.
Si encuentras un nuevo parentesis abierto '(', significa que está anidado 'dentro' del que ya encontraste, y que entonces está en un nivel mas interno. Lo que se hace es incrementar el nivel a 2.

Cuando encuentras un parentesis cerrado ')´significa que se ha cerrado un nivel de anidamiento, y se hace decrecer el contador 'nivel' en 1.

Cuando encuentras un parentesis cerrado ')', y el contador 'nivel' ha llegado a '0', significa que has encontrado el parentesis apareado con el que estaba abierto en la poscion A.

Guardas la posicion de este caracter en la variable B.

La funcion seria esta:

int detectbrackets(char s[], int &A, int &B)
{
int i = 0;
int nivel = 0;

/* aqui se supone que la cadena 's' no tiene errores, y que */
/* el primer parentesis que aparece es uno abierto: '(´ */

/* Esta instruccion busca el primer parentesis abierto */
/* Me parece adecuado poner esta buqueda aparte del resto */

while((s[i]>0) && (s[i] != '(')) {
i++;
}

if (s[i] == 0) return -1; /* codigo de error: no hay parentesis en s */

A = i; /* posicion en s del primer '(' */

nivel = 1;
while((s[i]>0) && (nivel>0)) {
i++;
if (s[i] == '(') nivel++; /* aumenta el anidamiento de parentesis */
if (s[i] == ')') nivel--; /* se relaja el anidamiento de parentesis */
}

if (s[i] == 0) return -1; /* error en s: no se cierra el parentesis abierto */

B = i; /* posicion en s del ')' apareado con el '(' en A */

return 0; /* codigo de error nulo: no ha habido errores */
}



Me parece que la funcion que te escribi te va a ayudar mucho a reconocer parentesis en expresiones con parentesis anidados, ademas de ser muy simple.

Podrias modificarla para guardar informacion intermedia.

Para eso, en vez de usar dos variabels A y B, podrias usar un array s2, paralelo al array de caracteres s, en el cual vayas poniendo los numeritos de nivel, a medida que vayan apareciendo, y usar esa informacion en algun otro lugar.

Por ejemplo, si s es la cadena "f(X,Y,g(X))", tendrias algo como esto:


s == f ( X , Y , g ( X ) )
s2 = * 1 * * * * * 2 * 1 0


Despus de haber logrado el manejo de los parentesis, lo unico que tienes que hacer es utilizar los vaklores A y B dentro de las funciones de busqueda de subcadenas en cadenas dadas.

Por ejemplo, detectbrackets("f(X,Y,g(X))",A,B) te daria como resultado

A == 2 y B == 11

A continuacion, extraes los caracteres entre el 2 y el 11 de la cadena,
a saber, la cadena "X,Y,g(X)".

Lo que harias ahora seria buscar las sucesivas comas que separan los elementos X, Y y g(X).

Sin embargo, si te encuentras con algo como "X,Y,g(W,Z)", la coma que aparece en g(W,Z) está ''anidada" en el nivel 2 de parentesis.
Para detectar cuales comas son del nivel 1 y cuales son las de niveles anidados mas adentro, solo tienes que usar ideas parecidasd a las de la funcion parecida a detectbrackets, en donde ignorarias las comas que aparezcan mientras la variable 'nivel' es mayor que 0.

Espero haber dado en el clavo con esta respuesta, y disculpame si acaso no fui claro.
Me parece que la idea clave es manejar siempre los niveles de parentesis, y saber todo el tiempo en que nivel de anidamiento estás.

Saludos
  #3 (permalink)  
Antiguo 05/01/2006, 10:29
 
Fecha de Ingreso: septiembre-2005
Ubicación: en el mundo
Mensajes: 41
Antigüedad: 18 años, 7 meses
Puntos: 0
Muchas Gracias.
Tu funcion me ha servido de gran ayuda, la he modificado un poco de forma q detecto las comas q separan los elementos.
Gracias otra vez
  #4 (permalink)  
Antiguo 05/01/2006, 22:22
Usuario baneado!
 
Fecha de Ingreso: febrero-2005
Mensajes: 116
Antigüedad: 19 años, 2 meses
Puntos: 0
Yo no lo compliqué tanto, simplemente fui creando funciones que analizaban determinadas partes, y luego era recursivo. El estándar define bastantes niveles de recursividad garantizados, por lo que no iba a encontrar funciones más complicadas que ésas.
  #5 (permalink)  
Antiguo 06/01/2006, 10:59
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 18 años, 10 meses
Puntos: 2
.

Por un lado, desde un punto de vista teórico, cualquier procedimiento recursivo se puede convertir en iterativo, lo cual a veces puede ser conveniente en términos de recursos de la maquina, tiempo, y control de lo que uno está haciendo.

Por otro lado, en ciertos problemas el planteo recursivo es más deseable.
Sería bueno que digas qué librerias has usado para manejar la recursividad.

Aún así, la funcioncita que escribí me parece que es bien simple, no complicada, y que puede ayudar a salir del paso, y entender un poco como pueden resolverse este tipo de problemas, de reconocimiento de estructuras en una cadena de caracteres.
Pero tengo claro además que no es una solución del todo completa, y depende más que nada de lo que uno quiera hacer finalmente. Por eso hice hincapié en la ''idea'' de reconcoer los parentesis, y no en la funcion misma.

Más allá de todas estas cosillas, me parece que lo idóneo es meterse un poco en la teoría de los reconocedores sintácticos, que se usa para el desarrollo de compiladores.
Un libro antiguo que introduce ese tema a nivel básico es el famoso
de WIRTH, N.: "Algoritmos + Estructuras de Datos = Programas".

Está escrito en Pascal, pero es muy claro, así sin dificultad se puede pasar a C.

Me parece que todo lo que tenga que ver con reconocimiento de estructuras sintacticas debiera encaminarse por ese lado, teniendo en cuenta esa teoria, y poniendo atencion a las objeciones que WIRTH hace sobre los ''lenguajes'' que no presentan ''problemas'' (o sea, bien definidos, de manera tal que cuando lo implementamos en un programa, no caemos en loops infinitos o caminos sin salida).

Para salir del paso a la hora de reconocer funciones matematicas, es viable usar funciones de C caseras, que reconozcan los niveles de parentesis. Cuando se quiere hilar mas fino, conviene irse a la teoria de compiladores, que es bastante interesante y sistematica.
Uno pone las reglas, y lo demas se hace practicamente solo. Tal vez sea mas facil (por decirlo asi) hacer un compilador que alguna otra aplicacion demasiado especifica.

Tal vez lo recomendable seria definir una clase, o una familia de clases en C++, con las estrucutras y funciones basicas de un compilador de compiladores, mezclando las ideas del libro de WIRTH con la potencia del C++.
  #6 (permalink)  
Antiguo 06/01/2006, 16:23
Avatar de Mephisto  
Fecha de Ingreso: enero-2006
Ubicación: Mexico DF
Mensajes: 184
Antigüedad: 18 años, 4 meses
Puntos: 3
Como otra opcion para el reconocimientio de paréntesis anidados yo recomendaria el manejo de una pila. De hecho en libros de Estructuras de Datos se utiliza como ejemplo de uso de Pilas la identificacion de paréntesis aninados. Para mayor referencia pueden checar el libro de Estructuras de Datos en C/C++ de Tenenbaum...
__________________
Saludos...

Todos somos sabios, solo que en diferentes disciplinas...
  #7 (permalink)  
Antiguo 06/01/2006, 18:32
Usuario baneado!
 
Fecha de Ingreso: febrero-2005
Mensajes: 116
Antigüedad: 19 años, 2 meses
Puntos: 0
¿Qué librería? No hace falta usar ninguna librería para hacer algo recursivo... Simplemente llamas a la misma función. Es decir:

Si tenemos una función que toma una cadena como "4+5+(6*5)" y analiza si existe algún paréntesis, si los encuentra, vuelve a llamarse a si misma con la cadena "6*5", con lo que determinaría que ya no existen más paréntesis.

Que yo sepa, para algo tan sencillo no hace falta usar nada recursivo.

Por otra parte, recomiendo que lo haga en C++, se cree una serie de clases, como por ejemplo "Operador" y "Valor", que una "Expresion" contenga una sucesión de ellas en un vector, o similar. Ejemplo:

5 + 6 * 3

Se transformaría a Valor(5) Operador(+) Expresion(6*3)

A su vez, la última expresión sería Valor(6) Operador(*) Valor(3).

Después de tener esto listo, se pueden añadir otros operadores, variables, hacer rutinas de simplificación algebraica, etc.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 02:30.