Ver Mensaje Individual
  #2 (permalink)  
Antiguo 28/12/2005, 18:05
argentinator
 
Fecha de Ingreso: junio-2005
Ubicación: Argentina
Mensajes: 90
Antigüedad: 19 años, 9 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