Ver Mensaje Individual
  #5 (permalink)  
Antiguo 23/03/2013, 12:47
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Buscar y reempalzar en c/c++.

Una propuesta: suponiendo que no quieres usar un char* extralargo para poder insertar todo lo que quieras, tienes que trabajar con punteros (que es a la conclusion que has llegado), de lo contrario no podras 'alargar' o 'recortar' para que el espacio se ajuste al texto.

La idea es la siguiente: creas un char* dinamico de x caracteres para que quepa la frase inicial (recuerda que todo lo que declaras dinamicamente tienes que liberarlo cuando ya no quieras usarlo), copias la frase inicial y ya tienes la base de trabajo:

Código:
char *texto;
int t;

t = strlen("En un bosque lleno de arboles quiero encontrar un arbol.");
texto = malloc(t+1);
texto[0] = '\0';
sprintf(texto, "En un bosque lleno de arboles quiero encontrar un arbol.");
En todo el codigo que voy a postear omito las comprovaciones de error, pero es muy importante que las implementes para el codigo final). Otra cosa, esta idea es solo para una coincidencia; para mas de una se hace lo mismo pero dentro de un bucle.

Ahora ya tienes la base de trabajo, determinas la palabra a buscar y el reemplazo:

Código:
char buscar[] = "encontrar";
char reemplazar[] = "ver";
Voy declarando las variables segun las voy usando, pero tendrian que estar declaradas arriba ok? En este caso declaro las palabras estaticas pero puedes preguntar por consola o lo que quieras.

Lo siguiente es identificar la palabra objetivo para calcular su longitud, y esta longitud se necesita para restarla de la longitud total de la frase actual para adaptarla al nuevo contenido:

Código:
char *pch;

pch = strstr(texto, buscar);
Esto me encuentra la primera conincidencia de la palabra; para hacer con multiples coincidencias tienes que hacer todo esto en un bucle hasta que el strstr no encuentre nada.

Luego reservas un poco de memoria para el texto que está detras de la palabra objetivo y que no vas a modificar para nada (si fuesen multiples coincidencias tampoco lo modificarias en el ciclo actual sino en los siguientes), en ese espacio copias el resto de la frase:

Código:
char *rem;

t = strlen(pch) - strlen(buscar);
rem = malloc(t+1);
rem[0] = '\0';
sprintf(rem, pch+strlen(buscar));
Ahora en la memoria resto tienes lo que hay entre el final de la palabra objetivo y el final de la frase. Con esto ya puedes redimensionar la base de trabajo para que se adapte al nuevo contenido:

Código:
char *mem;

t = strlen(texto) - strlen(pch) + strlen(reemplazar) + strlen(rem);
mem = realloc(texto, t+1);
texto = mem;
EL puntero 'mem' solo lo uso para hacer el realloc, y sobre ese puntero tienes que hacer una comprovacion de error (en caso de memoria insuficiente 'realloc' dará un 'mem' nulo con lo que puedes liberar 'texto' y salir, si por el contrario haces el realloc sobre 'texto' y te da un error de memoria no podras librerarlo porque te habrá retornado un puntero nulo).

Ahora me proparo el texto para trabajar facilmente constrcat (solo finalizo con un nulo), añado la palabra de reemplazo, añado el texto restante, libero el texto restante y ya lo tengo:

Código:
t = strlen(texto) - (strlen(buscar) + strlen(rem));
texto[t] = '\0';

strcat(texto, reemplazar);
t = strlen(texto);
strcat(texto, rem);
free(rem);
rem = 0;

printf("%s", texto);
Y justo antes de finalizar la aplicacion hago otro free para el 'texto'.

Esta es una forma de hacerlo, cuando lo hayas trabajado un poco encontrarás la forma elegante de hacerlo. Y para lo de multiples coincidencias con este metodo puedes usar un bucle limitado por el retorno de strstr o puedes complicarlo haciendo todas las substituciones a la vez con una lista de posiciones de coincidencias y restos de frase (no es imposible pero tampoco es facil).

Ten en cuenta que me he saltado todas las comprovaciones de error, en una aplicacion real no puedes olvidarlas.

Saludos
vosk