El lenguaje C permite organizar datos complejos mediante el uso de estructuras (struct), enumeraciones (enum) y punteros. A continuación, se presentan diversas implementaciones técnicas que abarcan desde la definición de tipos de datos personalizados hasta la manipulación de arreglos de estructuras y el ordenamiento de información.
1. Estructuras para Representación de Calendarios
Para gestionar datos cronológicos, es común agrupar el nombre del mes, su abreviatura, la cantidad de días y un identificador numérico en un solo bloque lógico.
struct RegistroMes {
char nombre[12];
char abreviatura[4];
int dias;
int numeroMes;
};
Podemos inicializar un arreglo que contenga la información de todo el año y desarrollar funciones para procesar estos datos, como calcular el acumulado de días transcurridos hasta un mes específico.
#include <stdio.h>
typedef struct RegistroMes Mes;
int calcularDiasAcumulados(Mes *calendario, int mesLimite) {
int acumulador = 0;
if (mesLimite < 1 || mesLimite > 12) {
return -1;
}
for (int idx = 0; idx < mesLimite; idx++) {
acumulador += calendario[idx].dias;
}
return acumulador;
}
int main(void) {
Mes anio[12] = {
{"Enero", "ene", 31, 1}, {"Febrero", "feb", 28, 2},
{"Marzo", "mar", 31, 3}, {"Abril", "abr", 30, 4},
{"Mayo", "may", 31, 5}, {"Junio", "jun", 30, 6},
{"Julio", "jul", 31, 7}, {"Agosto", "ago", 31, 8},
{"Septiembre", "sep", 30, 9}, {"Octubre", "oct", 31, 10},
{"Noviembre", "nov", 30, 11}, {"Diciembre", "dic", 31, 12}
};
int limite = 3;
printf("Días transcurridos hasta el mes %d: %d\n", limite, calcularDiasAcumulados(anio, limite));
return 0;
}
2. Paso de Estructuras por Valor y por Referencia
Al trabajar con cálculos de rendimiento, como el consumo de combustible, podemos optar por pasar la estructura completa o un puntero a la misma. Pasar punteros es generalmente más eficiente en términos de memoria.
typedef struct {
float recorrido;
float galones;
float eficiencia;
} DatosConsumo;
// Retorno por valor
DatosConsumo calcularPorValor(DatosConsumo d) {
if (d.galones > 0)
d.eficiencia = d.recorrido / d.galones;
else
d.eficiencia = -1.0;
return d;
}
// Modificación por referencia (puntero)
void calcularPorReferencia(DatosConsumo *d) {
if (d->galones > 0)
d->eficiencia = d->recorrido / d->galones;
else
d->eficiencia = -1.0;
}
3. Uso de Tipos Enumerados
Las enumeraciones facilitan la legibilidad del código al asignar nombres simbólicos a valores enteros constantes.
#include <stdio.h>
enum Estado { FALSO, VERDADERO, INDETERMINADO };
int main(void) {
enum Estado flag = FALSO;
printf("Valores de enumeración: %d, ", flag);
flag = VERDADERO;
printf("%d, ", flag);
flag = INDETERMINADO;
printf("%d\n", flag);
return 0;
}
4. Gestión de Registros y Algoritmos de Ordenamiento
En aplicaciones de gestión bibliográfica, es necesario almacenar múltiples campos y permitir el ordenamiento basado en diferentes criterios (alfabético o numérico).
#include <stdio.h>
#include <string.h>
#define MAX_STR 40
#define MAX_LIBROS 50
struct Libro {
char titulo[MAX_STR];
char autor[MAX_STR];
float precio;
};
void ordenarPorTitulo(struct Libro *punteros[], int total) {
struct Libro *temp;
for (int i = 0; i < total - 1; i++) {
for (int j = i + 1; j < total; j++) {
if (strcmp(punteros[i]->titulo, punteros[j]->titulo) > 0) {
temp = punteros[i];
punteros[i] = punteros[j];
punteros[j] = temp;
}
}
}
}
void ordenarPorPrecio(struct Libro *punteros[], int total) {
struct Libro *temp;
for (int i = 0; i < total - 1; i++) {
for (int j = i + 1; j < total; j++) {
if (punteros[i]->precio > punteros[j]->precio) {
temp = punteros[i];
punteros[i] = punteros[j];
punteros[j] = temp;
}
}
}
}
5. Estructuras Anidadas y Procesamiento de Datos de Alumnos
C permite anidar estructuras para representar jerarquías de datos, como los nombres de una persona dentro de un registro de estudiante.
#include <stdio.h>
#define TAM_NOMBRE 20
#define NUM_NOTAS 3
struct Identidad {
char nombre[TAM_NOMBRE];
char apellido[TAM_NOMBRE];
};
struct Estudiante {
struct Identidad info;
float notas[NUM_NOTAS];
float promedio;
};
void calcularPromediosIndividuales(struct Estudiante lista[], int n) {
for (int i = 0; i < n; i++) {
float suma = 0;
for (int j = 0; j < NUM_NOTAS; j++) {
suma += lista[i].notas[j];
}
lista[i].promedio = suma / NUM_NOTAS;
}
}
void mostrarResultados(const struct Estudiante lista[], int n) {
float totalClase = 0;
for (int i = 0; i < n; i++) {
printf("Alumno: %s %s - Promedio: %.2f\n",
lista[i].info.nombre, lista[i].info.apellido, lista[i].promedio);
totalClase += lista[i].promedio;
}
printf("Promedio general de la clase: %.2f\n", totalClase / n);
}