23
2011 UNAN – LEON Departamento de Computación Ing. En Sistemas de Información Autor: Ing: Karina Esquivel Alvarado. Asignatura: Programación Estructurada. ASIGNACIÓN DINÁMICA DE MEMORIA EN C

ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Embed Size (px)

Citation preview

Page 1: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

2011

UNAN – LEON Departamento de Computación Ing. En Sistemas de Información Autor: Ing: Karina Esquivel Alvarado. Asignatura: Programación Estructurada.

ASIGNACIÓN DINÁMICA DE MEMORIA EN C

Page 2: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

2

TEMA 8: ASIGNACIÓN DINÁMICA DE MEMORIA 8.1 INTRODUCCIÓN Los programas pueden crear variables globales o locales. Las variables declaradas globales en sus programas se almacenan en posiciones fijas de memoria, en la zona conocida como segmento de datos del programa, y todas las funciones pueden utilizar estas variables. Las variables locales se almacenan en la pila (stack) y existen sólo mientras están activas las funciones que están declaradas. Todas estas clases de variables comparten una característica común: se definen cuando se compila el programa. Esto significa que el compilador reserva (define) espacio para almacenar valores de los tipos de datos declarados. Es decir, en el caso de las variables globales y locales se ha de indicar al compilador exactamente cuántas y de qué tipo son las variables a asignar. O sea, el espacio de almacenamiento se reserva en el momento de la Compilación. Sin embargo, no siempre es posible conocer con antelación a la ejecución cuanta memoria se debe reservar al programa. En C, se asigna memoria en el momento de la ejecución en el montículo o montón (heap), mediante las funciones malloc(), realloc( ), calloc( ) y free( ), que asignan y liberan la memoria de una zona denominada almacén libre. 8.2 GESTIÓN DINÁMICA DE MEMORIA Consideremos un programa que evalúe las calificaciones de los estudiantes de una asignatura. El programa almacena cada una de las calificaciones en los elementos de una lista o tabla (array) y el tamaño del array debe ser lo suficientemente grande para contener el total de alumnos matriculados en la asignatura. Por ejemplo, la sentencia: int asignatura [40]; reserva 40 enteros, un número fijo de elementos. Los arrays son un método muy eficaz cuando se conoce su longitud o tamaño en el momento de escribir el programa. Sin embargo, presentan un grave inconveniente si el tamaño del array sólo se conoce en el momento de la ejecución. Las sentencias siguientes producirían un error durante la compilación:

scanf (“%d” &num_estudiantes) ; int asignatura[num_estudiantes] ;

Ya que el compilador requiere que el tamaño del array sea constante. Sin embargo, en numerosas ocasiones no se conoce la memoria necesaria hasta el momento de la ejecución.

Page 3: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

3

Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se puede prever, a priori, el tamaño del array necesario, a menos que se reserve un array de gran dimensión y se malgaste memoria cuando no se utilice. En el ejemplo anterior, si el número de alumnos de la clase aumenta, se debe variar la longitud del array y volver a compilar el programa. El método para resolver este inconveniente es recurrir a punteros y a técnicas de asignación dinámica de memoria. El espacio de la variable asignada dinámicamente se crea durante la ejecución del programa, al contrario que en el caso de una variable local cuyo espacio se asigna en tiempo de compilación. La asignación dinámica de memoria proporciona control directo sobre los requisitos de memoria de su programa. El programa puede crear o destruir la asignación dinámica en cualquier momento durante la ejecución. Se puede determinar la cantidad de memoria necesaria en el momento en que se haga la asignación. Dependiendo del modelo de memoria en uso, se pueden crear variables mayores de 64 K. El código del programa compilado se sitúa en segmentos de memoria denominados segmentos de código. Los datos del programa, tales como variables globales, se sitúan en un área denominada segmento de datos. Las variables locales y la información de control del programa se sitúan en un área denominada pila. La memoria que queda se denomina memoria del montículo o almacén libre. Cuando el programa solicita memoria para una variable dinámica, se asigna el espacio de memoria deseado desde el montículo. 8.3 FUNCIÓN malloc() La forma más habitual de C para obtener bloques de memoria es mediante la llamada a la función malloc( ). La función asigna un bloque de memoria que es el número de bytes pasados como argumento. malloc( ) devuelve un puntero, que es la dirección del bloque asignado de memoria. El puntero se utiliza para referenciar el bloque de memoria y devuelve un puntero del tipo void *. La función malloc( ) está declarada en el archivo de cabecera stdlib.h. La forma de llamar a la función malloc( ) es:

puntero = malloc(tamaño en bytes); Generalmente se hará una conversión al tipo del puntero:

tipo *puntero; puntero =(tipo *)malloc(tamaño en bytes);

Por ejemplo: int *p; p = (int *) malloc(4);

Page 4: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

4

El operador unario sizeof se utiliza con mucha frecuencia en las funciones de asignación de memoria. El operador se aplica a un tipo de dato (o una variable), el valor resultante es el número de bytes que ocupa. Así, si se quiere reservar memoria para un buffer de 10 enteros: int *r; r = (int *) malloc(10*sizeof(int)) ; Al llamar a la función malloc( ) puede ocurrir que no haya memoria disponible, en ese caso malloc( ) devuelve NULL. Sintaxis de llamada a malloc( ) tipo *puntero; puntero = (tipo *)malloc(tamaño) ; Prototipo que incluye malloc( ) void * malloc(size_t n ); En la sintaxis de llamada, puntero es el nombre de la variable puntero a la que se asigna la dirección del objeto dato, o se le asigna la dirección de memoria de un bloque lo suficientemente grande para contener un array de N elementos, o NULL, si falla la operación de asignación de memoria. El siguiente código utiliza malloc( ) para asignar espacio para un valor entero: int *pEnt; pEnt = (int *) malloc(sizeof(int)); La llamada a malloc( ) asigna espacio para un int (entero) y almacena la dirección de la asignación en pEnt. pEnt apunta ahora a la posición en el almacén libre (montículo) donde se establece la memoria. Así, por ejemplo, para reservar memoria para un array de 100 números reales: float *BloqueMem; BloqueMem = (float*) malloc (100*sizeof(float)); En el ejemplo se declara un puntero denominado BloqueMern y lo inicializan a la dirección devuelta por malloc( ). Si un bloque del tamaño solicitado está disponible, malloc( ) devuelve un puntero al principio de un bloque de memoria del tamaño especificado. Si no hay bastante espacio de almacenamiento dinámico para cumplir la petición, malloc( ) devuelve cero o NULL.

Page 5: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

5

La reserva de n caracteres se puede declarar así: int ncaracteres; char *s; scanf("%d",&ncaracteres); s = (char *) malloc(ncaracteres * sizeof(char)); Ejemplo #1: Este programa lee una línea de caracteres, reserva memoria para un buffer de tantos caracteres como los leídos y se copia en el buffer la cadena. //cadena.c #include <stdio.h> #include <string.h> #include <stdlib.h> void main() { char cad[21], *ptr ; int lon ; puts(“\nIntroduce una linea de texto:”) ; gets(cad) ; lon = strlen(cad); //Calcula la longitud de la cadena ptr = (char *)malloc( (lon+1) * sizeof (char)); /*Devuelve un puntero que apunta a una sección de memoria capaz de contener la cadena de longitud strlen ( ) más un byte extra por el carácter ‘\0’ al final de la cadena*/ strcpy (ptr, cad); //copia cad a nueva área de memoria printf ("ptr--> %s\n\n",ptr); /*cad está ahora en ptr*/ free(ptr) ; /*libera memoria apuntada por ptr*/ } Ejemplo de Salida:

Page 6: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

6

Ejemplo #2: Programa que crea un array de N valores de tipo entero de forma dinámica. //array_uni_dinamico.c #include <stdio.h> #include <stdlib.h> void main() { int *ptr,nelem,i; printf("Cuantos elementos: "); scanf("%d",&nelem); ptr = (int *)malloc(nelem * sizeof (int)); //Memoria dinámica para N elementos if(ptr == NULL) { printf("Insuficiente Espacio de Memoria"); exit(-1); //Salir del Programa } for(i=0;i<nelem;i++) { printf("Elemento[%d]:",i+1); scanf("%d",(ptr+i)); } printf("\n***ELEMENTOS DEL ARRAY***\n"); for(i=0;i<nelem;i++) { printf("%d ",*(ptr+i)); } free(ptr); //Liberación de memoria apuntada por ptr }

Page 7: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

7

Ejemplo de Salida:

8.3.1 USO DE MALLOC( ) PARA ARRAYS MULTIDIMENSIONALES Un array bidimensional es, en realidad, un array cuyos elementos son arrays. Al ser el nombre de un array unidimensional un puntero constante, un array bidimensinal será un puntero a puntero constante (tipo **). Para asignar memoria a un array multidimensional, se indica cada dimensión del array de igual forma que se declara un array unidimensional. Ejemplo #3: Programa en C que reserva memoria en tiempo de ejecución para una matriz de n filas y para cada fila m elementos. //array_bidi_dinamico.c #include <stdio.h> #include <stdlib.h> void main() { int **p; //Puntero a Puntero int n,m,i,j,k; do { printf ("\nCuantas filas?"); scanf ("%d",&n); } while(n <=1);

Page 8: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

8

//Reserva memoria para un array de n elementos, cada elemento es un puntero a entero (int *) p = (int **) malloc(n * sizeof(int *)); if(p==NULL) { printf("Insuficiente Espacio de Memoria"); exit(-1); } for(i=0; i<n; i++) { printf("\n\nNumero de elementos de fila %d:", i+1) ; scanf("%d",&m) ; p[i] = (int *)malloc(m*sizeof (int)); if(p[i]==NULL) { printf("Insuficiente Espacio de Memoria"); exit(-1); } for (j=0; j<m;j++) { printf("Elemento[%d][%d]:",i+1,j+1); scanf ("%d",&p[i][j]); //Lectura a través de Notación de array } printf("\nElementos de la Fila %d:\n", i+1) ; for (k=0; k<m;k++)

//Impresión de los elementos del array a través Notación de Puntero printf("%d ",*(*(p+i)+k)) ; } //Liberar la Memoria asignada a cada una de las filas for (i=0; i<n; i++) free(p[i]) ; //Liberar la Memoria asignada a la Matriz de Punteros free(p); }

Page 9: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

9

Ejemplo de Salida:

8.4 LIBERACIÓN DE MEMORIA, FUNCIÓN free( ) Cuando se ha terminado de utilizar un bloque de memoria previamente asignado por malloc( ), u otras funciones de asignación, se puede liberar el espacio de memoria y dejarlo disponible para otros usos, mediante una llamada a la función free( ). El bloque de memoria suprimido se devuelve al espacio de almacenamiento libre, de modo que habrá más memoria disponible para asignar otros bloques de memoria. El formato de la llamada es: free (puntero); 8.5 FUNCIONES DE ASIGNACIÓN DINÁMICA DE MEMORIA: calloc( ) y realloc( ) Además de la función malloc( ) para obtener bloques de memoria, hay otras dos funciones que permiten obtener memoria libre en tiempo de ejecución, éstas son calloc( ) y realloc( ). Con ambas se puede asignar memoria, lo que cambia en relación a la función malloc( ) es la forma de transmitir el número de bytes de memoria requeridos. Ambas devuelven un puntero al bloque asignado de memoria. El puntero se utiliza para referenciar el bloque de memoria. El puntero que devuelven es del tipo void *. 8.5.1 FUNCIÓN: calloc( ) La forma de llamar a la función calloc( ) es:

puntero = calloc(Número elementos,tamaño de cada elemento);

Page 10: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

10

Generalmente se hará una conversión al tipo del puntero:

tipo *puntero; puntero =(tipo *) calloc (numero elernentos,tamaño de cada elemento);

El tamaño de cada elemento se expresa en bytes, se utiliza para obtenerlo el operador sizeof. La función calloc( ) está declarada en el archivo de cabecera stdlib.h, por lo que será necesario incluir ese archivo de cabecera en todo programa que llame a la función. Se puede reservar memoria dinámicamente para cualquier tipo de dato, incluyendo char, float, arrays, estructuras e identificadores de typedef. Por ejemplo, se quiere reservar memoria para 5 datos de tipo double: #define N 5 double *pd; pd = (double *) calloc (N,sizeof(double)) ; Ejemplo #4: Este programa lee una línea de caracteres, reserva memoria con la función calloc( ) para un buffer de tantos caracteres como los leídos y se copia en el buffer la cadena. //funcion_calloc.c #include <string.h> #include <stdio.h> #include <stdlib.h> void main() { char *c, B[121]; puts("Introduce una cadena de caracteres:"); gets (B); /*Se reserva memoria para el número de caracteres + 1 para el carácter*/ c = (char*) calloc (strlen(B)+1,sizeof( char)); //Copia la cadena leída en c strcpy(c,B); printf("\nc--> %s\n",c);

//Liberación de Memoria free(c); }

Page 11: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

11

Ejemplo de Salida:

Ejemplo #5: En el siguiente programa se considera una secuencia de números reales, con una variable puntero a float se procesa un array de longitud variable, de modo que se puede ajustar la cantidad de memoria necesaria para el número de valores durante la ejecución del programa. //calloc_fn.c #include <stdlib.h> #include <stdio.h> void main(void) { float *pf=NULL; int num, i; do { printf("Cuantos datos en el array?"); scanf ( "%d",&num) ; }while (num<1); //Asigna memoria: num*tamaño bytes pf = (float *)calloc(num,sizeof(float)); if (pf == NULL) { puts("Error en la asignacion de memoria."); exit(-1); } printf ("\nIntroduce %d valores de tipo decimal\n",num); for (i=0; i<num; i++) { printf("Dato[%d]: ",i+1); scanf("%f",&pf[i]) ; }

Page 12: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

12

printf ("\nEn el array hay %d elementos\n",num) ; for (i=0; i<num; i++) printf("%.2f ",pf[i]) ; printf("\n\n"); //Liberación de la memoria asignada de forma dinámica free(pf); } Ejemplo de Salida:

8.5.2 FUNCIÓN: realloc( ) Esta función también es para asignar un bloque de memoria libre. Tiene una variación respecto a malloc( ) y calloc( ), permite ampliar un bloque de memoria reservado anteriormente. La forma de llamar a la función realloc( ) es:

puntero = realloc (puntero a bloque, tamaño total de nuevo bloque);

Generalmente se hará una conversión al tipo del puntero: tipo *puntero; puntero =(tipo *) realloc (puntero a bloque,tamaño total nuevo bloque);

El tamaño del bloque se expresa en bytes. El puntero a bloque referencia a un bloque de memoria reservado previamente con malloc( ) , calloc( ) o la propia realloc( ) .

Page 13: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

13

Ejemplo #6: Programa en C que permite reservar memoria para una cadena y a continuación, ampliar para otra cadena más larga utilizando la función realloc( ). //realloc_fn.c #include <stdio.h> #include <stdlib.h> #include <string.h> void main( ) { char *cadena; int tam; tam = (strlen("Practicas")+ 1) * sizeof (char); cadena = (char *) malloc (tam); strcpy (cadena,"Practicas") ; puts (cadena) ; //Ampliación del bloque de memoria tam += (strlen("Profesionales\n")+ 1)* sizeof (char); cadena = (char * ) realloc (cadena, tam); strcat (cadena," Profesionales\n"); puts(cadena); //Liberación de memoria free (cadena) ; } Ejemplo de Salida:

8.6 ASIGNACIÓN DE MEMORIA PARA ARRAYS La gestión de listas y tablas mediante arrays es una de las operaciones más usuales en cualquier programa. La asignación de memoria para arrays es, en consecuencia, una de las tareas que es preciso conocer en profundidad. Ejemplo #7: Este programa lee n líneas de texto, reserva memoria según la longitud de la línea leída, cuenta las vocales de cada línea e imprime cada línea y el número de vocales que tiene. El programa declara char *cad[N] como array de punteros a char, de tal forma que en la función entrada( ) se reserva memoria, con malloc( ), para cada línea de texto.

Page 14: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

14

//cuenta_vocales.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> #define N 10 //Prototipos de Funciones void salida(char *[ ], int *); void entrada(char *[ ]); int vocales(char *) ; void main( ) { char *cad[N]; int j, voc[N]; //Función para leer cadenas de caracteres entrada (cad) ; //Cuenta de vocales por cada cadena for(j=0; j<N; j++) voc[j] = vocales(cad[j]); salida(cad, voc) ; } //Función para leer N cadenas de caracteres void entrada(char *cd[ ]) { char B[121]; int j, tam; printf("\tEscribe %d lineas de texto\n",N); for(j=0; j<N; j++) { printf("Cadena[%d]: ",j+1); gets(B) ; tam = (strlen(B)+1)*sizeof(char); cd[j] = (char *)malloc(tam) ; strcpy(cd[j],B); } }

Page 15: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

15

//Función que cuenta el número de vocales que hay en una cadena int vocales (char *c) { int k, j; for (j=k=0; j<strlen(c); j++) //Cuenta vocales de la cadena c switch (tolower(*(c+j))) { case 'a' : case 'e': case 'i' : case 'o': case 'u': k++; break; } return k; } //Función para imprimir el número de vocales que tiene cada cadena void salida(char *cd[],int *v) { int j; puts ("\n\tSalida de las cadenas junto al numero de vocales") ; for (j=0; j<N; j++) { printf ("Cadena [%d]: %s tiene %d vocales\n",j+1,cd[j], v[j]); } }

Page 16: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

16

Ejemplo de Salida:

8.7 PUNTEROS A ESTRUCTURAS Los punteros a estructuras se declaran igual que los punteros a otros tipos de datos. Para referirse a un miembro de una estructura referenciado por un puntero es necesario utilizar el operador “->”. El hecho de declarar un puntero a una estructura no significa que dispongamos de la estructura; es necesario asignar al puntero un bloque de memoria del tamaño de la estructura donde se almacenarán los datos de la misma. Ejemplo #8: Programa que lee los datos de una estructura “Deportista” utilizando el operador “->”. //deportista.c #include<stdio.h> #include<stdlib.h> struct Deportista { char nombre [30]; float altura; float peso; };

Page 17: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

17

void main( ) { struct Deportista d,*dep; dep = &d; printf("Nombre: "); scanf("%s",dep->nombre); printf("Altura: "); fflush(stdin); scanf("%f",&dep->altura); printf("Peso: "); scanf("%f",&dep->peso); printf("\n****Datos del Deportista****\n"); printf("Nombre: %s\n",dep->nombre); printf("Peso: %.2f libras\n",dep->peso); printf("Altura: %.2f mts\n",dep->altura); } Ejemplo de Salida:

Ejemplo #9: Este programa asigna memoria dinámica para un array de 3 estructuras de tipo Estudiante y calcula cuál es el estudiante que obtuvo la mayor nota. //nota_mayor.c #include<stdio.h> #include<stdlib.h> struct Estudiante { char nombre[30]; int nota; };

Page 18: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

18

void main() { struct Estudiante *est; int i=1,j=1,pos,may; //Asignación de memoria para el array de 3 struct Estudiante est = (struct Estudiante *)calloc(3,sizeof(struct Estudiante)); if(est==NULL) { printf("Insuficiente Espacio de Memoria\n"); exit(-1); }

else {

for(i=0;i<3;i++) { printf("Nombre Estudiante[%d]: ",i+1); gets(est[i].nombre); printf("Nota Estudiante[%d]: ",i+1); scanf("%d",&est[i].nota); fflush(stdin); }

} may=0; for(j=0;j<3;j++) { if(est[j].nota > may) { may = est[j].nota; pos = j; } } printf("\n%s ES QUIEN OBTUVO LA MAYOR NOTA:%d\n\n",est[pos].nombre,may); //Liberando la memoria asignada al puntero a struct (struct *est) free(est); }

Page 19: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

19

Ejemplo de Salida:

Ejemplo #10: El profesor de la asignatura de Practicas Profesionales desea conocer el porcentaje de: � Alumnos de Sexo Femenino y Masculino. � Aprobados y reprobados, tomando en cuenta que la nota mínima para aprobar es 60 pts. //porcentaje.c #include<stdio.h> #include<stdlib.h> #include<string.h> struct Estudiante { char nombre[30]; char sexo; int nota; }; void main() { struct Estudiante *est; int n,nest,ap=0,re=0,nef=0,nem=0; float pap,prep,pf,pm; printf("Introduzca el numero de estudiantes: "); scanf("%d",&nest); //Asignando Memoria para el array de N datos de tipo struct est = (struct Estudiante *)calloc(nest,sizeof(struct Estudiante)); if(est==NULL) { printf("Insuficiente Espacio de Memoria\n"); exit(-1); }

Page 20: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

20

else { for(n=1;n<=nest;n++) { printf("Nombre Estudiante: "); fflush(stdin); gets(est[n].nombre); do { printf("Sexo(f/m): "); fflush(stdin); scanf("%c",&est[n].sexo); } while((est[n].sexo !='f' && est[n].sexo!='F') && (est[n].sexo !='m' && est[n].sexo!='M')); if((est[n].sexo=='f') || (est[n].sexo=='F')) nef++; if((est[n].sexo=='m') || (est[n].sexo=='M')) nem++; printf("Nota: "); scanf("%d",&est[n].nota); if(est[n].nota >=0 && est[n].nota<=60) ap++; else re++; } } pap = (ap*100)/nest; prep = (re*100)/nest; pf=(nef*100)/nest; pm=(nem*100)/nest; printf("Hay %d estudiantes APROBADOS y representan %.2f%%\n",ap,pap); printf("Hay %d estudiantes REPROBADOS y representan %.2f%%\n",re,prep); printf("Hay %d alumnos de sexo FEMENINO y representan %.2f%%\n",nef,pf); printf("Hay %d alumnos de sexo MASCULINO y representan %.2f%%\n",nem,pm); //Liberando Memoria para est (struct Estudiante *est) free(est); }

Page 21: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

21

Ejemplo de Salida:

8.8 REGLAS DE FUNCIONAMIENTO DE LA ASlGNAClÓN DE MEMORIA Se puede asignar espacio para cualquier objeto dato de C. Las reglas para utilizar las funciones malloc( ), calloc( ), realloc( ) y free( ) como medio para obtener/liberar espacio de memoria son las siguientes: 1. El prototipo de las funciones esta en stdlib.h. Ejemplo: #include <stdlib.h> int *datos; datos = (int*)malloc(sizeof(int));

2. Las funciones malloc( ) , calloc() , realloc( ) devuelven el tipo void *, lo cual exige hacer una conversión al tipo del puntero.

3. Las funciones de asignación tienen como argumento el número de bytes a reservar. 4. El operador sizeof permite calcular el tamaño de un tipo de objeto para el que está asignando memoria.

Page 22: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

22

Ejemplo: struct punto {

float x,y,z; } struct punto *p = (struct punto *)malloc (sizeof(struct punto));

5. La función realloc( ) permite expandir memoria reservada. Ejemplo: #include <stdlib.h> int *v=NULL; int n; scanf ("%d",&n) ; v = (int*)realloc(v,n); v = (int*)realloc(v,2*n);

6. Las funciones de asignación de memoria devuelven NULL si no han podido reservar la memoria requerida.

Ejemplo: double *v; v = malloc(1000 * sizeof(double)); if (v == NULL) {

puts ("Error de asignación de memoria. " ) ; exit(-1);

}

7. Se puede utilizar cualquier función de asignación de memoria para reservar espacio de objetos más complejos, tales como estructuras, arrays, en el almacenamiento libre.

Ejemplo: #include <stdlib.h> struct complejo {

float x,y; } ; void main() {

struct complejo *pz; int n;

Page 23: ASIGNACIÓN DINÁMICA DE MEMORIA EN C - · PDF fileAsignación Dinámica de Memoria en C 3 Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se

Asignación Dinámica de Memoria en C

23

scanf("%d",&n); /*Puntero a estructura complejo*/ /*Asigna memoria para un array de tipo complejo*/ pz = (struct complejo *)calloc(n,sizeof(struct complejo)); if (pz == NULL) {

puts ("Error de asignación de memoria.") ; exit(-1);

} } 8. Se pueden crear arrays multidimensionales de objetos con las funciones de asignación de memoria. Para un array bidimensional n x m, se asigna en primer lugar memoria para un array de punteros (de n elementos), y después se asigna memoria para cada fila (m elementos) con un bucle desde 0 a n -1.

Ejemplo: #include <stdlib.h> double **mat; int n,m,i; mat = (double**)malloc(n*sizeof(double*)); /*array de punteros*/ for (i=0; i<n; i++) {

mat[i] = (double *)malloc (m * sizeof(double)); /*fila de m elementos*/ } 9. Toda memoria reservada con alguna de las funciones de asignación de memoria se puede liberar con la función free ( ).

Ejemplo: Para liberar la memoria de la matriz dinámica mat: double **mat; for (i=O; i<n; i++) { free(mat[i]) ; }