Autor
|
Tema: [C] Llenar archivo Binario, y borrar datos mayores al promedio (Leído 4,743 veces)
|
ramaa000
Desconectado
Mensajes: 2
|
Hola! Me presento, yo soy Ramaa000, armo este thread ya que estoy en problemas con este programita. Basicamente lo que sucede, es que cuando hago la impresion que debería mostrar el segundo archivo, ya cumpliendo lo que dice la consigna del programa (la dejo abajo en verde), se imprime el programa sin modificaciones. Espero me puedan ayudar. Desde ya gracias! /*Leer por teclado (o generar al azar) una serie de numeros enteros y guardarlos en un archivo binario, finalizando la carga con un -1. Luego se solicita realizar un borrado logico de los registros superiores al promedio del mismo. Imprimir el archivo antes y despues del proceso de borrado, sin mostrar los elementos eliminados*/
#include <stdio.h> #include<time.h> #include <stdlib.h> #pragma warning (disable:4996) void carga_normal(); void carga_random(); int promedio(int *prom); void borrar_prom(int prom); int main(){ int choice; FILE *arch1,*arch2; srand(time(NULL)); puts("¿Como quiere cargar los numeros?"); puts("Opcion 1: Por teclado"); puts("Opcion 2: Al azar"); puts("Cualquier opcion diferente terminará el programa"); printf("Escriba su eleccion:"); scanf("%d",&choice); switch(choice) { case 1: carga_normal(); break; case 2: carga_random(); break; default:printf("\n Programa terminado"); return 1; } arch1=fopen("nros.dat","rb"); if (arch1==NULL){ puts("El archivo no se pudo abrir correctamente"); return 1; } fread(&dato,sizeof(dato),1,arch1); while(!feof(arch1)){ printf("%4d",dato); fread(&dato,sizeof(dato),1,arch1); } fclose(arch1); printf("\n"); promedio(&prom); borrar_prom(prom); arch2=fopen("nrosact.dat","rb"); if(arch2==NULL){ puts("El archivo no se pudo abrir correctamente"); return 2; } fread(&dato,sizeof(dato),1,arch2); while(!feof(arch2)){ printf("%4d",dato); fread(&dato,sizeof(dato),1,arch2); } fclose(arch2); return 0; } //FUNCIÓN PARA CARGAR NUMERO A NUMERO void carga_normal(){ int dato; FILE *arch; arch=fopen("nros.dat","wb"); if (arch==NULL){ puts("No se ha podido abrir el archivo"); return; } printf("\nIntroduzca el dato, -1 para concluir la operacion: "); scanf("%d",&dato); while(dato!=-1){ fwrite(&dato,sizeof(dato),1,arch); printf("\nIntroduzca el dato, -1 para concluir la operacion: "); scanf("%d",&dato); } fclose(arch); } //FUNCIÓN PARA HACER CARGA RANDOM void carga_random(){ int dato; FILE *arch; arch=fopen("nros.dat","wb"); if (arch==NULL){ puts("No se ha podido abrir el archivo"); return; } dato=(int)rand()%101-1; while(dato!=-1){ fwrite(&dato,sizeof(dato),1,arch); dato=(int)rand()%101-1; } fclose(arch); }[/quote] [b]FUNCIÓN PARA CALCULAR EL PROMEDIO DE LOS REGISTROS[/b] [quote] int promedio(int *prom){ int dato,contador=0,suma=0; FILE *arch; arch=fopen("nros.dat","rb"); if (arch==NULL){ puts("No se ha podido abrir el archivo"); return -1; } fread(&dato,sizeof(dato),1,arch); while(!feof(arch)){ suma=suma+dato; contador++; fread(&dato,sizeof(dato),1,arch); } *prom=suma/contador; fclose(arch); return *prom; }[/quote] [b]FUNCIÓN PARA BORRAR SUPERIORES AL PROMEDIO[/b] [quote]void borrar_prom(int prom){ int dato,menosuno=-1; FILE *arch,*arch2; arch=fopen("nros.dat","rb+"); if (arch==NULL){ puts("No se ha podido abrir el archivo"); return; } arch2=fopen("nrosact.dat","wb"); if(arch2==NULL){ puts("No se ha podido abrir el archivo"); return; } fread(&dato,sizeof(dato),1,arch); while(!feof(arch)){ if (dato>prom){ fwrite(&menosuno,sizeof(menosuno),1,arch); fseek(arch,0,SEEK_CUR); } fread(&dato,sizeof(dato),1,arch); } fseek(arch,0,SEEK_SET); fread(&dato,sizeof(dato),1,arch); while(!feof(arch)){ if(dato!=-1){ fwrite(&dato,sizeof(dato),1,arch2); fseek(arch,0,SEEK_CUR); } fread(&dato,sizeof(dato),1,arch); } fclose(arch); fclose(arch2); }
Mod: al publicar código usa las etiquetas GeSHi, las quote son para citasRamaa000: @Mod, si, disculpas. Ví tu advertencia en otro tema, y vine a modificarlo. Gracias! EDITO. FINALMENTE PUDE RESOLVERLO Hice 2 cambios. No se cual de los dos dio efecto. El primero fue la función promedio no pasarle ningún dato por referencia, sino que dentro del main declaré un int prom, y le asigné a prom el valor devuelto por la función. Por otro lado, dentro de la función "borrar_prom" , realicé un fseek del archivo, retrocediendo un registro, y con el IRA posicionado en ese registro, ahí si pude cambiar el valor almacenado por un -1. Adjunto el código por si a alguien le sirve. void borrar_prom(int prom){ int dato,menosuno=-1; FILE *arch,*arch2; arch =fopen("nros.dat","rb+"); if (arch==NULL){ puts("No se ha podido abrir el archivo"); return; } arch2 =fopen("nrosact.dat","wb"); if(arch2==NULL){ puts("No se ha podido abrir el archivo"); return; } fread(&dato ,sizeof(dato ),1,arch ); if (dato>prom){ fseek(arch ,-1*(int)sizeof(dato ),SEEK_CUR ); fwrite(&menosuno ,sizeof(menosuno ),1,arch ); } fread(&dato ,sizeof(dato ),1,arch ); } fread(&dato ,sizeof(dato ),1,arch ); if(dato!=-1){ fwrite(&dato ,sizeof(dato ),1,arch2 ); } fread(&dato ,sizeof(dato ),1,arch ); } }
Gracias a los que se molestaron. SaludosPd. No obstante, me gustaría tener una explicación de porque se solucionó con ese fseek, el de la línea 17, ya que no me queda muy claro.
|
|
« Última modificación: 2 Marzo 2015, 20:57 pm por ramaa000 »
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
me gustaría tener una explicación de porque se solucionó con ese fseek, el de la línea 17, ya que no me queda muy claro. No debes utilizar feof para controlar el bucle de lectura de datos, en su lugar puedes utilizar el valor de retorno de la función fread con lo cual el bucle termina así: while (fread(&dato ,sizeof(dato ),1,arch ) == 1) if (dato > prom){ fseek(arch , -1 * (int) sizeof(dato ), SEEK_CUR ); fwrite(&menosuno , sizeof(menosuno ), 1, arch ); }
Es necesario utilizar fseek porque cada vez que lees/escribes en un archivo el indicador de posición de este avanza a la siguiente posición, si no fuera así y, por ejemplo, tratas de leer diez valores en las diez ocasiones leerías el mismo valor. En resumen con fread lees un valor, el indicador avanza a la siguiente posición, con fseek regresas a la posición del valor leído y finalmente con fwrite lo sobrescribes con un menos uno. Por ultimo la llamada a función:
Es inútil porque indica que a partir de la posición actual (indicada por SEEK_CUR) se desplace ... cero bytes (segundo argumento). Un saludo
|
|
|
En línea
|
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language
|
|
|
ramaa000
Desconectado
Mensajes: 2
|
Entiendo. Una pregunta, antes de este while, ¿es necesaria una lectura previa como con el feof? while (fread(&dato ,sizeof(dato ),1,arch ) == 1)
Por otro lado, no entiendo una cosa, la condicion dice que mientras fread() == 1, ¿Cómo es eso que el fread puede ser igual o distinto a 1? Porque te refieres explicitamente a la función fread, y no a la variable donde almaceno el valor (dato) . Me queda esa duda unicamente. Por otro lado te comento, tenía en mis apuntes lo siguiente: "Si luego de grabar un archivo, quiero leerlo, tengo que reposicionar el indicador haciendo un fseek." Solamente lo hice por eso, porque lo tomé de mis apuntes, aunque como bien dices, no le veo utilidad. Saludos, y gracias por tu código.
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
antes de este while, ¿es necesaria una lectura previa como con el feof? No es necesario, esa es una de las razones por las cuales no se recomienda feof: te obliga a duplicar las operaciones de lectura. En el caso que mencionas basta con una sola llamada fread la cual sirve como condición del bucle. Si te interesa ahondar sobre las razones para no usar feof te recomiendo utilizar el motor de búsqueda de los foros, encontraras una media docena de mensajes sobre ello. while (fread(&dato ,sizeof(dato ),1,arch ) == 1)
Por otro lado, no entiendo una cosa, la condicion dice que mientras fread() == 1, ¿Cómo es eso que el fread puede ser igual o distinto a 1? Porque te refieres explicitamente a la función fread, y no a la variable donde almaceno el valor (dato). Explico: la función fread trata de leer del stream indicado (cuarto argumento) el numero de elementos (tercer argumento) del tamaño indicado (en bytes, segundo argumento) y los almacena a partir de la dirección indicada (primer argumento). Su valor de retorno es el numero de elementos leídos con éxito y que en tu caso si es uno indica una lectura exitosa lo que nos lleva a olvidarnos de feof (si la función retorna cero ello indica que se activo el indicador de error o fin de archivo). Un saludo
|
|
|
En línea
|
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Borrar datos de un archivo escrito en php
PHP
|
Cerdo
|
0
|
1,981
|
28 Julio 2008, 05:48 am
por Cerdo
|
|
|
error en runtime leyendo datos de un archivo binario c++
Programación C/C++
|
winroot
|
2
|
2,969
|
16 Mayo 2010, 01:29 am
por winroot
|
|
|
Insertar datos en Archivo Binario
Programación C/C++
|
willy1855
|
7
|
5,302
|
16 Abril 2012, 05:27 am
por durasno
|
|
|
Pasar datos de un archivo binario a una lista dinamica
Programación C/C++
|
ezar147
|
3
|
3,636
|
10 Junio 2017, 01:07 am
por ezar147
|
|
|
Busco ayuda para encotrar datos relacionados al control Remoto en un archivo Binario de un TV led
Ingeniería Inversa
|
Osmelfb5
|
0
|
18,201
|
12 Marzo 2024, 22:35 pm
por Osmelfb5
|
|