Foros del Web » Programación para mayores de 30 ;) » C/C++ »

No duplicar palabra al grabar en archivo [C]

Estas en el tema de No duplicar palabra al grabar en archivo [C] en el foro de C/C++ en Foros del Web. Hola gente, que tengan un muy buen día.- Continuando con mis estudios de archivos y a pesar de que la solución sea muy sencilla de ...
  #1 (permalink)  
Antiguo 30/03/2015, 12:26
rdv316
Invitado
 
Mensajes: n/a
Puntos:
No duplicar palabra al grabar en archivo [C]

Hola gente, que tengan un muy buen día.-
Continuando con mis estudios de archivos y a pesar de que la solución sea muy sencilla de descubrir, les confieso que estoy como en un bucle mental, no logro parar el láser en el lugar adecuado.-
El error lo tengo en la última función, necesito verificar que el ingreso no sea duplicado, pero si bien en la función buscar me funciona, en está no.-

Código:
#include <stdio.h>
#include <string.h>
#include <windows.h>

typedef struct{
    char marcado;
	char ingles[30];
	char espaniol[30];
}Traductor;

void mainMenu(FILE *ptrFile);
void agregar( FILE *ptrFile, Traductor *ptrTrad);
void buscar( FILE *ptrFile, Traductor *ptrTrad);
void listado( FILE *ptrFile, Traductor *ptrTrad);
int validarAgregar( FILE *ptrFile, Traductor *ptrTrad, char temp[], int verAgre);

int main(void){
	FILE *ptrFile;

	if( ( ptrFile = fopen("archivo.txt","a+") ) == NULL ){
		ferror( ptrFile );	
	}
	else{
		mainMenu(ptrFile);

		fclose(ptrFile);		
	}

	return 0;
}


void mainMenu(FILE *ptrFile){
	Traductor trad;
	int opc=0, ch, ok, registros;
	long tam;
	
	tam=sizeof(trad);
	fseek(ptrFile, 0, SEEK_END);
	registros=ftell(ptrFile)/tam;	
	
	while(opc != 4){
		do{
			system( "cls" );
			printf( " \n\n====== Men%c principal ======\n\n", 163 );
			printf( "  1 - Agregar\n" );
			printf( "  2 - Buscar\n" );
			printf( "  3 - Listado  ===> total %d registro(s)\n", registros);
			printf( "  4 - Salir\n" );
			printf( "\n\n  Elija opci%cn.......: ",162 );
			ok = scanf( "%d", &opc ) == 1 && opc >= 1 && opc <= 4;
			while ((ch = getchar()) != EOF && ch != '\n');
		}while(!ok);
	
		switch(opc){
			case 1 :
				agregar( ptrFile, &trad );
				break;
			case 2 :
				buscar( ptrFile, &trad );
				break;
			case 3 :
				listado( ptrFile, &trad );
				break;
			case 4 :
				break;
		}
	}
}

void agregar( FILE *ptrFile, Traductor *ptrTrad){
	int opcGd, ch, ok, verAgre=0;
	char *p = NULL, temp[30];
	
	do{
		printf("\n ingl%cs.......: ", 130);
		fgets(ptrTrad->ingles, 30, stdin);
		if((p=strchr(ptrTrad->ingles, '\n'))){
			*p='\0';
		}
		else{
			while((ch = getchar()) !='\n' && ch!=EOF);
		}
		ok = strlen(ptrTrad->ingles);
	}while(!ok);	

	strcpy(temp, ptrTrad->ingles);
	verAgre = validarAgregar( ptrFile, ptrTrad, temp, verAgre);
	if( verAgre == 0){
		do{
			printf("\n traducci%cn...: ", 162);
			fgets(ptrTrad->espaniol, 30, stdin);
			if((p=strchr(ptrTrad->espaniol, '\n'))){
				*p='\0';
			}
			else{
				while((ch = getchar()) !='\n' && ch!=EOF);
			}
			ok = strlen(ptrTrad->espaniol);
		}while(!ok);
		
		printf( "\n ======================================================" );
		printf( "\n 1 - Grabar" );
		printf( "\n 2 - Descartar" );

		do{
			printf( "\n\n Elija opci%cn......:", 162 );
			ok = scanf( "%d", &opcGd ) == 1 && opcGd >= 1 && opcGd <= 2;
			while ((ch = getchar()) != EOF && ch != '\n');
		}while(!ok);
	
		if(opcGd == 1){
			fwrite(ptrTrad, sizeof(Traductor), 1, ptrFile);
	
			if( ferror(ptrFile) ){
				printf( "\n No se pudo escribir en el archivo" );
			}
			else printf( "\n Los datos se an grabado.....");
		}
	
		printf("\n\n\n Pulse [Enter] para volver al men%c principal....", 163); getchar();
	}
	else{
		printf( "\n\n La palabra ya existe..." );
		printf("\n\n\n Pulse [Enter] para volver al men%c principal....", 163); getchar();
		mainMenu(ptrFile);
	}

}
	

void buscar( FILE *ptrFile, Traductor *ptrTrad){
	char buscar[30], *p = NULL;
	int ch, ok;
	
	do{
		printf("\n\n Ingrece palabra a traducir.......: ");
		fgets(buscar, 30, stdin);
		if((p=strchr(buscar, '\n'))){
			*p='\0';
		}
		else{
			while((ch = getchar()) !='\n' && ch!=EOF);
		}
		ok = strlen(buscar);
	}while(!ok);	

	
	rewind(ptrFile);
	while (fread(ptrTrad, sizeof(Traductor), 1, ptrFile) == 1){
		if( strstr(buscar, ptrTrad->espaniol) != NULL ){
			printf( "\n Traducido al ingl%cs..............: %s", 130, ptrTrad->ingles);
			ok=0;
			break;
		}
		else if( strstr(buscar, ptrTrad->ingles) != NULL ){
			printf( "\n Traducido al espa%col.............: %s", 164, ptrTrad->espaniol);
			ok=0;
			break;
		}	}
	if(ok > 0){
		printf( "\n No existe..." );
	}
	printf("\n\n\n Pulse [Enter] para volver al men%c principal....", 163); getchar();
}
	
	
void listado( FILE *ptrFile, Traductor *ptrTrad){
	int bandera=0;
	rewind(ptrFile);

	while (fread(ptrTrad, sizeof(Traductor), 1, ptrFile) == 1){
		if(bandera == 0){
			printf("\n  Ingl%cs       Espa%col", 130, 164);	
			bandera++;
		}
		printf("\n %7s %13s", ptrTrad->ingles, ptrTrad->espaniol);  
	}
	if(bandera == 0){
		printf("\n El archivo esta vacio.....");	
	}
	
	printf("\n\n Pulse [Enter] para volver al men%c principal...", 163); getchar();
}


int validarAgregar( FILE *ptrFile, Traductor *ptrTrad, char temp[], int verAgre){
	while (fread(ptrTrad, sizeof(Traductor), 1, ptrFile) == 1){
		if( strstr(temp, ptrTrad->ingles) != NULL ){
			verAgre = 1;
			break;
		}	
	}
	return verAgre;
}

Es todo, desde ya muchas gracias por el tiempo.-
Saludos.
Daniel
  #2 (permalink)  
Antiguo 30/03/2015, 15:45
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 6 meses
Puntos: 38
Respuesta: No duplicar palabra al grabar en archivo [C]

esa función no te funciona debido al modo de apertura del fichero. Como abres el archivo como "a+" al hacer esto, el puntero de lectura/escritura se sitúa al final del archivo ya que estas en modo añadir contenido extendido a lectura, al hacer una búsqueda es como si buscaras desde el final hacia adelante cosa que sabemos que lo único que hay después de la ultima traducción es el EOF y nunca te va dar duplicados aun que hayan, estas buscando después de todo. XD

Eso se soluciona poniendo un rewind(ptrFile) antes del bucle para que inicie la lectura desde el principio del fichero. Pero no te olvides que si vas a volver a escribir en el debes poner el puntero al final con fseek o lo que sea, si vas añadir más contenido.

Otra cosa que vi es que el archivo se queda lleno de residuos. Puedes arreglar eso cambiando Traductor trad; por Traductor trad = {0}; en la función mainMenu, Eso te crea la estructura limpia sin residuos que estén en la memoria.

No he probado a fondo el programa, pero con eso ya puedes seguir. =D
  #3 (permalink)  
Antiguo 30/03/2015, 16:48
rdv316
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: No duplicar palabra al grabar en archivo [C]

Hola vangodp.
Mil disculpas por no darme cuenta de una cosa tan elemental y más teniendo en cuenta que ya utilice rewind en la función búsqueda.-
Desconocía que después de una búsqueda tenia que poner el puntero al final del archivo, creí que fwrite lo hacía de forma automática, evidentemente tengo que releer sobre fwrite.-

Saludos.
Daniel
  #4 (permalink)  
Antiguo 30/03/2015, 17:05
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 6 meses
Puntos: 38
Respuesta: No duplicar palabra al grabar en archivo [C]

fwrite si lo pone al final y fread me parece que también lo hace o no estoy seguro... Ese es el problema si lees avanzas, si escribes avanzas.
Imaginemos que después de escribir en el fichero el puntero esta al final, lo que pasa es que al leer con fread estas leyendo desde donde se quedo con fwrite(desde el final).
Y por si fuera poco, cuando abres un archivo con los atributos "a+" estas diciendo que vas añadir contenido al final del fichero, y que también puedes leer ya que lo extendiste con el '+', puedes leer pero 'a' sitúa el puntero al final. El atributo W lo hace al principio destruyendo el fichero.
Todo se centra en tener claro en que modo de apertura estas y tener claro donde esta el puntero de escritura en todo el momento.
Si has escrito algo, el puntero avanza preparando se para una nueva escritura, luego si quiero buscar algo mejor seria abrirlo con el atributo "r", entonces el puntero se sitúa al principio, o puedo usar rewind para ponerlo al principio.

Eso es practicar y ya.

puedes abrir diferentes punteros en cada función y así no te lías, no olvides cerrarlos. Eso si.. me parece que no se puede crear indefinidos punteros a un archivo dependiendo de que sistema estés.

Puede que me haya equivocado en algo, pero muy lejo no anda el tiro.XD No soy un puto crack en C/C++ como los demás. XDD

Buen lugar para leer es aquí: http://www.c.conclase.net/ficheros/
  #5 (permalink)  
Antiguo 31/03/2015, 05:09
rdv316
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: No duplicar palabra al grabar en archivo [C]

Hola.
Cita:
Iniciado por vangodp Ver Mensaje
puedes abrir diferentes punteros en cada función y así no te lías, no olvides cerrarlos. Eso si.. me parece que no se puede crear indefinidos punteros a un archivo dependiendo de que sistema estés.
Muy interesante, no lo había leído en ninguna parte, bueno esto parece ser todo sobre este tema.-
Estoy leyendo sobre ordenar archivos y no me queda muy claro el asunto, estoy preparando un post nuevo con el tema, espero puedas(n) ayudarme.-

Muchas gracias por tú tiempo.-
Saludos.
Daniel

Etiquetas: char, duplicar, funcion, int, palabra
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:35.