FUNDAMENTOS DE PROGRAMACIÓN Sabino Miranda Jiménez Universidad Autónoma del Estado de México (UAEM)
Apuntadores (1) Un apuntador es una variable que contiene la dirección de una ora variable Generan código compacto y eficiente Arreglos y apuntadores están relacionados Flexibilidad para que un programa crezca dinámicamente Operador unario de direccionamiento: & Operador unario de indirección o desreferencia: * DECLARACIÓN: tipo *nombre_apuntador;
Apuntadores (2) UNIVERSIDAD AUTÓNOMA DEL ESTADO DE MÉXICO x 9 int *p, c=9, x; A0F1 BF30 DA93 // p apunta a la dirección de memoria donde se encuentra c (BF30) p = &c // p apunta a BF30 // obtiene el valor que se encuentra en la dirección de memoria a la que apunta p (BF30) x=*p // x= 9
Ejemplo de uso: apuntadores #include <stdio.h> int main() int x,y,z[5]=3,4,5,6,7; int *ap; x=1; y=10; printf("sin uso de apuntadores x=%d y=%d z[0]=%d\n",x,y,z[0]); ap = &x; y = *ap; *ap=100; printf("después del uso de apuntadores x=%d y=%d\n",x,y); ap= &z[0]; *ap=999; printf("z[0]=%d\n",z[0]); UNIVERSIDAD AUTÓNOMA DEL ESTADO DE MÉXICO
Salida UNIVERSIDAD AUTÓNOMA DEL ESTADO DE MÉXICO sin uso de apuntadores x=1 y=10 z[0]=3 Después del uso de apuntadores x=100 y=1 z[0]=999
Apuntadores (3) Un apuntador debe contener una dirección válida Inicializar el apuntador a NULL Apuntar a una dirección de memoria que continúe válida Variables que continúen en memoria Variables que no se han liberado Errores comunes No inicializar apuntadores Apuntar a una dirección fuera de los datos del programa Desestabilizar al programa o al S.O Operaciones: incremento y decremento según su tipo
Aritmética de apuntadores Operaciones: incremento y decremento Si p y q son apuntadores a algún elemento de un arreglo p++ p = p +i p+=i q-- incrementa a p para apuntar a la siguiente dirección de memoria (sig. Elemento) incrementa a p i elementos a delante de su posición actual Decrementa a q en una posición para apuntar al elemento previo
Apuntadores y funciones En el lenguaje C se pasan los argumentos de funciones por valor Los datos son una copia del original No se pueden modificar el original
Apuntadores y funciones #include <stdio.h> void intercambia(int a,int b); void intercambiaref(int* a,int* b); int main() int a=10, b=20; intercambia(a,b); printf("por valor A=%d B=%d\n",a,b); intercambiaref(&a,&b); printf("por referencia A=%d B=%d\n",a,b); void intercambia(int a, int b) int temp= a; a=b; b=temp; void intercambiaref(int* a, int* b) int temp= *a; *a=*b; *b=temp; return 0;
Salida?
Apuntadores y arreglos El nombre de un arreglo es un apuntador al inicio del arreglo Se puede direccionar arreglos como apuntadores Se puede direccionar apuntadores como arreglos Aritmética de apuntadores: suma y resta Suma o resta el número de bloques de bytes correspondientes
Apuntadores y arreglos (2) #include <stdio.h> int main() int num[5] = 10, 20, 30, 40, 50; int *ap_num; ap_num = num; printf("%d ",num[0]); printf("%d ",ap_num[0]); printf("%d ",*num); printf("%d ",*ap_num); printf("%d ",num[3]); printf("%d ",ap_num[3]); return 0; printf("%d ",++*ap_num); printf("%d ",*++ap_num); printf("%d ",*ap_num++);
Salida?
Apuntadores y arreglos (3) #include <stdio.h> #include <string.h> int main() int lista[5] = 10, 20, 30, 40, 50; int *p; char cad[15]; char *q; p = &lista[3]; p = lista + 3; printf("%d ", lista[2]); printf("%d ", *(lista+2)); strcpy(cad, "Programando"); for (q = cad; *q!= '\0'; q++) printf("%c",*q); return 0;
Salida?
Apuntadores y arreglos (4) double x[5] = 1.1, 2.1, 3.1, 4.1, 5.1; double *p = &x[1], *q = &x[4]; int n; n = q - p; // a n se le asigna 3
Apuntadores y arreglos (5) #include <stdio.h> void imprimearruni(int *num,int tot); int main() int num2[4] = 1,3,4,7; imprimearruni(num2,4); return 0; void imprimearruni(int *num,int tot) for (int j=0;j<tot;j++) printf("elemento %d -> %d\n",j,num[j]);
Salida?
Apuntadores y arreglos (6) #include <stdio.h> void imprimetexto(char **cads,int lineas) for (int i=0;i<lineas;i++) puts(*(cads+i)); // o cads[i] int main() char *estaciones[4] = "Primavera, "Verano", "Otoño, "Invierno" ; imprimetexto(estaciones,4); return 0;
Salida?
Asignación dinámica de memoria Almacenamiento de variables Globales en posiciones fijas de memoria (en segmento de datos) Locales en la pila (Stack) sólo mientras está activa la función que las declara Se reserva el espacio en el momento de compilación Se puede almacenar y utilizar memoria dinámica (heap) En C se cuenta con funciones para reservar memoria y liberarla: malloc() y free() malloc() reserva memoria y retorna la dirección o NULL en caso de fallo free() libera memoria reservada a través de un apuntador
Asignación dinámica de memoria (2) Sintaxis void *malloc(size_t tam_bloque); size_t es un tipo de datos entero tam_bloque es el tamaño en bytes del bloque de memoria por reservar void free(void *bloque); bloque es un apuntador a la zona de memoria a liberar.
Asignación dinámica de memoria (3) malloc() Reserva memoria sin importar el tipo de datos que se almacenará Retornando un apuntador a void, convertir el tipo de apuntador al tipo del apuntador que guardará la dirección. Necesario calcular cuántos bytes se requieren, el operador sizeof ayuda.
Asignación dinámica de memoria (4) #include <stdio.h> #include <stdlib.h> int main () int i, n; int *pnum; printf ("Cantidad de números por introducir: "); scanf ("%d",&i); pnum = (int*) malloc (i * sizeof(int)); if (pnum==null) exit (1);
Asignación dinámica de memoria (cont.) for (n=0;n<i;n++) printf ("Número %d: ",n); scanf ("%d",&pnum[n]); printf ("Números capturados: "); for (n=0;n<i;n++) printf ("%d ",pnum[n]); free (pnum); return 0;
Ejemplo de lectura de datos tipo caracter Pantallazo del 2013-11-04 13:23:49
Ejemplo lectura de datos #include <stdio.h> #include <stdlib.h> #define LINEA 200 int main () int k,n; char** documento; printf ("Cantidad de líneas por capturar: "); fflush(stdin); scanf ("%d",&n); //limpiar el buffer de entrada (consumir el salto de línea) fflush(stdin); // usar getchar(); o algo equivalente, en linux
Ejemplo lectura de datos(2) // reserva la memoria para el conjunto de líneas documento = (char**) malloc( n * sizeof(char*)); if (documento==null) exit (1); for (k=0;k<n;k++) // reserva la memoria para cada línea documento[k] = (char*) malloc(linea * sizeof(char)); printf ("línea %d: ",k+1); gets(documento[k]); printf ("\norden inverso de líneas capturadas: \n"); for (k=n-1; k>=0; k--) puts(documento[k]);
Ejemplo lectura de datos(3) //------ liberar la memoria reservada for (k=0; k<n; k++) // libera la memoria de cada línea free(documento[k]); // libera la memoria del conjunto de líneas free (documento); //---- fin liberar memoria return 0;
Ejemplo de lectura de datos con funciones Pantallazo del 2013-11-04 13:23:49
Funciones: ejemplo lectura de datos #include <stdio.h> #include <stdlib.h> #define MAX_CARS 100 #define MAX_LIN 5 void LeeTexto(char** doc,int Totlin) int i=0; for( i=0; i<totlin ;i++) printf("\nlinea%d: ",i+1); gets(doc[i]);
Funciones: ejemplo lectura de datos (2) void imprimetexto(char ** doc, int Nlin) int i=0; for( i=0; i<nlin ;i++) printf("%s\n",doc[i]);
Funciones: ejemplo lectura de datos (3) char** reservamemoria() int k; char ** doc= (char**) malloc( MAX_LIN * sizeof(char*)); for (k=0;k<max_lin;k++) doc[k] = (char*) malloc(max_cars * sizeof(char)); return doc;
Funciones: ejemplo lectura de datos (4) void liberamemoria(char **doc) int k; // liberar la memoria reservada for (k=0; k<max_lin; k++) // libera la memoria de cada línea free(doc[k]); // libera la memoria del conjunto de líneas free (doc); // fin liberar memoria
Funciones: ejemplo lectura de datos (5) int main() char **doctxt; doctxt = reservamemoria( ); printf("\n<< \t\tescriba un documento máximo 5 líneas>>\n"); LeeTexto(docTxt, MAX_LIN); printf("\n\n\n<< \t\t----documento CAPTURADO---->>\n"); imprimetexto(doctxt, MAX_LIN); liberamemoria(doctxt); return 0;