elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Únete al Grupo Steam elhacker.NET


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [C] Llenar archivo Binario, y borrar datos mayores al promedio
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [C] Llenar archivo Binario, y borrar datos mayores al promedio  (Leído 4,395 veces)
ramaa000

Desconectado Desconectado

Mensajes: 2


Ver Perfil
[C] Llenar archivo Binario, y borrar datos mayores al promedio
« en: 2 Marzo 2015, 19:43 pm »

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*/



Código
  1. #include <stdio.h>
  2. #include<time.h>
  3. #include <stdlib.h>
  4. #pragma warning (disable:4996)
  5.  
  6. void carga_normal();
  7. void carga_random();
  8. int promedio(int *prom);
  9. void borrar_prom(int prom);
  10.  
  11. int main(){
  12. int choice;
  13. FILE *arch1,*arch2;
  14. srand(time(NULL));
  15.  
  16. puts("¿Como quiere cargar los numeros?");
  17. puts("Opcion 1: Por teclado");
  18. puts("Opcion 2: Al azar");
  19. puts("Cualquier opcion diferente terminará el programa");
  20. printf("Escriba su eleccion:");
  21. scanf("%d",&choice);
  22.  
  23. switch(choice)
  24. {
  25. case 1: carga_normal();
  26. break;
  27. case 2: carga_random();
  28. break;
  29. default:printf("\n Programa terminado");
  30. return 1;
  31. }
  32.  
  33. arch1=fopen("nros.dat","rb");
  34. if (arch1==NULL){
  35. puts("El archivo no se pudo abrir correctamente");
  36. return 1;
  37. }
  38. fread(&dato,sizeof(dato),1,arch1);
  39. while(!feof(arch1)){
  40. printf("%4d",dato);
  41. fread(&dato,sizeof(dato),1,arch1);
  42. }
  43. fclose(arch1);
  44.  
  45. printf("\n");
  46. promedio(&prom);
  47. borrar_prom(prom);
  48.  
  49. arch2=fopen("nrosact.dat","rb");
  50. if(arch2==NULL){
  51. puts("El archivo no se pudo abrir correctamente");
  52. return 2;
  53. }
  54.  
  55. fread(&dato,sizeof(dato),1,arch2);
  56. while(!feof(arch2)){
  57. printf("%4d",dato);
  58. fread(&dato,sizeof(dato),1,arch2);
  59. }
  60.  
  61. fclose(arch2);
  62. return 0;
  63. }
  64.  
  65. //FUNCIÓN PARA CARGAR NUMERO A NUMERO
  66.  
  67. void carga_normal(){
  68. int dato;
  69. FILE *arch;
  70. arch=fopen("nros.dat","wb");
  71. if (arch==NULL){
  72. puts("No se ha podido abrir el archivo");
  73. return;
  74. }
  75. printf("\nIntroduzca el dato, -1 para concluir la operacion: ");
  76. scanf("%d",&dato);
  77. while(dato!=-1){
  78. fwrite(&dato,sizeof(dato),1,arch);
  79. printf("\nIntroduzca el dato, -1 para concluir la operacion: ");
  80. scanf("%d",&dato);
  81. }
  82.  
  83. fclose(arch);
  84. }
  85.  
  86.  
  87. //FUNCIÓN PARA HACER CARGA RANDOM
  88.  
  89. void carga_random(){
  90. int dato;
  91. FILE *arch;
  92. arch=fopen("nros.dat","wb");
  93. if (arch==NULL){
  94. puts("No se ha podido abrir el archivo");
  95. return;
  96. }
  97. dato=(int)rand()%101-1;
  98. while(dato!=-1){
  99. fwrite(&dato,sizeof(dato),1,arch);
  100. dato=(int)rand()%101-1;
  101. }
  102. fclose(arch);
  103. }[/quote]
  104.  
  105. [b]FUNCIÓN PARA CALCULAR EL PROMEDIO DE LOS REGISTROS[/b]
  106. [quote]
  107. int promedio(int *prom){
  108. int dato,contador=0,suma=0;
  109. FILE *arch;
  110. arch=fopen("nros.dat","rb");
  111. if (arch==NULL){
  112. puts("No se ha podido abrir el archivo");
  113. return -1;
  114. }
  115.  
  116. fread(&dato,sizeof(dato),1,arch);
  117. while(!feof(arch)){
  118. suma=suma+dato;
  119. contador++;
  120. fread(&dato,sizeof(dato),1,arch);
  121. }
  122. *prom=suma/contador;
  123. fclose(arch);
  124. return *prom;
  125. }[/quote]
  126.  
  127. [b]FUNCIÓN PARA BORRAR SUPERIORES AL PROMEDIO[/b]
  128.  
  129. [quote]void borrar_prom(int prom){
  130. int dato,menosuno=-1;
  131. FILE *arch,*arch2;
  132. arch=fopen("nros.dat","rb+");
  133. if (arch==NULL){
  134. puts("No se ha podido abrir el archivo");
  135. return;
  136. }
  137. arch2=fopen("nrosact.dat","wb");
  138. if(arch2==NULL){
  139. puts("No se ha podido abrir el archivo");
  140. return;
  141. }
  142. fread(&dato,sizeof(dato),1,arch);
  143. while(!feof(arch)){
  144. if (dato>prom){
  145. fwrite(&menosuno,sizeof(menosuno),1,arch);
  146. fseek(arch,0,SEEK_CUR);
  147. }
  148. fread(&dato,sizeof(dato),1,arch);
  149. }
  150. fseek(arch,0,SEEK_SET);
  151. fread(&dato,sizeof(dato),1,arch);
  152.  
  153. while(!feof(arch)){
  154. if(dato!=-1){
  155. fwrite(&dato,sizeof(dato),1,arch2);
  156. fseek(arch,0,SEEK_CUR);
  157. }
  158. fread(&dato,sizeof(dato),1,arch);
  159. }
  160. fclose(arch);
  161. fclose(arch2);
  162. }

Mod: al publicar código usa las etiquetas GeSHi, las quote son para citas

Ramaa000: @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.

Código
  1. void borrar_prom(int prom){
  2. int dato,menosuno=-1;
  3. FILE *arch,*arch2;
  4. arch=fopen("nros.dat","rb+");
  5. if (arch==NULL){
  6. puts("No se ha podido abrir el archivo");
  7. return;
  8. }
  9. arch2=fopen("nrosact.dat","wb");
  10. if(arch2==NULL){
  11. puts("No se ha podido abrir el archivo");
  12. return;
  13. }
  14. fread(&dato,sizeof(dato),1,arch);
  15. while(!feof(arch)){
  16. if (dato>prom){
  17. fseek(arch,-1*(int)sizeof(dato),SEEK_CUR);
  18. fwrite(&menosuno,sizeof(menosuno),1,arch);
  19. fseek(arch,0,SEEK_CUR);
  20. }
  21. fread(&dato,sizeof(dato),1,arch);
  22. }
  23. fseek(arch,0,SEEK_SET);
  24. fread(&dato,sizeof(dato),1,arch);
  25.  
  26. while(!feof(arch)){
  27. if(dato!=-1){
  28. fwrite(&dato,sizeof(dato),1,arch2);
  29. fseek(arch,0,SEEK_CUR);
  30. }
  31. fread(&dato,sizeof(dato),1,arch);
  32. }
  33. fclose(arch);
  34. fclose(arch2);
  35. }

Gracias a los que se molestaron. Saludos

Pd. 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 Desconectado

Mensajes: 1.639


Ver Perfil
Re: [C] Llenar archivo Binario, y borrar datos mayores al promedio
« Respuesta #1 en: 4 Marzo 2015, 16:59 pm »

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í:
Código
  1. while (fread(&dato,sizeof(dato),1,arch) == 1)
  2.   if (dato > prom){
  3.      fseek(arch, -1 * (int) sizeof(dato), SEEK_CUR);
  4.      fwrite(&menosuno, sizeof(menosuno), 1, arch);
  5.   }

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:
Código
  1. fseek(arch,0,SEEK_CUR);
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 Desconectado

Mensajes: 2


Ver Perfil
Re: [C] Llenar archivo Binario, y borrar datos mayores al promedio
« Respuesta #2 en: 4 Marzo 2015, 18:42 pm »

Entiendo. Una pregunta, antes de este while, ¿es necesaria una lectura previa como con el feof?

Código
  1. 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 Desconectado

Mensajes: 1.639


Ver Perfil
Re: [C] Llenar archivo Binario, y borrar datos mayores al promedio
« Respuesta #3 en: 5 Marzo 2015, 02:57 am »

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.

Código
  1. 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
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines