[Ayuda] Reemplazar String en un archivo

Iniciado por .:UND3R:., 4 Mayo 2016, 17:35 PM

0 Miembros y 2 Visitantes están viendo este tema.

HardForo

Creo puede funcionar para archivos binarios donde generalmente la cadena_a_reemplazar y el reemplazo son de longitudes iguales

Para un archivo de texto, podrias querer cambiar una palabra corta por una larga (con probabilidad de 50% de que ocurra) y creo tu programa dejaria un hueco con basura... me tocaria revisalor mejor.
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

AlbertoBSD

#11
Cita de: boctulus en  4 Mayo 2016, 20:10 PM
Creo puede funcionar para archivos binarios donde generalmente la cadena_a_reemplazar y el reemplazo son de longitudes iguales

Para un archivo de texto, podrias querer cambiar una palabra corta por una larga (con probabilidad de 50% de que ocurra) y creo tu programa dejaria un hueco con basura... me tocaria revisalor mejor.

Basura como tal no, pero si se concatenaría la cadena con algun valor adyacente. Y e programa hacia cosas raras, por ejemplo como el registro esta delimitado por Enter y si se borra este se concatenaría con el siguiente registro.

El siguiente codigo genera una base de datos random para prueba

#include<stdio.h>
#include<stdlib.h>

int main() {
FILE *f;
char *linea;
int i = 0,j;
int len,valor;
int max = 10000000;
time_t inicio, fin;
srand(time(NULL));
f = fopen("bd","w");
printf("Escribiendo archivo por favor espere son %i de registros\n",max);
inicio = time(NULL);
while(i < max) {
len = 40 + rand() % 20;
j = 0;
linea = calloc(len,1);
while(j < len) {
linea[j] = (char) 97 + rand()%26;
j++;
}
valor = rand();
fprintf(f,"%s*%i\n",linea,valor);
free(linea);
i++;
}
fin = time(NULL);
printf("tiempo de escritura %lu\n",fin-inicio);
fclose(f);
}



Tarda 52 segundos en escribir el archivo (En mi sistema) y incluye el tiempo de creacion del texto random, supongo que sera menor si el texto ya esta creado El archivo pesa sobre 500 MB
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

class_OpenGL

Es cierto. Se me olvidó mencionarlo. La basura se crearía cuando hay saltos de línea en archivos de texto, pues Windows usa salto de carro y salto de línea, mientras que otros sistemas operativos usan solo el salto de línea

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

.:UND3R:.

Cita de: class_OpenGL en  4 Mayo 2016, 20:23 PM
Es cierto. Se me olvidó mencionarlo. La basura se crearía cuando hay saltos de línea en archivos de texto, pues Windows usa salto de carro y salto de línea, mientras que otros sistemas operativos usan solo el salto de línea

Lo mio debe funcionar en GNU/Linux

Cita de: AlbertoBSD en  4 Mayo 2016, 19:08 PM
A ver implemente una forma de reescribir todo el archivo, me tome de la liberar de cambiar algunas cosas..

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include<sys/stat.h>

char **resultados;
char **lines;
char *nueva_linea;
int *map;

int count = 0;

char** str_split(char* a_str, const char a_delim){
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }
    count += last_comma < (a_str + strlen(a_str) - 1);
    count++;
    result = malloc(sizeof(char*) * count);
    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);
        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }
    return result;
}

off_t fsize(char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
return -1;
}

void mostrarProducto(){
int i;
printf("%i coincidencias encontradas...\n\n", count);
for(i = 0; i < count; i++){
printf("%i) %s\n", i+1, resultados[i]);
}
printf("Por favor, seleccione una opcion: ");
}

void seleccionarProducto(){
int nuevo_stock,opcion;

char** resultado_split;
scanf("%i", &opcion);
printf("%s", resultados[opcion-1]);

resultado_split = str_split(resultados[opcion-1], '*');

printf("\nEl stock actual del producto es: %s\nPor favor introduzca el nuevo stock:",resultado_split[1]);
scanf("%i", &nuevo_stock);
nueva_linea = calloc(20+strlen(resultado_split[0]),1);
sprintf(nueva_linea,"%s*%i",resultado_split[0],nuevo_stock);
free(resultado_split[2]);
free(resultado_split[1]);
free(resultado_split);
printf("%s", nueva_linea); // ACAA!! nueva_linea es la que debe reemplazar a
free(lines[map[opcion-1]]);
lines[map[opcion-1]] = nueva_linea;
}

void buscarProducto(char * codProducto){
FILE * fp;
char *file_buff;
    size_t len = 0;
int i = 0, j = 0;
len = fsize("bd");
file_buff =  calloc(len+1,sizeof(char));
fp = fopen("bd", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

fread(file_buff,sizeof(char),len,fp);
fclose(fp);
lines = str_split(file_buff,'\n');
memset(file_buff,0,len);
free(file_buff);
while(lines[i] != NULL) {
printf("Examinando linea %i: %s\n",i,lines[i]);
if(strstr(lines[i],codProducto) != NULL) {
printf("Coinciendia %s encontrada en linea %i, copiando apuntador a resultado %i\n",codProducto,i,count);
resultados = realloc(resultados,sizeof(char*)*count+1);
map = realloc(map,sizeof(int)*count+1);
resultados[count] = lines[i];
map[count] = i;
count++;
}
i++;
}
if(count != 0){
mostrarProducto(count);
seleccionarProducto();
}else{
printf("No se ha encontrado el producto!");
}
j = 0;
fp = fopen("bd","w");
while(j < i) {
fprintf(fp,"%s\n",lines[j]);
free(lines[j]);
j++;
}
fclose(fp);
    exit(EXIT_SUCCESS);
}


int main(){
buscarProducto("h65t");
exit(EXIT_SUCCESS);
}



Falla al momento de reescribir el campo seleccionado, todavía estoy depurando...



Muchísimas gracias  ;-) ;-) ;-)

Ha funcionado a la perfección, no puedo estar más que feliz, de verdad en general y para todos desde el fondo de mi MUCHAS GRACIAS, me agrada ver la disposición y ganas de ayudar, ya saben si tienen alguna duda que esté dentro de mi área, con gusto intentaré ayudar.

Gracias nuevamente  ;-) ;-) ;-)

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)

fary

Aunque ya se solucionó pongo otra alternativa: Mapear el archivo en la memoria.

saludos.
Un byte a la izquierda.

class_OpenGL

Cita de: fary en  5 Mayo 2016, 21:01 PM
Aunque ya se solucionó pongo otra alternativa: Mapear el archivo en la memoria.

saludos.

Eso ya se había propuesto, pero pensamos que si el archivo es demasiado grande, había que buscar otra solución

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

fary

Aunque el archivo sea grande se podría trabajar de la misma manera   :laugh:  swap.

Un byte a la izquierda.

class_OpenGL

Ahora que me doy cuenta, mi función estaba hecha una pena XDD.

Versión mejorada:
void insertar(FILE * archivo, unsigned int pos, const char *nueva_cadena, unsigned int longitud_cadena) {
   char *buffer = malloc(longitud_cadena);

   while(feof(archivo) != 0) {
       fseek(archivo, pos, SEEK_CUR); // Nos movemos por el archivo hasta la posición 'pos'
       fread((void *)buffer, sizeof(char), longitud_cadena, archivo);
       clearerr(archivo); // Por si hemos llegado al final del archivo...
       fseek(archivo, pos, SEEK_CUR);
       fwrite((const void *)nueva_cadena, sizeof(char), longitud_cadena, archivo);
       pos += longitud_cadena;
   }

   free(buffer);
}

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL