[PC] Ayuda para C: Templates y variables.

Buenas, estoy intentando crear un programita un poco simple (aún estoy aprendiendo xd).

La cosa es que quiero hacer lo siguiente:

Modelo.txt (por ejemplo)
[%s], nombre
EDAD=%i, edad
ALTURA=%.2f, altura


Entonces, a partir de un programa que lea dicho modelo.txt y te pidiera que insertaras la variable nombre, edad, y altura, me gustaría saber como sustituir esas variables, y volver a crear un txt con los campos (%s con la variable nombre, %i con la variable edad, y %.2f con la variable altura) ya rellenados según lo que insertase, y siguiendo la misma estructura que tenía modelo.txt
#include <stdio.h>
#include <string.h>

int main()
{
   FILE *archivo_entrada, *archivo_salida;
   char *contenido_archivo, aux;
   long tamano_archivo = 0;
   char nombre[32];
   int edad;
   float altura;
   
   //Obtenemos los datos a insertar
   printf("Nombre: "); fgets(nombre,32,stdin); nombre[strlen(nombre)-1] = '\0';
   printf("Edad: "); scanf("%i",&edad);
   printf("Altura: "); scanf("%f",&altura);
   
   //Abrimos el archivo de plantilla
   archivo_entrada = fopen("modelo.txt","r");
   if(!archivo_entrada) {
      printf(">Error: No se puede abrir el archivo modelo.txt\n");
      return(1);
   }
   
   //Calculamos el tamaño del archivo
   while(!feof(archivo_entrada)) {
      fread(&aux,1,1,archivo_entrada);
      tamano_archivo++;
   }
   rewind(archivo_entrada);
   
   //Reservamos memoria suficiente
   contenido_archivo = (char *)(malloc(sizeof(char)*tamano_archivo));
   
   //Leemos el contenido del archivo y lo pasamos a una variable
   fread(contenido_archivo,tamano_archivo,1,archivo_entrada);
      
   //Cerramos el archivo ahora que ya no lo necesitamos
   fclose(archivo_entrada);
   
   //Abrimos el archivo de salida
   archivo_salida = fopen("modelonuevo.txt","w");
   if(!archivo_salida) {
      printf(">Error: No se puede crear el archivo modelonuevo.txt\n");
      return(1);
   }
   
   //Escribimos en el archivo de salida, utilizando como máscara el contenido del archivo
   //que hemos abierto antes
   fprintf(archivo_salida,contenido_archivo,nombre,edad,altura);
   
   //Cerramos el archivo de salida
   fclose(archivo_salida);
   
   //Liberamos la memoria que habíamos reservado
   free(contenido_archivo);
      
   
   return(0);
}
Muchas gracias, ahora lo probaré, a ver que tal.

¿Es realmente necesario reservar la memoria? Me refiero a cuando calculas el tamaño del archivo, y luego lo utilizas para reservar la memoria necesaria. ¿Que utilidad tiene esto? (¿o que ocurriría si no se usase?). Nunca lo había usado.

Por cierto, ¿qué diferencias hay entre las variables con * y las que no lo tienen?
   FILE *archivo_entrada, *archivo_salida;
   char *contenido_archivo, aux;


Un saludo.
periko_palote escribió:Por cierto, ¿qué diferencias hay entre las variables con * y las que no lo tienen?
   FILE *archivo_entrada, *archivo_salida;
   char *contenido_archivo, aux;


Un saludo.


las que tienen * son punteros, no es la variable en sí, sino apunta a la dirección de memoria donde se aloja el elemento.

Aquí tienes un tutorial por Jorge Walter Hefty de iniciación que puede ayudarte a entenderlo bien.

http://es.geocities.com/jorge_hefty/Basico.htm
Sí tio, mejor será que le eche un vistazo, por que lo de variables con punteros no lo he pillado del todo xd.

Gracias saulotmalo :).
En C tienes dos formas de manejar la memoria: de manera estática, dejando que el compilador se encargue de reservar y liberar la memoria automáticamente; y de manera dinámica, donde el programador debe hacerlo manualmente

La memoria estática se utiliza cuando conoces exactamente el tamaño máximo de los datos que se van a introducir en una variable. En el código que puse tenemos como ejemplo:
char nombre[32];
int edad;
float altura;

Ya sabemos que vamos a necesitar un número entero para la edad, un nº en coma flotante para la altura, y 32 caracteres como máximo para el nombre, así que simplemente declaramos las variables y el compilador se encarga automáticamente de reservar la memoria necesaria.


Sin embargo a veces no conocemos de antemano el tamaño de los datos que vamos a almacenar en una variable. Por ejemplo, ¿de que tamaño declaramos la variable contenido_archivo que va a almacenar los contenidos del archivo?
Si le ponemos 10000 caracteres y luego el archivo que abrimos tiene 15000, nuestro programa intentará poner los 5000 sobrantes en una zona de memoria que no le ha sido asignada y que podría pertenecer perfectamente a otro programa. En ese caso se producirá una violación de acceso a memoria y el sistema operativo responderá cerrando nuestro programa
También podría suceder lo contrario, reservamos 10000 bytes de memoria y luego resulta que el archivo sólo tiene 50. Es este caso estaremos desperdiciando inútilmente 9950 bytes que no están siendo utilizados y que no se pueden asignar a otro programa

La solución a este problema consiste en averiguar en tiempo de ejecución la memoria que vamos a necesitar y reservarla dinámicamente con el tamaño justo. Para ello vamos a utilizar un puntero:

char *contenido_archivo;


Para nuestro propósitos podemos definir un puntero como una etiqueta que apunta a una zona de memoria.

Dejamos aparcado de momento el puntero y procedemos a abrir el archivo y a calcular su tamaño. Con este dato ya sabemos cómo de grande tiene que ser nuestra variable para que quepa en ella el contenido completo del archivo

Con la función malloc reservamos un bloque de memoria suficientemente grande para nuestro archivo y lo asignamos al puntero que hemos definido
contenido_archivo = (char *)(malloc(sizeof(char)*tamano_archivo));

A partir de este momento podemos utilizar el puntero para hacer referencia a la dirección del bloque de memoria, o lo podemos utilizar como cualquier otra variable normal si le anteponemos el operador *

(NOTA: En C las cadenas de texto son en realidad un puntero al primer caracter de la cadena. Por eso en este ejemplo no utilizamos nunca el operador * con el puntero contenido_archivo; el propio puntero representa la cadena de texo)


Cuando hayamos terminado de utilizar el puntero debemos liberar la memoria. De lo contrario, esta memoria quedará marcada como reservada y no podrá ser utilizada para otros fines hasta que no finalice el programa
free(contenido_archivo);

(En este caso el programa acaba inmediatamente, así que la memoria se liberaría de todas maneras; no obstante en la mayoría de los casos no será así, así que hay que asegurarse de que cada instrucción malloc() tiene su correspondiente free(), cuando ya no necesitemos más la variable)



No sé si te habré aclarado mucho las cosas... la programación con punteros puede ser confusa, pero asegúrate de comprender bien cómo funcionan porque se utilizan constantemente en C


Saludos
muy completo ;) pero con el link que le he pasado entendería mejor la memoria
Gracias a los dos. Ya me ha quedado bastante más claro :)
7 respuestas