Guardar/recuperar valor de variables en archivo

Estoy haciendo sobre inteligencia artificial en C++. Unas criaturas tratan de escapar de un depredador. La cosa es que me gustaría salvar la intentar de todas ellas (numero flotante guardado en criatura. X y criatura.Y)En un fichero de texto y poder volver a poner ese valor en la respectiva variable cuando ejecute el programa de nuevo, leyendo el archivo creado. Se como detectar la pulsación de una tecla para guardar los datos y como abrir un archivo para leer/escribir pero ni idea de como almacenar la información y ponerla de nuevo en su sitio.

2 respuestas

Respuesta
1
Escribir en un archivo puedes hacerlo de varias formas, lo más normal, cuando guardas valores numéricos, sería almacenarlos en formato binario. El archivo no sería de texto ni tratable desde un editor, pero es la forma en que el archivo te quedará con menores dimensiones. Para ello tienes dos funciones:
fwrite(dirección_dato,tamaño_dato,número_datos,fichero);
Por ejemplo, si tienes el dato en criatura]. POR y es de tipo float, puedes guardarlo en un archivo abierto para escritura así:
fwrite(&(criatura.X),sizeof(float),1,f);
donde 'f' es el fichero abierto para escritura (f=fopen("archivo.ext","w");).
Este mismo dato, lo podrás recuperar haciendo:
fread(&(criatura.X),sizeof(float),1,f);
donde ahora 'f' es un archivo abierto para lectura. (f=fopen("archivo.ext","r");)
Supongo que usas la función fopen para abrir los archivos.
Si quieres guardar los datos en formato texto, usa las funciones fprintf y fscanf, funcionan igual que printf y scanf, pero se especifica el archivo donde se almacenan las salidas/entradas, sustituyendo a la pantalla y el teclado. No recuerdo su sintaxis exacta, pero es muy fácil.
Puesto que tengo varias criaturas, ¿seria correcto escribir una función guardar() por ejemplo con algo como?:
void guardar(){
fichero=fopen("archivo.dat","w");
for (i=0;i<numero_criaturas;i++)
{
fwrite(&(criatura.X),sizeof(float),1,fichero);
fwrite(&(criatura.Y),sizeof(float),1,fichero);
}
}
y lo mismo para recuperarlos?
void cargar(){
fichero=fopen("archivo.dat","r");
for (i=0;i<numero_criaturas;i++)
{
fread(&(criatura.X),sizeof(float),1,fichero);
fread(&(criatura.Y),sizeof(float),1,fichero);
}
}
Al escribir con fwrite, ¿deja alguna separación entre cada valor? ¿Cómo detecta luego fread cuando acaba un valor y empieza el siguiente?
... ya lo haces bien, algo así es bastante correcto. La función fread lee los valores correctamente, puesto que le decimos (con sizeof(float)) el tamaño en bytes que debe leer en cada caso.
Puede que te vaya bien, si el número de criaturas es variable, que lo guardes en primera posición del archivo así:
fwrite(&numero_criaturas,sizeof(int),1,f);
Así, a la hora de leer, sacas primero ese valor y ya tendrás información acerca del número de datos almacenados... pero bueno, si no hay más que eso en el fichero, controlando el final del mismo también podrás hacerlo bien.
He encontrado algo en un libro. En C++ se usan los métodos read() y write() en vez de fwrite, fread. Al parecer para abrir el archivo binario (escritura)es ofstream nombre("fichero.dat", ios::out¦ios::binary) y luego nombre. write(puntero al dato,tamaño dato)
Lo voy a intentar con esas instrucciones. Si te parece finalizare tu respuesta en cuanto pruebe esto. Gracias de todos modos.Un saludo
Saludosl
He encontrado este código que hace exactamente lo que yo quiero hacer, salvo que necesito pasar a la función leer_datos el valor de una estructura:criatura. X y criatura. Y en vez de x:
void leer_datos(char *nombre,int elementos,float *x,float *y){
//abrir archivo
ifstream in(nombre,ios::binary);
//leer datos
for(int elem=0;elem<elementos;elem++){
in.read( (char *)&x[elem],sizeof(float) );
in.read( (char *)&y[elem],sizeof(float) );
}
}
y la funcion main:
main(){
int elementos=20;
float x[elementos],y[elementos];
leer_datos("fichero.dat",elementos,x,y);
}
Asi que en vez de x e y, que tengo que pasar a leer_datos?Valdria esto?
leer_datos("fichero.dat",elementos,criatura) y modificar leer_datos para que solo coja tres argumentos y dentro hacer:
for....
in.read( (char *)&criatura[elem].X,sizeof(float) );
in.read( (char *)&criatura[elem].Y,sizeof(float) );
No creo que funcione.(Ahora no tengo el programa aquí así que no puedo probarlo).Gracias.Un saludo
... modifica la función para que reciba los tres argumentos que comentas, hazlo de la siguiente manera:
void leer_datos(char *nombre, int elementos, tipo_criatura *criaturas)
{
...
}
y la llamas con:
leer_datos("nombre.ext",elementos,criatura);
Dentro de la misma, puedes hacer sin problemas el código que proponías, pues dispondrás del array de criaturas "tal cual"... aunque recuerda que este paso de parámetros es por referencia, cualquier modificación en el array (dentro de la función) afectará al original.
No, si hasta ahí todo bien. ¿El problema es cual es tipo_criatura?
Lo que tengo es criatura[num_elementos] que es una array de estructuras, cada una con dos valores punto flotante por e y a los que se accede como criatura. x o criatura.y, con i siendo un contador. ¿Así qué tipo_criatura que es? ¿Un array, una estructura? ¿Cómo lo paso a la función?
... tipo_criatura es el nombre de la estructura.
¿Si quisieras declarar otro array de estructuras de esas qué pondrías? Pues el mismo tipo que usarías es el que debes ponerle al parámetro...
Ejemplo:
struct punto
{
int x;
int y;
};
// para declarar un array de puntos haría...
struct punto p[20];
y para hacer una función que pueda recibir ese array pondría
void función(struct punto *p)
{
//tratando aquí dentro p como el array original.
}
Ok. Esa era mi duda, si se podría pasar una estructura como argumento a una función y luego dentro de ella podría tener acceso a todos sus elementos. No tengo el programa aquí así que no podía comprobarlo. Lo intentare esta tarde. Muchísimas gracias. Un saludo
...
Perdona. Solo una cosilla más. Todo funciona bien, solo que ademas de los arrays con la intentar POR e Y, tengo que pasar a grabar_datos y leer_datos un entero y me da error al pasarlo como un puntero (no puede convertir int a *int). ¿Lo he solucionado declarando esa variable que guarda el entero como una array de tamaño 1 y pasándolo como los demás.Hay alguna otra forma? ¿Cómo lo paso a la función: leer_datos("nombre.ext", elementos, criatura,?)
?
¿Qué pongo en la declaración de la función para que lo reciba? : void leer_datos(char *nombre, int elementos, tipo_criatura *criaturas,?)
Como lo proceso dentro de la funcion?: in.read( (char *)?????,sizeof(int) );
. Elementos también es int, pero como no tengo que grabar ni cargar su valor en el fichero no hay problema, es solo con el que quiero grabar/cargar.En resumen, como se pasa por referencia a una función algo que no es un array para grabar su valor en el fichero. Gracias (juro que finalizare tu respuesta después de esto)
... no lo he visto, pero apostaría que si dejas todo igual y en la llamada le pasas la dirección del entero (&variable_entera) que tú tengas, ya te funcionará.
Recuerda, de todos modos, que dentro de la función tendrás que referirte al contenido de la variable como *variable_entera, incluso en el código de la función.
Respuesta
-1
El tema de archivos es algo amplio para explicarlo aquí mejor te voy a pasar un curso bastante bueno
http://www.geocities.com/g_urrutia/
http://c.conclase.net/
Siento no pedertelo exoplicar estoy en exámenes finales

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas