Programación estructurada

Archivos

Archivos

Hay diversas razones por las cuales necesitamos usar archivos en nuestros programas:

  • Reusabilidad
  • Portabilidad
  • Eficiencia
  • Capacidad de almacenamiento

 

En resumen, por permanencia

Archivos

En términos generales hay dos tipos de archivos:

  • Archivos de texto: contiene información en forma de caracteres ASCII
    • Cada línea termina con un caracter especial (\n o \r\n)
    •  Pueden leerse y modificarse con cualquier editor de text
  • Archivos binarios: contiene información en forma de caracteres binarios, almacenada más o menos de la misma manera en como se almacena en la memoria
    • Se crean dentro de programas específicos
    • No pueden leerse fácilmente

Archivos

Cuando operamos un archivo lo hacemos a través de un apuntador a la memoria de donde se almacena

 

El apuntador hace referencia, más específicamente, a una posición en particular de un archivo abierto

#include<stdio.h>

FILE* pointer_name;

Abrir archivos

FILE* fopen(const char *nombre_de_archivo, const char *modo_de_acceso);

Para abrir un archivo es necesario tener la ruta completa al mismo desde donde se ejecuta el programa así como especificar los modos de acceso adecuados

La función fopen() regresa un valor nulo si el archivo no se pudo abrir correctamente o un apuntador en caso contrario

Modo Descripción
r Abre el archivo de texto en modo lectura
rb Igual que el anterior pero el archivo se abre en modo binario
w Abre el archivo de texto en modo escritura. Si el archivo existe se sobre-escribe su contenido; si no existe, se crea
wb Igual que el anterior pero el archivo se abre en modo binario
a Abre el archivo de texto en modo escritura. Si el archivo existe el puntero se coloca al final del archivo; si no existe, se crea
ab Igual que el anterior pero el archivo se abre en modo binario
r+ Abre el archivo de texto en modo lectura y escritura. Si el archivo existe se sobre-escribe su contenido
rb+ Igual que el anterior pero el archivo se abre en modo binario
w+ Abre el archivo de texto en modo lectura y escritura. Si el archivo existe se sobre-escribe su contenido; si no existe, se crea
wb+ Igual que el anterior pero el archivo se abre en modo binario
a+ Abre el archivo de texto en modo lectura y escritura. Si el archivo existe el puntero se coloca al final del archivo; si no existe, se crea
ab+ Igual que el anterior pero el archivo se abre en modo binario

Abrir archivos

#include <stdio.h>

int main()
{
    FILE* archivo;

    archivo = fopen("prueba.txt", "r");

    if (archivo == NULL) {
        printf("El archivo no pudo ser abierto\n");
        return -1;
    }
    else {
        printf("El archivo sí pudo ser abierto");
    }

    return 0;
}

La respuesta va a depender de la existencia del archivo así como del modo que elijamos para abrirlo

Cerrar archivos

#include <stdio.h>

int main()
{
    FILE* archivo;

    archivo = fopen("prueba.txt", "r");

    if (archivo == NULL) {
        printf("El archivo no pudo ser abierto\n");
        return -1;
    }
    else {
        printf("El archivo sí pudo ser abierto");
    }

	fclose(archivo);
    return 0;
}

La instrucción fclose() cierra el archivo, deshace la referencia del apuntador y libera el espacio de memoria ocupado

 

Siempre, pero siempre, cierren sus archivos

Escribir en archivos

#include <stdio.h>

int main()
{
	FILE* archivo;

	archivo = fopen("prueba.txt", "w");

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		fprintf(archivo, "Una cadena con el número %d en ella\n", 5);
		fputs("Otra cadena más\n", archivo);
		fputc(5, archivo);
	}

	fclose(archivo);
	return 0;
}

Podemos escribir en un archivo con una de las siguientes instrucciones:

  • fprintf(): Se comporta como printf pero manda la salida a un archivo
  • fputs(): Escribe la línea completa, con un salto de línea al final, en un archivo
  • fputc(): Escribe un caracter en un archivo

Leer archivos

#include <stdio.h>

int main()
{
	FILE* archivo;
	char nombre[50];
	char apellido[50];
	int matricula;
	char linea[200];
	char caracter;

	archivo = fopen("prueba.txt", "r");

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		fscanf(archivo, "Nombre: %s\n", nombre);
		fscanf(archivo, "Apellido: %s\n", apellido);
		fscanf(archivo, "Matricula: %d\n", &matricula);
		printf("%d: %s %s\n\n", matricula, nombre, apellido);

		fgets(linea, 200, archivo);
		printf("%s", linea);

		fgets(linea, 200, archivo);
		printf("%s", linea);

		do {
			caracter = fgetc(archivo);
			putchar(caracter);
		}
		while (caracter != EOF);
	}

	fclose(archivo);
	return 0;
}

Podemos leer  un archivo con una de las siguientes instrucciones:

  • fscanf(): Se comporta como scanf pero manda la salida a un archivo
  • fgets(): Lee una línea completa, deteniéndose en un salto de línea, de un archivo
  • fgetc(): Lee un caracter de un archivo

 

La instrucción rewind(archivo) se utiliza para regresar el apuntador al inicio del archivo

Leer archivos

#include <stdio.h>

int main()
{
	FILE* archivo;
	char nombre[50];
	char apellido[50];
	int matricula;
	char linea[200];
	char caracter;

	archivo = fopen("prueba.txt", "r");

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, 200, archivo)!=NULL) {
			printf("%s", linea);
		}
	}

	fclose(archivo);
	return 0;
}

Como difícilmente podemos tener contol absoluto sobre los formatos de los archivos de entrada lo más normal es leer todo con ciclos y fgets()

Leer archivos

typedef struct {
	char nombre[50];
	char calificacion[2];
} materia;


typedef struct {
	char matricula[12];
	char nombre[100];
	char apellido[100];
	materia materias[60];
} estudiante;

¿Cómo convertirías un archivo de varios estudiantes, con el mismo formato del archivo prueba.txt en un arreglo de registros como el que se ve a la izquierda?