Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Laboratorios de computación
salas A y B
Profesor: M.I. Edgar Tista García
Grupo: 01
No de Práctica(s): 04
Semestre: 2021-2
Observaciones:
CALIFICACIÓN:
__________
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
OBJETIVO DE LABORATORIO:
Utilizarás funciones en lenguaje C que permiten reservar y almacenar información
de manera dinámica (en tiempo de ejecución).
ACTIVIDAD 1
Código de la guía de Laboratorio “Malloc”
anterior se modificará el tamaño del apuntador actual al doble mediante la función Realloc,
se le asignará a otro apuntador, luego el nuevo apuntador se le asignará al apuntador
anterior y mediante un ciclo for se le pedirá al usuario que llene los espacios
faltantes/nuevos con valores, después otro for imprimirá el apuntador desde el primer valor
hasta los últimos agregados, ya al final se utiliza la función free para poder limpiar los
apuntadores designados a memoria dinámica. Se hizo uso de la biblioteca stdlib.h para
tener acceso a la funciones del sistema (cls, pause) y darle mejor formato al programa.
ACTIVIDAD 4
Código del ejercicio Propuesto “Malloc”
Primero que nada se tuvo que realizar una modificación al código ya que en la función
principal (main) no especificaba si era una función int, void, o char; una vez modificado
eso pasamos a ver la ejecución del código; lo que está haciendo este código es guardar en
memoria un arreglo de n espacios; sin embargo, al imprimir dicho arreglo se hacen dos
cosas, en primer lugar imprime la dirección de memoria dónde se encuentran almacenados
los valores contenidos en el arreglo los cuales se imprimirán dentro del ciclo for, en segundo
lugar es al imprimir el contenido de dicho arreglo los primeros espacios imprimen los valores
ya establecidos en el renglón 5 pero después de eso imprime valores que contiene la
memoria previamente los cuáles no se establecieron por el usuario; en el siguiente ciclo for
lo que hace es imprimir las direcciones de memoria del apuntador *ptr destinado a memoria
dinámica y seguido de eso imprime los valores que se encuentran en ese apuntador los
cuales son “datos basura” que se encuentran en la memoria del sistema operativo.
ACTIVIDAD 4.b
Código del ejercicio Propuesto “Malloc” 1ra modificación.
ACTIVIDAD 4.c
Código del ejercicio Propuesto “Malloc” llenado de espacios.
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
(a) (b)
Figura 4.d.2 En la Figura (a) se muestran los valores y direcciones de
memoria al asignar con Realloc memoria al mismo apuntador; Figura (b) se
muestran valores y direcciones de memoria al asignar con Realloc memoria
a otro apuntador.
Lo que se hace en este código, es reasignar/modificar la memoria dinámica para
aumentar el tamaño de 10 a 20 espacios para ello se hace 2 procedimientos, el
primero es asignarle al mismo apuntadora modificar la nueva memoria (tal como en
la Figura 4.d.1) o la otra forma es asignarlo a un nuevo apuntador (también se
muestra en la Figura 4.d.1). Al momento de imprimir los valores y las direcciones de
memoria nos damos cuenta que, en la parte de las direcciones y valores, son las
mismas por lo que podemos suponer que el sistema operativo compara lo que se
quiere realizar y al ver que son iguales en todos sus “aspectos” este los trata por
igual y por eso nos da esos resultados; por lo tanto no importa que procedimiento
escojamos (asignar al mismo apuntador o uno nuevo) el resultado será el mismo.
ACTIVIDAD 5
Código del ejercicio Propuesto “Estructuras con memoria Dinámica”
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
Figura 5.3 Ejecución exitosa del Código Estructura con Memoria Dinámica
Al momento de compilar el código por primera vez nos arrojó errores dentro de la
biblioteca Alumno.h los cuáles se solucionaron, en la misma biblioteca, agregando
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
otras bibliotecas tales como stdlib.h y string.h, otra opción con la que podríamos
haber trabajado era solamente agregar a la biblioteca Alumno.h la biblioteca
string.h mientras que la otra agregarla directamente al archivo del código del
problema; además en el código del programa la función principal no se especificó
que tipo de función era (int, char, float, void), por lo que, al ver la forma en que
trabajaba dicha función main se le declaró como función tipo void ya que no
regresaba ningún valor. Una vez corregido estos problemas se volvió a compilar y
ejecutar el programa, obteniendo los resultados mostrados en la Figura5.3, dichos
resultados hacen referencia a la dirección de memoria en la que se encuentra cada
parte de los apuntadores de memoria dinámica; el primer “lote” se refiere al
apuntador con memoria dinámica malloc, el segundo al apuntador de memoria
dinámica tipo calloc mientras que el último es la “reestructuración” del apuntador
calloc para memoria dinámica realloc.
También, antes que se impriman las direcciones de memoria, se imprime el tamaño
de la estructura Alumno almacenada en memoria, su tamaño es 176 bytes, dicho
tamaño lo obtuvimos mediante la función sizeof el cual devuelve la cantidad en
bytes que ocupa un objeto en la memoria (variable, apuntador, arreglo, estructura,
etc.). Una vez impreso eso se hizo uso de funciones del sistema para poder pausar
y limpiar la pantalla de la terminal; acto seguido se empieza a ejecutar la parte en
que el usuario debe escribir/almacenar los datos necesarios del Alumno a crear.
Para ello en el código, en el archivo .c del primer envío, se agregó una función void
para realizar el llenado de datos, a dicha función se le pasaba como parámetro de
entrada el número total de alumnos a crear; dicho número se preguntaba en la
función principal (main), ya dentro de la función void llenado_datos se declaran
variables enteras y flotantes que hacen referencia a los valores numéricos de las
estructuras creadas (struct Alumno y struct Direccion), se declararon arreglos y
apuntadores de caracteres haciendo referencia a los datos tales como nombre,
apellido, colonia, etc. Y por último se declaro una variable de tipo Alumno junto con
un apuntador del mismo tipo, el apuntador se utilizó como arreglo dinámico calloc
con espacios a reservar iguales a la variable numero_alumnos (parámetro de
entrada a la función actual) y cada espacio tiene el tamaño de la estructura Alumno;
hecho eso se hizo uso de un ciclo for para que el usuario ingrese los datos por cada
alumno, aquellos datos que no son de tipo carácter, se almacenan de la forma
tradicional con un scanf, pero para los apuntadores de caracteres (obligatorios, más
adelante se explica por qué) se hace uso de la función setbuf, para limpiar lo que
exista en la memoria del siguiente renglón, y la fgets que nos permite almacenar de
forma directa toda una cadena de caracteres en un arreglo, después los
apuntadores de caracteres se igualaron con sus respectivos arreglos (*Nombre,
nombre[40]->Nombre=nombre), cabe destacar que para corroborar que el
copiado de la información en cada apuntador se hizo de manera correcta se realizó
lo siguiente, una variable de tipo entera nombrada longitud se iguala a la longitud
del enunciado del arreglo deseado para ello se ocupo la función
strlen(arreglo_deseado), después mediante un ciclo for y otra variable entera j se
realizó la impresión del apuntador (para mayor claridad dichas líneas de código
aparecen comentadas en el código); esto se realizó con cada apuntador de
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
caracteres, lo único que se hizo fue reutilizar las líneas explicadas anteriormente
cambiando los arreglos y apuntadores necesarios.
Una vez que ya se tenían almacenados los datos en las variables se igualó el
apuntador dinámico *(alumnos+i) a la función crearAlumno el cual se encarga de
pasar los datos almacenados en la función llenado_datos a las estructuras, para
ello se le pasa como parámetros de entrada las variables numéricas (de tipo int o
float) y los apuntadores de caracteres, se le pasan los apuntadores y no los arreglos
porque la función (previamente creada por el profesor) recibe apuntadores por eso
mismo se había igualado los apuntadores a los arreglos para que en estos se
almacenara la información y utilizarla en esta nueva función; ya dentro de la función
crearAlumno que es de tipo Alumno se declara otra variable de tipo Alumno y
mediante esta se empieza a “copiar” la información de los parámetros de entrada a
los miembros de las estructuras Alumno y Dirección. Terminado el copiado de
información regresa la variable alumnoCreado y se regresa a la función
llenado_datos y si el for ha concluido el siguiente paso es entrar a otro ciclo for en
el cual la información del apuntador *(alumnos+i) se guarda en una nueva variable,
también de tipo Alumno, alumnoPrint dicha variable se pasa como parámetro de
entrada a una función void imprimirAlumno la cuál su única finalidad es imprimir
los datos de cada alumno, para ello, una vez adentro de la función, se hace uso de
varios printf pero las variables a imprimir son alumnoPrint con la extensión del
miembro a imprimir mediante el operador punto.
Un punto importante a destacar es que las funciones, tanto de imprimirAlumno como
crearAlumno, les faltaban instrucciones ya que las existentes al inicio solo servían
para los miembros de la estructura Alumno pero no para la estructura Direccion para
ello se agregaron las líneas de código faltantes. Otro punto es que si se ocupa el
código postal como valor entero en ocasiones la impresión arroja basura de la
memoria sin embargo al momento de utilizarlo como tipo long no existe este error,
por ello mismo existe una línea comentada en los códigos donde código postal es
%ld.
Otra cosa importante es que se nos pide “idear” una forma en que se pueda liberar
la memoria sin hacer uso de la función free para ello lo que se hizo en el programa
es redimensionar aunque sea un apuntador dinámico, obviamente antes de
liberarlo, de tal forma que los espacios que fuera a utilizar fueran 0 y para corroborar
si esto sirve se hizo una impresión de pantalla de la dirección de memoria respecto
al apuntador después de haberlo redimensionado y obtuvimos que era 0 por lo tanto
no abarca ningún espacio de memoria.
ACTIVIDAD 5
Ejercicio 3 Propuesto por el profesor
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
a utilizar junto con las estructuras pero no se han declarado, la primera línea de
código es el uso de la biblioteca Computador.h, como se mencionó anteriormente
este archivo solo contiene las declaraciones de las funciones indicando qué tipo de
dato regreso junto qué datos/parámetros de entrada tiene y se declararon las
estructuras a utilizar dándoles un alias mediante typedef para no tener que escribir
struct seguido del nombre de la estructura cada vez que vayamos a utilizarla.
Continuando con la explicación del archivo .c, después de haber agregado la
biblioteca Computadora.h sigue la creación de las estructuras a emplear, son un
total de 5 estructuras sin embargo 4 de ellas están “de manera independiente”
mientras que la quinta encapsula a loas otras 4; la primera estructura declarada se
le puso el nombre de Procesador y contiene arreglos de caracteres, cada arreglo
hace referencia a una característica del CPU/Procesador de una computadora
(maraca, modelo y generación), la siguiente estructura con nombre Gráficos
contiene dos arreglos de caracteres los cuáles se refieren a datos sobre la tarjeta
de video (marca y modelo), la siguiente estructura llamada Almacenamiento
también tiene arreglos de tipos caracteres los cuales hacen referencia a algunas
características del tipo de disco duro (tipo del almacenamiento y cantidad de
almacenamiento), la 4ta estructura se le conoce como Componentes y al igual
que las anteriores estructuras tiene arreglos de tipo carácter los cuáles almacenarán
información respecto al tipo ancho de banda de internet, tipo de conectividad a
internet, la cantidad de RAM y por último a la resolución del monitor, para
concluir la última estructura es la más importante, recibe el nombre de
Computadora en esta se almacenan en cadenas de caracteres la marca, tipo de
computadora, uso de la computadora además de que contiene variables de los
tipos de estructuras mencionados anteriormente.
Una vez establecida cada estructura se continúa a la función “nombrada/llamada”
en la función main del 3er código ejercicio3.c, aquí lo que se hace es crear una
variable de tipo computadora CompuPrint y un apuntador computadora del mismo
tipo, dicho apuntador se le trabajará como memoria dinámica mediante calloc, las
posiciones a almacenar el puntador serán igual a la cantidad de computadoras que
se van a almacenar por eso mismo esta función recibe como parámetro de entrada
a la variable numero_computadoras entonces nuestro apuntador dinámico quedaría
de la siguiente forma computadora=calloc(numero_computadoras,
numero_computadoras*sizeof(Computadora)). Hecho lo anterior se declararon
dos variables enteras i y longitud, después se declararon un total de 14
apuntadores y 14 arreglos todos de caracteres (cada arreglo y apuntador hacen
referencia a los distintos miembros de las estructuras); finalizada todas las
declaraciones de las variables a utilizar se ingresó dentro de un ciclo for iniciando
con i=0 hasta llegar a i<numero_computadoras, en este ciclo lo que se hace es
pedirle al usuario que vaya ingresando datos referentes a los miembros de las
estructuras pero dicha información no se almacenará todavía de forma directa en
estructura sino en las variables creadas en la función que nos encontramos.
Anteriormente se comentó que en el archivo .c el cuál estamos explicando, contenía
varias funciones que servían solamente para impresión, bueno dichas funciones son
llamadas dentro del ciclo for para mostrar información hacer ca los miembros de
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
CONCLUSIONES
En ésta práctica se fue a otro nivel de abstracción, prácticas anteriores se llegaban
a puntos en los que se utilizaban funciones para tener un mejor programa y poder
manipularlo con mayor facilidad al igual que se empezaron a usar estructuras para
crear nuestros propios datos de tipo abstracto y tener una mayor variedad de
variables para un mejor almacenamiento y práctica de la programación; sin
embargo, esta vez se presentaron dos nuevos retos ya que se empezaron a usar
apuntadores de memoria dinámica además de que se empleó un nuevo concepto,
no mencionado durante las clases pero si en la materia anterior a esta
(Fundamentos de Programación), el uso de bibliotecas propias del programador.
Estos dos propusieron un reto debido a que debíamos usar ambos (memoria
dinámica y bibliotecas) para poder hacer un buen programa, el problema no fue
como implementarlo sino cómo pasar de un lado a otro sin que se perdiera la
información a almacenar, varias veces se trató pasar los apuntadores de caracteres
a las funciones para poder guardar la información deseada sin embargo no se pudo
encontrar una forma de hacerlo por lo que se optó por los arreglos; también en una
ocasión se intentó pasar el apuntador dinámico como parámetro a una función para
no usar paso por valor pero no se encontró una forma de lograr dicho objetivo
propuesto por el alumno.
Los objetivos propuestos al inicio de la práctica se cumplieron en su totalidad
además de que se fue más allá de lo deseado debido al uso de la biblioteca del
programador, al principio no se lograba comprender cómo se pasaba de la biblioteca
a un archivo .c y después al archivo principal; para lograr comprender dicho
procedimiento sin problema alguno se llevó alrededor de dos horas y una vez
logrado se empezó a codificar el siguiente problema propuesto por el profesor,
también cabe destacar que en las funciones de impresión se quiso implementar un
switch pero no se pudo lograr almacenar el valor de retorno sin ocupar una nueva
variable.
La ventaja de la forma en que se programaron los últimos dos códigos es que al
momento de querer modificar una función no se tiene que buscar dentro de un main
con más de 100 líneas de código lo cual sería complicado y tal vez un desastre
porque podría alterar todo el funcionamiento de la función main, para ello se
emplearon varias funciones lo cual fue efectivo porque varias veces se llegó a
modificar varias líneas de código pero sin la necesidad de borrar por completo (o
aunque sea la mayoría del código) para poder resolver un problema. Las
desventajas en este caso es que se llegan a ocupar muchas variables a tal grado
que se puede llegar a confundir o no tener “imaginación” para crear otra variable
que no entre en conflicto con otra, con una función o con una estructura.
La práctica en cuestión fue muy buena para el alumno, ya que él se vio a la
necesidad de aprender nuevos conceptos en poco tiempo para tener una mejor
“programación” mediante diferentes capas de abstracción además de que le hizo
ver las “acciones” que se pueden hacer y las que no se pueden hacer mediante
apuntadores, funciones; el único problema que no se pudo resolver en su totalidad
es al momento de la ejecución de las últimas 2 práctica, esto porque en ocasiones
Cote Valencia Alexis Daniel Grupo 1 Práctica 4 Almacenamiento en tiempo
de ejecución
al momento de ejecutar dichos programas se “rompían” y sólo hacían una parte del
programa, se debía ejecutar otra vez o incluso otras 3 veces para que se ejecutara
de forma correcta.