Problema al modificar registro en un archivo

Iniciado por Elyic, 18 Mayo 2017, 08:20 AM

0 Miembros y 1 Visitante están viendo este tema.

Elyic

Hola buenas noches, quisiera que me ayudaran con un problema que tengo al usar la funcion fseek para modificar cierto registro en un archivo txt, el problema es que cuando ingreso un "ID" que no sea 1, no me toma ninguna registro, si pudieran ayudarme se los agradeceria mucho :)

#include <iostream>
#include <conio>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <ctype.h>
FILE *FMaterial = NULL;
struct Material
{
int iID;
   char cNombre[25];
   int iExist;
   float fPrecioC;
   int iExistm;
   char cDescrip[30];
   float fPrecioV;
   int iEliminado;
};
void modificar()
{
clrscr();
Material material;
int auxID;
cout<<"ID Material: ";
cin>>auxID;
FMaterial = fopen("Material.txt","r+");
if (FMaterial == NULL)
{
cout<<"No hay registros en el archivo...\n";
}else
{
fseek(FMaterial, (long)(auxID-1)* sizeof(Material), 0);
fread(&material, sizeof(Material),1,FMaterial);
cout<<"Nombre: "material.cNombre<<"\n";
fclose(FMaterial);
}
}
void main()
{
modificar();
getch();
}

MAFUS

#1
Y una copia del archivo, sino no podemos probar.


Ahora que me fijo: buscas datos binarios en el archivo pero lo abres para texto, por eso tienes problemas a la hora de conseguir datos.

Elyic

Gracias por responder, que deberia cambiar en el codigo?
https://mega.nz/#!LgIzQQTT!2K7-cx9Hh5KuoaJDJFt77pwpyLEJn1glII4crufymLM
Aqui dejo el archivo de texto de donde intento sacar los datos, solo tiene 2 registros.

MAFUS

#3
Vale, tienes un pequeño problema pero es muy engorroso. No es difícil de arreglar, pero sí que conlleva escribir bastante código y a estructuras más grandes más código a escribir.

Verás. Se llama memory padding, en español acomodación de la memoria. ¿De qué se trata?

C, y por extensión C++, vienen de un tiempo donde la memoria era algo precioso (escasa y cara) y los procesadores eran muy lentos por lo que el lenguaje mismo ayudaba a que los datos, estructuras, ocuparan lo mínimo posible pero al mismo tiempo que el acceso a sus datos fuera lo más rápido posible. Así que acomodaba los datos, no en el orden que había dictado el programador, sino que hacía que quedaran múltiplos al tamaño de palabra del procesador y con el menor número de huecos posibles. Ya, suena complicado, para entenderlo te invito a que profundices en manejo de memoria por parte de C.

¿En qué te afecta? Cuando tienes una estructura y la quieres copiar toda de una vez en un archivo C, y por extensión C++, copiará literalmente esa porción de memoria en el archivo y lo hará todo lo desordenada (para él ordenada) que sea, así que los campos en el disco no están como esperas. De esta forma cuándo vayas a sacarlos y copiarlos de nuevo a una estructura copiará tal cual del disco y lo situará en la porción de memoria que tienes byte a byte. Un desastre.

¿Qué puedes hacer? Existen extensiones del compilador, y por tanto no es portable el código, que aseguran que en memoria los datos van a estar tal cual lo has escrito en el código.
O
Una forma más portable, es copiar uno a uno los campos de la estructura en el disco y, a la hora de leerlos, adquirirlos uno a uno llenando así la estructura destino.

Elyic

Muchisimas gracias por la ayuda/explicacion, te cuento que pude arreglar el error gracias a lo que me dijiste de que estaba buscando datos en binario, cambie la forma de guardar los datos envés de usar ".txt" lo cambie a ".bin".
Adjunto el codigo para que veas lo que modifique.
Ingreso
#include <iostream>
#include <conio>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <ctype.h>
FILE *FMaterial = NULL;
struct Material
{
int iID;
   char cNombre[25];
   int iExist;
   float fPrecioC;
   int iExistm;
   char cDescrip[30];
   float fPrecioV;
   int iEliminado;
};
void vingresomat()
{
Material material;
   clrscr();
   fflush(stdin);
   cout<<"\t||=====Ingreso de datos=====\n";
   cout<<"\t||Nombre: ";
   fgets(material.cNombre,sizeof(material.cNombre),stdin);
   if(material.cNombre[strlen(material.cNombre)-1]=='\n')
   {
    material.cNombre[strlen(material.cNombre)-1] = '\0';
   }
   fflush(stdin);
   cout<<"\t||Existencia: ";
   cin>>material.iExist;
   fflush(stdin);
   cout<<"\t||Precio Costo: Q";
   cin>>material.fPrecioC;
   fflush(stdin);
   cout<<"\t||Existencia Minima: ";
   cin>>material.iExistm;
   cout<<"\t||Descripcion: ";
   fgets(material.cDescrip,sizeof(material.cDescrip),stdin);
   if(material.cDescrip[strlen(material.cDescrip)-1] == '\n')
   {
    material.cDescrip[strlen(material.cDescrip)-1] = '\0';
   }
   cout<<"\t||Precio de Venta: Q";
   cin>>material.fPrecioV;
   material.iEliminado=0;
   FMaterial = fopen("Material.bin", "r");
   if(FMaterial==NULL)
   {
    FMaterial = fopen("Material.bin","a+b");
      material.iID=1;
      fwrite(&material,sizeof(Material),1,FMaterial);
      fclose(FMaterial);
   }else
   {
    fclose(FMaterial);
      FMaterial=fopen("Material.bin","a+b");
      fseek(FMaterial,0,SEEK_END);
      material.iID=(ftell(FMaterial)/sizeof(Material))+1;
      rewind(FMaterial);
      fwrite(&material,sizeof(Material),1,FMaterial);
      fclose(FMaterial);
   }
}
void main()
{
   vingresomat();
getch();
}

Mostrar
#include <iostream>
#include <conio>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <ctype.h>
FILE *FMaterial = NULL;
struct Material
{
int iID;
   char cNombre[25];
   int iExist;
   float fPrecioC;
   int iExistm;
   char cDescrip[30];
   float fPrecioV;
   int iEliminado;
};
void vreportemat()
{
Material material;
clrscr();
   FMaterial = fopen("Material.bin", "r");
   if (FMaterial == NULL)
   {
    cout<<"No se han ingresado datos....\n";
   }else
   {
   cout<<"\t||=======Datos=======\n";
   fread(&material,sizeof(Material),1,FMaterial);
   while(feof(FMaterial)== 0)
   {
   if (material.iEliminado==0)
   {
   cout<<"\t||ID: "<<material.iID;
   cout<<"\n\t||Nombre: "<<material.cNombre;
   cout<<"\n\t||Existencia: "<<material.iExist;
   cout<<"\n\t||Precio Costo: Q."<<material.fPrecioC;
   cout<<"\n\t||Existencia Minima: "<<material.iExistm;
   cout<<"\n\t||Descripcion: "<<material.cDescrip;
   cout<<"\n\t||Precio de Venta: Q."<<material.fPrecioV;
   cout<<"\n\t||======================================\n";
   }
   fread(&material,sizeof(Material),1,FMaterial);
   }
   }
   fclose(FMaterial);
getch();
}
void main()
{
vreportemat();
}

Modificar
#include <iostream>
#include <conio>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <ctype.h>
FILE *FMaterial = NULL;
struct Material
{
int iID;
   char cNombre[25];
   int iExist;
   float fPrecioC;
   int iExistm;
   char cDescrip[30];
   float fPrecioV;
   int iEliminado;
};
void modificar()
{
clrscr();
Material material;
int auxID;
cout<<"ID Material: ";
cin>>auxID;
FMaterial = fopen("Material.bin","r+");
if (FMaterial == NULL)
{
cout<<"No hay registros en el archivo...\n";
}else
{
fseek(FMaterial, (long)(auxID-1)* sizeof(Material), 0);
fread(&material, sizeof(Material),1,FMaterial);
cout<<"Nombre: "<<material.cNombre<<"\n";
fclose(FMaterial);
}
}
void main()
{
modificar();
getch();
}