agrego practicas
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
/* =========================================================================
|
||||
* PROYECTO: Sistema de Registro y Telemetría para el Nanosatélite "Andrómeda-1"
|
||||
* -------------------------------------------------------------------------
|
||||
* CONTEXTO:
|
||||
* La Agencia Espacial Experimental está desarrollando el software de a bordo
|
||||
* para su próximo nanosatélite. El sistema necesita gestionar memoria de
|
||||
* forma dinámica y eficiente debido a los recursos limitados del microcontrolador
|
||||
* y a la naturaleza impredecible de las ráfagas de datos en órbita.
|
||||
*
|
||||
* OBJETIVO:
|
||||
* Diseñar e implementar un programa en lenguaje C que resuelva los siguientes
|
||||
* módulos de gestión de memoria dinámica requeridos por la estación de tierra:
|
||||
*
|
||||
* 1. Vector Dinámico Básico (Canales de Sensores):
|
||||
* Pide al operador un número N de canales activos, utiliza malloc para
|
||||
* reservar un arreglo de enteros con las lecturas iniciales, muéstralo en
|
||||
* consola y libera correctamente la memoria con free al terminar.
|
||||
*
|
||||
* 2. Cadenas Dinámicas (Identificadores de Misión):
|
||||
* Escribe una función que reciba una cadena estática (char *) con el nombre
|
||||
* de código del satélite, calcule su longitud exacta, reserve espacio
|
||||
* dinámicamente con malloc, copie la cadena y devuelva el nuevo puntero
|
||||
* dinámico para ser registrado en los logs del sistema.
|
||||
*
|
||||
* 3. Estructura Dinámica (Buffer de Archivos de Telemetría):
|
||||
* Define una struct Archivo que contenga dos campos: size_t tamano y
|
||||
* uint8_t *datos. Escribe una función que reciba el tamaño deseado y reserve
|
||||
* memoria dinámicamente tanto para la estructura en sí como para su búfer
|
||||
* interno de datos binarios.
|
||||
*
|
||||
* 4. Redimensionamiento con realloc (Stream de Datos en Tiempo Real):
|
||||
* Crea una rutina que lea números enteros (paquetes de telemetría) desde
|
||||
* la consola de forma indefinida hasta una condición de parada. Almacénalos
|
||||
* en un arreglo dinámico que duplique su tamaño cada vez que se llene
|
||||
* utilizando realloc para optimizar el almacenamiento.
|
||||
*
|
||||
* 5. Estructuras Anidadas Dinámicas (Subsistemas del Satélite):
|
||||
* Crea una estructura principal (por ejemplo, MisionEspacial) que contenga
|
||||
* un puntero a un arreglo dinámico de subestructuras (representando varios
|
||||
* subsistemas como energía, propulsión y comunicación). Asegúrate de
|
||||
* implementar un protocolo estricto de liberación en orden inverso
|
||||
* (primero las subestructuras internas y sus recursos, luego el arreglo
|
||||
* principal) para evitar fugas de memoria (memory leaks) críticas en órbita.
|
||||
*
|
||||
* REQUISITOS TÉCNICOS:
|
||||
* - Uso obligatorio de las funciones de <stdlib.h> (malloc, realloc, free).
|
||||
* - Validación de punteros (verificar que no sean NULL tras cada reserva).
|
||||
* - Código limpio, modularizado en funciones y bien comentado.
|
||||
* ========================================================================= */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct{
|
||||
size_t size;
|
||||
uint8_t *datos;
|
||||
}TelemetryFile;
|
||||
|
||||
typedef struct{
|
||||
TelemetryFile base;
|
||||
size_t offset;
|
||||
}TelemetryArray;
|
||||
|
||||
typedef struct{
|
||||
int n_chanels;
|
||||
int* chanels;
|
||||
TelemetryFile* telemetry_file;
|
||||
TelemetryArray telemetry_array;
|
||||
}ProgramData;
|
||||
|
||||
|
||||
void print_menu(ProgramData *);
|
||||
void print_data(ProgramData *);
|
||||
void get_nchanels(ProgramData *);
|
||||
void get_chanels(ProgramData *);
|
||||
|
||||
void get_telemetry_file(ProgramData *);
|
||||
TelemetryFile* telemetry_file_create(size_t fs);
|
||||
void telemetry_file_free(ProgramData *);
|
||||
|
||||
void get_telemetry_data(ProgramData *);
|
||||
bool telemetry_array_is_full(ProgramData *);
|
||||
void telemetry_array_alloc(ProgramData *);
|
||||
void telemetry_array_free(ProgramData *);
|
||||
void telemetry_array_set(ProgramData *, uint8_t data);
|
||||
|
||||
void free_data(ProgramData*);
|
||||
void pause(void);
|
||||
|
||||
|
||||
int main(void){
|
||||
|
||||
ProgramData data = {
|
||||
.n_chanels = 0,
|
||||
.chanels = NULL,
|
||||
.telemetry_file = NULL,
|
||||
.telemetry_array = {
|
||||
.base = {
|
||||
.size = 0,
|
||||
.datos = NULL
|
||||
},
|
||||
.offset = 0
|
||||
}
|
||||
};
|
||||
|
||||
print_menu(&data);
|
||||
|
||||
free_data(&data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_menu(ProgramData* ref_data){
|
||||
|
||||
int option = 0;
|
||||
int exit = 0;
|
||||
|
||||
system("clear");
|
||||
printf("MENU DE OPCIONES\n");
|
||||
printf("\t 1- Cargar canales\n");
|
||||
printf("\t 2- Mostrar Datos\n");
|
||||
printf("\t 3- Crear archivo de telemetría\n");
|
||||
printf("\t 4- Recibir telemetria\n");
|
||||
printf("\t 5- Salir\n");
|
||||
|
||||
scanf("%d", &option);
|
||||
|
||||
switch (option) {
|
||||
case 1:
|
||||
get_nchanels(ref_data);
|
||||
get_chanels(ref_data);
|
||||
break;
|
||||
case 2:
|
||||
print_data(ref_data);
|
||||
break;
|
||||
case 3:
|
||||
get_telemetry_file(ref_data);
|
||||
break;
|
||||
case 4:
|
||||
get_telemetry_data(ref_data);
|
||||
break;
|
||||
case 5:
|
||||
exit = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!exit){
|
||||
print_menu(ref_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void get_telemetry_data(ProgramData *ref_data){
|
||||
system("clear");
|
||||
printf("RECEPCION DE TELEMETRIA\n");
|
||||
uint8_t read_data;
|
||||
|
||||
do{
|
||||
printf("\nIngresar valor (0 para terminar):");
|
||||
scanf("%" SCNu8, &read_data);
|
||||
|
||||
//printf("Se ha leido: %" SCNu8 "\n", read_data);
|
||||
|
||||
if(read_data > 0){
|
||||
telemetry_array_set(ref_data, read_data);
|
||||
}
|
||||
|
||||
}while(read_data > 0);
|
||||
}
|
||||
|
||||
bool telemetry_array_is_full(ProgramData *ref_data){
|
||||
|
||||
uint8_t* start_add = ref_data->telemetry_array.base.datos;
|
||||
|
||||
if(start_add == NULL){
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* end_add = start_add + ref_data->telemetry_array.base.size;
|
||||
uint8_t* test_add = start_add + ref_data->telemetry_array.offset;
|
||||
return test_add >= (end_add);
|
||||
}
|
||||
|
||||
void telemetry_array_alloc(ProgramData *ref_data){
|
||||
//Si esta vacio reserva espacio para uno.
|
||||
if(ref_data->telemetry_array.base.datos == NULL){
|
||||
ref_data->telemetry_array.base.datos = malloc(sizeof(uint8_t));
|
||||
if(ref_data->telemetry_array.base.datos == NULL){
|
||||
perror("Error asignando memoria para streaming de telemetria.");
|
||||
exit(1);
|
||||
}
|
||||
ref_data->telemetry_array.base.size = 1;
|
||||
ref_data->telemetry_array.offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* result = realloc(ref_data->telemetry_array.base.datos, ref_data->telemetry_array.base.size * 2);
|
||||
|
||||
if(result == NULL){
|
||||
perror("Error reasignando memoria para streaming de telemetria.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ref_data->telemetry_array.base.datos = result;
|
||||
ref_data->telemetry_array.base.size *= 2;
|
||||
|
||||
printf("La nueva capacidad es: %zu \n", ref_data->telemetry_array.base.size);
|
||||
}
|
||||
|
||||
void telemetry_array_free(ProgramData *ref_data){
|
||||
if(ref_data->telemetry_array.base.datos == NULL){
|
||||
free(ref_data->telemetry_array.base.datos);
|
||||
ref_data->telemetry_array.base.datos = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void telemetry_array_set(ProgramData *ref_data, uint8_t data){
|
||||
if(telemetry_array_is_full(ref_data)){
|
||||
printf("Esta lleno, vamos a agrandar \n");
|
||||
telemetry_array_alloc(ref_data);
|
||||
}
|
||||
|
||||
*(ref_data->telemetry_array.base.datos + ref_data->telemetry_array.offset) = data;
|
||||
ref_data->telemetry_array.offset += 1;
|
||||
}
|
||||
|
||||
|
||||
void get_telemetry_file(ProgramData *ref_data){
|
||||
|
||||
size_t fs;
|
||||
|
||||
system("clear");
|
||||
|
||||
printf("CREAR ARCHIVO DE TELEMETRIA\n");
|
||||
printf("\tEnter de size in bytes:");
|
||||
scanf("%zu", &fs);
|
||||
|
||||
telemetry_file_free(ref_data);
|
||||
ref_data->telemetry_file = telemetry_file_create(fs);
|
||||
|
||||
}
|
||||
|
||||
void telemetry_file_free(ProgramData *ref_data){
|
||||
if(ref_data->telemetry_file != NULL){
|
||||
if(ref_data->telemetry_file->datos != NULL){
|
||||
free(ref_data->telemetry_file->datos);
|
||||
ref_data->telemetry_file->datos = NULL;
|
||||
}
|
||||
free(ref_data->telemetry_file);
|
||||
ref_data->telemetry_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TelemetryFile* telemetry_file_create(size_t fs){
|
||||
TelemetryFile* telemetry_file = malloc(sizeof(TelemetryFile));
|
||||
|
||||
if(telemetry_file == NULL){
|
||||
perror("Error creating telemetry file.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
telemetry_file->size = fs;
|
||||
telemetry_file->datos = malloc(sizeof(uint8_t)*fs);
|
||||
|
||||
if(telemetry_file->datos == NULL){
|
||||
free(telemetry_file);
|
||||
telemetry_file = NULL;
|
||||
perror("Error allocating memory for the buffer to telemetry file.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return telemetry_file;
|
||||
|
||||
}
|
||||
|
||||
void get_nchanels(ProgramData* ref_data){
|
||||
system("clear");
|
||||
int n_chanels = 0;
|
||||
printf("Cantidad de canales: ");
|
||||
scanf("%d", &n_chanels);
|
||||
|
||||
ref_data->n_chanels = n_chanels;
|
||||
|
||||
}
|
||||
|
||||
void get_chanels(ProgramData* ref_data){
|
||||
if(ref_data->chanels != NULL){
|
||||
free(ref_data->chanels);
|
||||
ref_data->chanels = NULL;
|
||||
}
|
||||
ref_data->chanels = malloc(sizeof(int)*ref_data->n_chanels);
|
||||
if(ref_data->chanels == NULL){
|
||||
perror("No se pudo reservar memoria para los canales.");
|
||||
exit(1);
|
||||
}
|
||||
for(int i=0; i < ref_data->n_chanels; i++){
|
||||
int chanel;
|
||||
printf("Frecuacia en Mhz del canal%d:", i);
|
||||
scanf("%d", &chanel);
|
||||
*(ref_data->chanels + i) = chanel;
|
||||
}
|
||||
}
|
||||
|
||||
void print_data(ProgramData* ref_data){
|
||||
system("clear");
|
||||
printf("DATOS DEL PROGRAMA\n");
|
||||
printf("Cantidad de canales: %d\n", ref_data->n_chanels);
|
||||
|
||||
for (int i=0; i < ref_data->n_chanels; i++){
|
||||
printf("\t CH %d Mhz\n", *(ref_data->chanels + i));
|
||||
}
|
||||
|
||||
if(ref_data->telemetry_file != NULL){
|
||||
printf("Archivo de telemetria creado. Size: %zu bytes.\n", ref_data->telemetry_file->size);
|
||||
}
|
||||
|
||||
printf("Datos de telemetria: ");
|
||||
for(size_t i=0; i < ref_data->telemetry_array.offset; i++){
|
||||
printf("%" SCNu8 ", ", *(ref_data->telemetry_array.base.datos + i));
|
||||
}
|
||||
if(ref_data->telemetry_array.base.size == 0){
|
||||
printf("No hay datos.");
|
||||
}
|
||||
printf("\n");
|
||||
pause();
|
||||
}
|
||||
|
||||
void free_data(ProgramData* ref_data){
|
||||
if(ref_data->chanels){
|
||||
free(ref_data->chanels);
|
||||
}
|
||||
telemetry_file_free(ref_data);
|
||||
telemetry_array_free(ref_data);
|
||||
}
|
||||
|
||||
void pause(void){
|
||||
// 1. Limpiamos el búfer por si quedó algún caracter pendiente del scanf anterior
|
||||
int c;
|
||||
while ((c = getchar()) != '\n' && c != EOF);
|
||||
// 2. Mostramos el mensaje y esperamos a que el usuario presione Enter de verdad
|
||||
printf("Presione Enter para continuar...\n");
|
||||
getchar();
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Reference in New Issue
Block a user