[C con Clase] Tratamiento de cadenas

Steven R. Davidson vze266ft en verizon.net
Mie Ene 30 19:00:48 CET 2008


Hola Alejandro,

Alejandro wrote:

> ¡Hola lista! Cada vez me asusto más mirando lo que perdí en los
> escasos meses que dejé de programar... ¡ya no doy hecho ni la función
> que quiero. Tras decidir usar la idea de Steven de la librería
> cstring, me surjen ciertos problemas entre cadenas y punteros que me
> tiene algo descolocado. La función es ésta:
> 
> char* ModTexto(char inicial[128], int jug, int oponente)
> 

Como no vas a modificar el contenido de 'inicial', sugiero indicarlo 
anteponiendo 'const'. Esto sería: const char inicial[]

> Y en su interior, por partes, tengo ésto para resolverlo de la forma
> qe me aconsejó Steven:
> 
> 1.  Buscar '%' en la cadena: original
> 
>       char definitiva[128];//Cadena definitiva
>       int k, i, x;//Contadores
>       char busca = '%';//Caracter a buscar
>       
>       for(k = 0; inicial[k] != busca; k++);
> 

Ten cuidado con sobrepasar la cantidad máxima de caracteres de la cadena 
'inicial'. Sugiero comprobar si hemos llegado al final de la cadena o 
no. Esto sería,

for( k=0; inicial[k] && inicial[k] != busca; k++ );

Por otro lado, sugiero usar la función 'strchr()' que sirve exactamente 
para esto:

char *ptr;
...
ptr = strchr( inicial, '%' );

> 
> 
> 2.  Copiar la subcadena de original hasta '%' al final de: resultado
> (aquí se presenta el primer problema)
> 
>       strncat(definitiva, inicial, k);
> 

La función 'strncat()' funcionará correctamente la primera vez si 
'definitiva' contiene una cadena nula. Por ejemplo,

definitiva[0] = 0;

while( !bHemosTerminado )
{
   strncat( definitiva, inicial, k );
   ...
}

Esto es porque 'strncat()' busca el final de la cadena 'definitiva' lo 
cual implica buscar el carácter nulo.

> Como ya me da un problema, no sigo. A contnuación escribo "return
> definitiva" y lo que me devuelve es la cadea "a9D" o similar. No
> estoy seguro de cuál es el problema, pero intuyo que es algo
> relacionado con los punteros/cadenas/funciones que devuelven cadenas.
> Y como ya dije, hace varios meses que no programo y tengo algo
> olvidados esos temas... ¿Alguna ayuda?
> 

Sin ver el código, es algo difícil de ver claramente el problema. Sin 
embargo, tal y como has escrito el prototipo y el poco código que nos 
has dado, creo que sé cuál es el problema. Estás retornando un array local.

Recuerda que las variables locales son creadas al entrar en el ámbito y 
destruidas al terminar tal ámbito. Sospecho que tienes algo parecido a 
lo siguiente:

char *ModTexto( const char inicial[], int jug, int oponente )
{
   char definitiva[128];
   ...
   return definitiva;
}

El array es creado al ejecutar 'ModTexto()' y destruido al salirse de 
esta función. Al regresar, al punto de invocación, se retorna la 
dirección de memoria que es el array local 'definitiva'. Sin embargo, 
como este array deja de existir, tenemos un puntero inválido apuntando a 
una dirección arbitraria.

Tenemos dos soluciones:
1. Crear memoria dinámicamente y retornarla.
2. Aceptar un puntero como parámetro.

Sugiero usar el método #2. El prototipo sería,

char *ModTexto( char definitiva[], const char inicial[], int jug, int 
oponente )
{
   ...
   return definitiva;
}

Invocaríamos esta función de la siguiente manera:

int main()
{
   char szMensaje[128] = "Vaya! %j le ha dado un buen golpe a %o!";
   char szResultado[256];
   ...
   cout << ModTexto( szResultado, szMensaje, jugador, oponente ) << endl;
   ...
}


Espero que esto te ayude.

Steven







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