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