330 likes | 553 Views
Unidad 3. Punteros. Objetivos del Aprendizaje. Definir qué son los punteros y describir su rol en la resolución de problemas. Discutir los conceptos de punteros, variables, direcciones de memoria y referencias. Explicar cómo hacer declaraciones de punteros.
E N D
Unidad 3 Punteros
Objetivos del Aprendizaje • Definir qué son los punteros y describir su rol en la resolución de problemas. • Discutir los conceptos de punteros, variables, direcciones de memoria y referencias. • Explicar cómo hacer declaraciones de punteros. • Discutir el uso de los punteros para pasar parámetros a las funciones por referencias. • Explicar funciones que pueden recibir arreglos unidimensionales como argumentos a través de punteros.
Fundamentos de Punteros • Un punteroes una variable en C que representa una dirección de un elemento de datos en la memoria. • Los punteros son importantes porque: • Son útiles para crear aplicaciones • Se pueden usar para pasar argumentos a funciones por referencia. • Son útiles para acceder a elementos individuales de estructuras de datos tales como arreglos, estructuras y tipos de datos definidos por el usuario. • Se pueden usar para realizar asignación dinámica de memoria, es decir, reservar la cantidad de memoria que requiera la estructura de datos, en vez de estar limitado por arreglos de dimensiones y tamaño fijos.
Nombre de la variable x 5 Valor en la posición (Contenido de la variable) Dirección de la variable 43658 Asignación de Memoria en Declaración de Variable • La declaración int x = 5solicita al compilador: • Asignar o realmente reservar memoria para almacenar el entero. • Asociar el nombre x con la posición de memoria. • Almacenar el valor entero 5 en esa posición.
Dirección de x Valor de x =5, var_nombre x Asignar dirección de variable a otra variable • Siendo… • int x = 5; • var_nombre = &x; • &x se refiere a la dirección de memoria de xy no a su valor. • var_nombre ahora apunta a la dirección de la ubicación donde el valor de x está almacenado. • Es posible acceder al valor de la variable x usando el operador de indirección o de 'desreferencia‘ con: • *var_nombre.
Declaración de Punteros • Declaración de puntero: • tipo-de-dato *variable_puntero; • tipo-de-dato:tipo de dato del objeto. • variable_puntero:nombre de la variable puntero que se está declarando • El carácter * debe preceder el nombre de la variable puntero. • Ejemplo de declaraciones válidas de punteros: • int *var_name; • float *temp; • char *pval; • Se puede inicializar una variable puntero en la misma declaración. • int x, y; • int *var_name = &x;
Usar Punteros para pasar Argumentos a Funciones • En C, el método normal de pasar argumentos a funciones es a través de parámetros por valor. • Cuando se pasa un argumento como un valor a una función, se hace una copia del elemento de dato dentro de la función. • Dentro de la función todas las referencias a los argumentos a través de los parámetros formales son dirigidos a la copia. • De manera que si se modifica este elemento de dato, es la copia dentrode la función la que es modificada y no la usada en la llamada.
Uso de Punteros...Ejemplo 1 Intercambiar el valor de dos variables intercambiar(&x, &y); La función intercambiarse define como: void intercambiar(int *p, int *q){ int temp; temp = *p; *p = *q; *q = temp; return; }
Uso de Punteros...Ejemplo 2 • Sumar los números impares de un arreglo • Función main() • int main(){ • int vector[100]; • … • printf(“La suma de los datos impares es \ • %d\n”, sum_impar(vector)); • … • } • Prototipo de función y argumento formal a la función: • int sum_impar(int vect[]); • int sum_impar(int *vect);
Pasar Arreglos a scanf() • Para leer variables int, float, y char se debe usar la función scanf(). • La variable debe estar precedidas por el carácter &. • Ejemplo: • int x; float p; char ch; • scanf(“%d %f %c”, &x, &p, &ch); • La función scanf require la dirección de manera que los elementos de datos se puedan almacenar en la ubicación correcta. • La función scanf no requiere el carácter & para leer cadenas en un arreglo. • char fnombre[45]; • scanf(“%s”, fnombre);
Aritmética de Direcciones • Un nombre de arreglo es realmente un puntero al primer elemento del arreglo. • Si caja es un arreglo unidimensional, la dirección del primer elemento puede ser referenciado como &caja[0] o sólo caja. • Se tienen dos formas de escribir las direcciones de los elementos de un arreglo: • &caja[i] y • caja + i. • El subíndice i se denomina desplazamiento (offset).
Búsqueda Lineal • Planteamiento: • Buscar un elemento en el arreglo • La búsqueda se comienza desde el primer elemento en el arreglo y se continúa buscando a través del arreglo hasta que el elemento se encuentre o hasta que se haya recorrido todo el arreglo. • Se denomina búsqueda lineal, porque se busca desde el primer elemento hasta el último elemento, o hasta que el elemento se encuentra en el arreglo.
Búsqueda Lineal...2 int busqueda(int *caja,int n, int num){ /* n es el tamaño del arreglo, num es el número buscado */ int k; k=0; while(k<n){ if(*(caja+k) ==num) return (k); else k++; } return(-1); }
Resumen • Se definió qué son los punteros y se describió su rol en la resolución de problemas. • Se discutieron los conceptos de punteros, variables, posiciones de memorias y referencias. • Se explicó cómo hacer declaraciones de punteros • Se discutió el uso de punteros para pasar parámetros a funciones por referencia. • Se explicaron las funciones que pueden recibir arreglos unidiemensionales como argumentos a través de punteros.
Objetivos del Aprendizaje • Explicar la aritmética de direcciones. • Describir un puntero a puntero y un arreglo de punteros. • Discutir cómo declarar y usar punteros con estructuras. • Explicar cómo pasar funciones como argumentos a otras funciones a través de punteros.
Introducción • Los punteros son importantes en cualquier esfuerzo para resolver problemas. • Se puede declarar un puntero para cualquier tipo de dato. • C permite que el programador declare tipos de datos definidos por el usuario. • C permite usar punteros a estructuras.
Aritméticas de Direcciones • Un tipo de dato es un conjunto de valores y las operaciones definidas sobre ellos. • Un puntero se declara como int *ptr; indicando que ptr es una variable que pertenece al tipo de dato int *. • C considera sólo dos operaciones sobre las variables punteros: adición y resta. • Para la la aritmética de direcciones, el tipo de dato al que el puntero está asociado es importante. • El tamaño del tipo de dato es lo que se usa en el cálculo de la expresión que involucra aritmética de direcciones.
Aritméticas de Direcciones • La aritmética de direcciones se usa para mover el puntero a la próxima posición en la memoria y acceder al elemento almacenado en esa posición. • En este caso la asignación de memoria contigua es fundamental. • La aritmética de direcciones normalmente aplica cuando se usa con arreglos. • C integra punteros, arreglos y aritmética de direcciones. • Los arreglos en C implícitamente usan aritmética de direcciones para acceder a sus elementos. • La aritmética de direcciones no se puede usar con tipos de datos como int o char porque el contenido de la próxima posición no se conoce.
arreglo ptr Direcciones de la Variable Puntero ptr
ptr1 ptr2 Dos Variables Punteros
x y z x 10 1024 508 10 508 1024 3308 508 x 10 y 508 508 1024 Puntero a Puntero Dirección y Contenido de una Variable Puntero Posición de una Variable Puntero y su Contenido Posición de Variables Puntero y su Contenido
Arreglo de Punteros • Un arreglo bidimensional se define como un arreglo unidimensional de punteros: • tipo-de-dato *arreglo[c_expr]; • Un arreglo de bidimensional se define como: • tipo-de-dato arreglo[c_expr1][ c_expr2]; • Las dos definiciones anteriores son equivalentes. • El tamaño de un arreglo es siempre una constante, representada anteriormente por c_expr. • Los subíndices de un arreglo pueden ser de tipos integrales int y char. • El tipo de dato float no se puede usar como subíndice de arreglos.
Arreglo de Punteros...2 • Se puede extender la definición del uso de punteros para arreglos multi-dimensionales como: • data-type *array[c_expr1][c_expr2]…[c_exprn-1]; • para un arreglo de n dimensiones. • Note que tiene una dirección menos. Una definición de arreglo equivalente es: • data-type *array[c_expr1][c_expr2]…[c_exprn]; • Un arreglo bidimensional de cinco filas y 25 columnas de enteros se define como: • int *x[5];
Arreglo de Punteros...3 • Ejemplo de arreglo multidimensional: • Arreglo tridimensional de enteros de tamaño 5 x 10 x 15 se define como un arreglo bidimensional de punteros: • int *y[5][10]; • Un elemento individual de un arreglo tridimensional, convencionalmente se accede como y[i][j][k], se puede acceder también como: • *(y[i][j] + k) • Los arreglos de punteros se usan para almacenar cadena de caracteres, cada elemento del arreglo es un puntero a carácter que define el principio de una cadena separada: • char *a[10];
Uso de Punteros a Cadenas de Caracteres...Ejemplo 1 • Considere cuatro cadenas de caracteres. • Se requiere hacer lo siguiente: • Comparar la primera cadena de caracteres con todos las otras cadenas de caracteres y verificar si la primera cadena de caracteres es mayor, menor o igual a las otras cadenas de caracteres. Mostrar el resultado . • Concatenar las cadenas de caracteres con la palabra ’color’.
Uso de Punteros a Cadenas de Caracteres...Ejemplo 1 • En el ejemplo: • Se usa la librería de funciones de cadenas de caracteres (string) definidas en <string.h>, • Se asigna memoria dinámicamente. • Se usan las siguientes cuatro funciones de cadenas de caracteres: • int strlen(const char *):Toma un puntero a una cadena, y retorna la longitud de la cadena. • char * strcpy(char *, const char *):Toma dos cadenas y copia la segunda cadena dentro de la primera cadena.
Uso de Punteros a Cadenas de Caracteres • int strcmp(const char *, const char *):Toma dos cadenas y retorna: • 0 si ambas cadenas son iguales, • < 0 si la primera cadena es menor que la segunda • > 0 si la primera cadena es mayor que lal segunda. • char * strcat(char *, const char *):Toma dos cadenas y concatena (une) las dos cadenas agregando la segunda cadena a la primera.
Punteros a Estructura • Los punteros pueden apuntar a estructuras. • Ejemplo: • struct persona{ • char nombre[45]; • int edad; • float peso; • }; • struct persona *sptr; • Si sptr es la variable puntero a la estructura, se puede acceder a cada componente individual de la estructura de la siguiente forma: • sptr->nombre • sptr->edad • sptr->peso
Punteros a Funciones • Es posible definir punteros a una función, la cual puede ser colocada en arreglos, pasada a funciones y retornar de las funciones. • Una función puede ser pasada como un argumento a otra función y para eso se usa el puntero a una función. • Tal situación se presenta cuando una función, referida como la primera función, realiza tareas usando otra función.
Punteros a Funciones...2 • Se tienen cuatro funciones independientes que realizan cálculos diferentes dependiendo de la entrada: • Determinar la raíz cuadrada de un entero • Determinar la raíz cúbica de un entero • Determinar si un número entero es primo • Determinar si un entero es un palíndrome
Punteros a Funciones...Ejemplo 1 int raizCuadrada(int x){ int sqrt=0; sqrt =(int) pow (x,0.5); return(sqrt); } void generarTabla(int (*fptr)(int)){ int i; for(i=1;i<=1000;i++) printf("%d\t%d\n",i,(*fptr)(i)); } main(){ generarTabla(raizCuadrada); }
Resumen • Se explicó la aritmética de direcciones. • Se estudió el concepto de puntero a puntero y arreglo de punteros. • Se explicó cómo declarar y usar punteros con estructuras. • Se estudió cómo pasar funciones como argumentos a otras funciones a través de punteros.