[C con Clase] Tratamiento de cadenas

Alejandro alepelexo en yahoo.es
Mie Ene 30 15:28:10 CET 2008


¡Muchas gracias! Creo que trataré de usar la librería <cstring> y sus respectivas funciones, es la opción más simple, se adapta a todos los casos y es la que mejor comprendo (lo cual es muy importante). De nuevo gracias por tu ayuda.

Un saludo, Alejandro.

El pasado 2008-01-29 16:00:40, Steven escribió:
 
S> Hola Alejandro,
S> 
S> Alejandro wrote:
S> 
S> > ¡Hola lista! Tengo un pequeño problema con una función que realiza
S> > cierto tratamiento sobre una cadena. Éste es el código de la función:
S> >
S> 
S> [CORTE]
S> 
S> >
S> > Pues bien, lo que yo quiero es que me transforme una cadena del tipo
S> > "Vaya! %j le ha dado un buen golpe a %o!". Decha cadena estaría en un
S> > arcjivo de texto y lo que quiero es que sustituya los caracteres "%j"
S> > y "%o" por los nicks de un jugador y su oponente. Dichos nicks se
S> > introducen al principo del programa. Ahora voy a contar mi problema.
S> > Si la cadena es como dije y acaba con un caracter normal, no tengo
S> > ningún problema. Pero cuando la cadena que intento tratar acaba por
S> > "%o" o por "%j" se me añaden unas sopechosas símbolos al final de la
S> > cadena, tras un salto de línea. Supongamos que el nick del jugador es
S> > "Jug1" y el del oponente es "Opon". Pues si yo intento tratar la
S> > cadena "Vaya! Un gran ataque de %j golpea a %o!" el resultado es:
S> > "Vaya! Un gran ataque de Jug1 golpea a Opon!". Perfecto. Sin embargo,
S> > si yo intento tratar la cadena "Vaya! Un gran ataque de %j golpea a
S> > %o" el resultado es: "Vaya! Un gran ataque de Jug1 golpea a Opon
S> > w2s". Además de w2s me aparecen otros símbolos raros, hasta completar
S> > un total de cuatro. Dichos símbolos aparecen tras un salto de
S> > línea... ¿A qué se debe?
S> >
S> 
S> Tienes un error al usar 'auxiliar' cuando quieres asignar el valor de 0
S> inicialmente. Escribes:
S> 
S> for( int y = 0; auxiliar[y]; y++ )
S> {
S>   auxiliar[y] = 0;
S> }
S> 
S> Como 'auxiliar' no fue inicializado, éste contiene basura. Además, lo
S> que realmente quieres es usar el valor de 512, porque es el valor
S> máximo. Esto sería,
S> 
S> for( int y = 0; y < 512; y++ )
S> {
S>   auxiliar[y] = 0;
S> }
S> 
S> El otro problema es que no asignas el carácter nulo al final de la
S> cadena en 'definitiva'. Ten presente que estás construyendo una cadena
S> de caracteres desde cero y por tanto necesitas agregar un cero al final.
S> 
S> 
S> De todos modos, sugiero usar las funciones estándares de <cstring> para
S> realizar estas manipulaciones. Específicamente, las funciones 'strchr()'
S> y 'strncat()'. La primera sirve para buscar un carácter en una cadena y
S> la segunda para copiar x caracteres de una cadena al final de otra. El
S> esquema del algoritmo sería algo así:
S> 
S> 1.  Buscar '%' en la cadena: original
S> 2.  Copiar la subcadena de original hasta '%' al final de: resultado
S> 3.  Si el siguiente carácter es 'j', entonces
S> 4.     Copiar jugador.nombre al final de resultado
S> 5.  Si no y el siguiente carácter es 'o', entonces
S> 6.     Copiar oponente.nombre al final de resultado
S> 7.  Repetir los pasos #1-#6 hasta que lleguemos al final de original
S> 8.  Terminar( resultado )
S> 
S> Básicamente vamos encontrando y copiando subcadenas en la cadena
S> original. Estamos haciendo algo parecido a esto:
S> 
S> char szResultado[512];
S> 
S> strcpy( szResultado, "Vaya! " );
S> strcat( szResultado, jugador.nombre );
S> strcat( szResultado, " le ha dado un buen golpe a " );
S> strcat( szResultado, oponente.nombre );
S> strcat( szResultado, "!" );
S> 
S> 
S> Otra solución podría ser la siguiente. Encontrar cada pareja "%j" y "%o"
S> y sustituirlos por "%s". Posteriormente, invocamos 'sprintf()' pasando
S> las cadenas necesarias. El comportamiento sería el siguiente:
S> 
S> formato <- "Vaya! %j le ha dado un buen golpe a %o!"
S> 
S> Lo convertimos a:
S> 
S> "Vaya! %s le ha dado un buen golpe a %s!"
S> 
S> Ahora invocamos 'sprintf()':
S> 
S> sprintf( szResultado, formato, jugador.nombre, oponente.nombre );
S> 
S> Lo problemático sería saber cuáles y cuántos parámetros pasar a
S> 'sprintf()'. Si ya conoces los mensajes y los parámetros que existen,
S> entonces es sencillo. Si no, entonces tenemos que usar 'vsprintf()' y
S> construir una lista de parámetros. Como son cadenas de caracteres,
S> necesitamos un array de punteros a 'char'. Algo como,
S> 
S> char *lista[10];
S> 
S> switch( nParam )
S> {
S>   case 2:
S>     lista[0] = jugador.nombre;
S>     lista[1] = oponente.nombre;
S>   case 3:
S>     lista[0] = jugador1.nombre;
S>     lista[1] = jugador2.nombre;
S>     lista[2] = oponente.nombre;
S>   case 4:
S>     lista[0] = jugador1.nombre;
S>     lista[1] = jugador2.nombre;
S>     lista[2] = oponente1.nombre;
S>     lista[3] = oponente2.nombre;
S> }
S> 
S> sprintf( szResultado, formato, (va_list)lista );
S> 
S> Para una explicación de las macros de <cstdarg>, puedes consultar el
S> capítulo 20 yendo a:
S> http://c.conclase.net/curso/index.php?cap=020#PAR_VARIABLES  y su
S> referencia: http://c.conclase.net/librerias/libreria.php?lib=stdarg
S> 
S> 
S> Espero que esto te ayude.
S> 
S> Steven


Más información sobre la lista de distribución Cconclase