Programación estructurada

Procesamiento de archivos

Procesamiento de archivos

Las instrucciones que hemos usado hasta ahora (fscanf, fgets y fgetc) no son suficientes para procesar, de manera relativamente simple, un archivo de texto

 

Para hacerlo, utilizamos una instrucción nueva: strtok

 

Esta nueva función separa una cadena en tokens con base en uno o varios caracteres

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

El código del ejemplo abre un archivo con un formato prestablecido para después poder procesarlo

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Primero se abre el archivo, y se cierra eventualmente, como de costumbre

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Luego leemos el archivo línea por línea

 

En este punto no nos importa separar lo que cada línea contiene, eso lo haremos en el paso que sigue

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Para poder separar la cadena en tokens, utilizamos la función strtok, que recibe dos parámetros:

  1. Un apuntador a la cadena que se va a separar
  2. El caracter, o caracteres, que se van a usar como separador para dividir la cadena

 

La función regresa una cadena (un token, pues)

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Ojo con lo siguiente: la primera vez que se llama a strtok, se envía como parámetro la cadena que queremos separar

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Ojo con lo siguiente: la primera vez que se llama a strtok, se envía como parámetro la cadena que queremos separar

Para las llamadas subsecuentes que queramos hacer sobre la misma cadena, el parámetro que se envía es NULL

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Ojo con lo siguiente: la primera vez que se llama a strtok, se envía como parámetro la cadena que queremos separar

Para las llamadas subsecuentes que queramos hacer sobre la misma cadena, el parámetro que se envía es NULL

Esto es porque strtok funciona de manera similar a la lectura deun archivo, mantiene un contexto que indica en que parte de la cadena se queda al empezar a separarla

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

La cadena se sigue procesando hasta que no haya tokens nuevos, en cuyo caso la función regresa un valor NULL

Es en este punto en el que podemos procesar, finalmente, la información del archivo

En este ejemplo en particular, el procesamiento consiste en llevar la cuenta de las líneas que contiene el archivo junto con la suma de las horas y créditos de cada materia para mostrar un resumen de información en otra parte del programa

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

En términos muy generales podemos decir que el procesamiento de un archivo implica, cuando menos, dos ciclos:

  1. Uno para leer el archivo línea a línea
  2. Otro para leer cada línea token a token

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	FILE* archivo;
	char linea[1024];
	char *token;
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;
	int i=0;


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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			i=0;
			token = strtok(linea, ",");
			while (token != NULL) {
				if (i==0) {
					//El primer token es la UEA, no nos importa en este caso
					printf("Materia leida: %s\n", token);
				}
				if (i==1) {
					//El segundo token es la clave de la UEA, no nos importa en este caso
				}
				if (i==2) {
					//El tercer token es la cantidad de horas por UEA, este sí importa
					horas+=atoi(token);
				}
				if (i==3) {
					//El último token es la cantidad de créditos por UEA, este también importa
					creditos+=atoi(token);
				}
				token = strtok(NULL, ",");
				i++;
			}
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

En términos muy generales podemos decir que el procesamiento de un archivo implica, cuando menos, dos ciclos:

  1. Uno para leer el archivo línea a línea
  2. Otro para leer cada línea token a token

... y esa es la razón por la que tendrían que tener muy clara la forma de describir y ejecutar ciclos

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lineas.h"

int main()
{
	FILE* archivo;
	char linea[1024];
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;

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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			parseaLinea(archivo, linea, &horas, &creditos);
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Y aquí tienen una versión modular (con funciones, pues) del mismo programa

Procesamiento de archivos

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lineas.h"

int main()
{
	FILE* archivo;
	char linea[1024];
	int numero=0;
	float horas=0;
	float creditos=0;
	float promedioHoras=0;
	float promedioCreditos=0;

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

	if (archivo == NULL) {
		printf("El archivo no pudo ser abierto\n");
		return -1;
	}
	else {
		while (fgets(linea, sizeof(linea), archivo)!=NULL) {
			numero++;
			parseaLinea(archivo, linea, &horas, &creditos);
		}
		promedioHoras=horas/numero;
		promedioCreditos=creditos/numero;
		printf("\n");
		printf("El archivo contiene información de %d materias, que suman en total %.0f horas y %.0f créditos\n", numero, horas, creditos);
		printf("En promedio cada materia requiere %.02f horas de estudio a la semana y tiene tiene un valor de %.02f créditos", promedioHoras, promedioCreditos);
	}
	fclose(archivo);
	return 0;
}

Y aquí tienen una versión modular (con funciones, pues) del mismo programa

... y también tendrían que tener claro como abstraer funciones para poder dividir un problema en problemas más pequeños

Programación estructurada: Procesamiento de archivos

By Gilberto 🦁

Programación estructurada: Procesamiento de archivos

Procesamiento de archivos

  • 85