PUNTEROS ¿Qué es un PUNTERO?: Un puntero es una variable que apunta a otra variable. Esta variable almacena la dirección de memoria de otra variable. No hay que confundir una dirección de memoria con el contenido de esa dirección de memoria. int x = 25; Dirección
...
...
1502
1504
1506
1508
25
...
...
...
...
La dirección de la variable x (&x) es 1502 El contenido de la variable x es 25 ALGORITMOS Y ESTRUCTURA DE DATOS
1
PUNTEROS Las direcciones de memoria dependen de la arquitectura del ordenador y de la gestión que el sistema operativo haga de ella. OPERADORES DE LOS APUNTADORES Operador de dirección & Permite saber la dirección de memoria de la variable: &fnum representa la dirección de fnum. Operador de contenido o indirección * Si el operador * esta antes de la variable durante la declaración, indica que esta declarando la variable tipo puntero. ALGORITMOS Y ESTRUCTURA DE DATOS
2
PUNTEROS Ejemplo int *p, *q; // p y q son variables puntero que apunta a un entero. Si el operador * precede a una variable puntero (no en la parte declarativa), indica que vamos acceder al dato de la variable al cual apunta el puntero. Ejemplo float *p, altura = 26.92; p = &altura; //inicializaci贸n del puntero, p apunta a altura cout<<altura<<endl // Escribe el valor de 26.92 cout<<*p<<endl; // Escribe el valor de altura, osea 26.92 ya que p apunta la variable altura.
ALGORITMOS Y ESTRUCTURA DE DATOS
3
PUNTEROS Una variable puntero se declara como todas las variables. Debe ser del mismo tipo que la variable apuntada. Su identificador va precedido de un asterisco (*) int *punt; Es una variable puntero que apunta a una variable que contiene un dato de tipo entero llamada punt. char *car: Es una variable puntero que apunta a una variable que contiene un dato de tipo car谩cter llamada car. Un puntero tiene su propia direcci贸n de memoria: &punt &car ALGORITMOS Y ESTRUCTURA DE DATOS
4
PUNTEROS #include <iostream> using namespace std; int main() { int a, b, c, *p1, *p2; p1 = &a; // Paso 1. La dirección de a es asignada a p1 *p1 = 1; // Paso 2. p1 (a) es igual a 1. Equivale a a = 1; p2 = &b; // Paso 3. La dirección de b es asignada a p2 *p2 = 2; // Paso 4. p2 (b) es igual a 2. Equivale a b = 2; p1 = p2; // Paso 5. El valor del p1 = p2 *p1 = 0; // Paso 6. b = 0 p2 = &c; // Paso 7. La dirección de c es asignada a p2 *p2 = 3; // Paso 8. c = 3 cout<<a<<b<<c<<endl; // Paso 9. ¿Qué se imprime? } ALGORITMOS Y ESTRUCTURA DE DATOS
5
PUNTEROS Paso
a 0x22ff74
b 0x22ff70
c 0x22ff6c
1
p1 0x7c80b4cb
p2 0x304fc24
0x22ff74
2
1
0x22ff74
3
1
0x22ff74
0x22ff70
4
1
2
0x22ff74
0x22ff70
5
1
2
0x22ff70
0x22ff70
6
1
0
0x22ff70
0x22ff70
7
1
0
0x22ff70
0x22ff6c
8
1
0
3
0x22ff70
0x22ff6c
9
1
0
3
0x22ff70
0x22ff6c
ALGORITMOS Y ESTRUCTURA DE DATOS
6
PUNTEROS PUNTEROS Y ARRAYS Sea el array de una dimensi贸n: int mat[ ] = {2, 16, -4, 29, 234, 12, 0, 3}; en el que cada elemento, por ser tipo int, ocupa dos bytes de memoria. Suponemos que la direcci贸n de memoria del primer elemento, es 1500: &mat[0] es 1500 &mat[1] ser谩 1502 &mat[7] ser谩 1514
ALGORITMOS Y ESTRUCTURA DE DATOS
7
PUNTEROS PUNTEROS Y ARRAYS int mat[ ] = {2, 16, -4, 29, 234, 12, 0, 3}; En total los 8 elementos ocupan 16 bytes. Podemos representar las direcciones de memoria que ocupan los elementos del array , los datos que contiene y las posiciones del array en la forma: 1500
1502
1504
1506
1508
1510
2
16
-4
29
234
12
Mat[0] mat[1]
1512
1514
0
3
mat[2] mat[3] mat[4] mat[5] mat[6] mat[7]
ALGORITMOS Y ESTRUCTURA DE DATOS
8
PUNTEROS Analizando las direcciones de memoria del array: Direcci贸n del elemento 0
Direcci贸n del octavo elemento
&mat[0] &mat[1] &mat[2] &mat[3] &mat[4] &mat[5] & mat[6] &mat[7]
2
16
-4
mat
mat+1
mat+2
29
234
12
mat+3
mat+4
mat+5
0
3
mat+6
mat+7
mat++ Puntero a la direcci贸n del elemento 0
Incremento en una unidad int (dos bytes) ALGORITMOS Y ESTRUCTURA DE DATOS
9
PUNTEROS De lo anterior se obtienen varias conclusiones: - Es lo mismo &mat[0] que mat, &mat[2] que mat + 2 - Para pasar de un elemento al siguiente, es lo mismo for(i=0; i<8; i++) cout<<&mat[i]<<endl;
que el c贸digo: for(i=0; i<8; i++) cout<<mat + i<<endl; A esta forma de desplazarse se llama aritmetica de punteros. ALGORITMOS Y ESTRUCTURA DE DATOS
10
ARITMETICA DE PUNTEROS La aritmética de punteros implica usar los operadores para suma(+), resta (-) o incremento(++) o decremento (--). Direccion de a memoria Ejemplo: 1004 Contenido en esa Direccion de memoria
int *p, a; 50 p=&a; p=p+5; // Esta sentencia implica que p se desplaza a la siguiente dirección de memoria según la siguiente formula. p=p+5*sizeof(int);// Suponiendo que int ocupa 2 bytes, la nueva direccion de memoria que almacena p es = 1014 Recuerda que las direcciones de memoria esta dado en formato hexadecimal. ALGORITMOS Y ESTRUCTURA DE DATOS
11
ARITMETICA DE PUNTEROS Ejemplos:
x 1012
c 1002
float x, *y; char car, *q; 3,25 y=&x; // Asuma que un lotante ocupa 4 bytes y+=3; // Cual es la nueva dirección que almacena y…?.
‘#’
q=&c; // Sabemos que un char ocupa 1 byte en la memoria q++; // Cual es la nueva dirección que almacena q…? Un puntero solo puede apuntar al tipo de dato con el cual fue declarado. ALGORITMOS Y ESTRUCTURA DE DATOS
12
PUNTEROS Utilizando la aritmética de punteros nos desplazamos de unas posiciones de memoria a otras. Pero. ¿cómo acceder a los contenidos de esas posiciones utilizando notación de punteros?
mat[0] = 2 mat[0]
2
mat[7] = 3
mat[1]
mat[2]
mat[3]
16
-4
29
*mat *(mat+1) *(mat+2)
*mat = 2
mat[4]
234 *(mat+4)
*(mat+3)
mat[5]
mat[6]
mat[7]
12
0
3
*(mat+6)
*(mat+5)
*(mat+7) = 3
Empleamos el operador *, indirección que nos da el contenido de la dirección de memoria apuntada. ALGORITMOS Y ESTRUCTURA DE DATOS
13
PUNTEROS Punteros a CADENAS DE CARACTERES: Una cadena de caracteres es un array de caracteres. La forma de definir un puntero a una cadena de caracteres: char *cadena; El identificador del array es la dirección de comienzo del array. Para saber dónde termina la ca, el compilador añade el carácter ‘\0’ (ASCII 0, NULL): char *nombre = “PEPE PEREZ”; nombre
dirección de memoria
P E P E *(nombre+2)
P E R E Z \0 contenido ALGORITMOS Y ESTRUCTURA DE DATOS
14
nombre
PUNTEROS P E P E
P E R E Z \0 *(nombre+2)
Si quiero recorrer la cadena con notaci贸n de puntero:
i = 0; do cout<<*(nombre+i)<<endl; while(*(nombre+ i ++));
Condici贸n de salida
ALGORITMOS Y ESTRUCTURA DE DATOS
15
PUNTEROS #include <iostream> #include <stdlib.h> //Declaracion de funciones using namespace std; void VerContenido(int x[],int); void VerDireccion(int *p,int); void VerContenido1(int *p,int); void VerDireccion1(int *p,int); // programa principal int main() { int x[]={10,20,5,80,45,15,54},*p,n;; n=sizeof(x)/sizeof(n); p=x; //p=&x[0]; VerContenido(x,n); VerDireccion(p,n);cout<<endl; VerContenido1(x,n); VerDireccion1(x,n); cout<<"N="<<n<<endl; system("pause"); } ALGORITMOS Y ESTRUCTURA DE DATOS
16
PUNTEROS //Declaraciones de funciones void VerContenido(int x[],int n) { int i; for(i=0;i<n;i++) cout<<" "<<x[i]<<"\t"; cout<<endl; } void VerDireccion(int *p,int n) { int i; for(i=0;i<n;i++) cout<<(p+i)<<" "; cout<<endl; } ALGORITMOS Y ESTRUCTURA DE DATOS
17
PUNTEROS void VerContenido1(int *p,int n) { int i; for(i=0;i<n;i++) cout<<*(p+i)<<"\t"; cout<<endl; } void VerDireccion1(int *p,int n) { int i; for(i=0;i<n;i++) cout<<p++<<" "; cout<<endl; } ALGORITMOS Y ESTRUCTURA DE DATOS
18
PROBLEMAS CON PUNTEROS #include <iostream> #include <ctype.h> #include <string.h> using namespace std; const int N=80; // funciones prototipo void SoloVocales(char *, char *); int main() { char s[N],s1[N]; cout<<"Ingrese Cadena:";cin.getline(s,80); cout<<endl<<endl; SoloVocales(s,s1); cout<<"La cadena de vocales es "<<s1<<endl<<endl; system("PAUSE"); } ALGORITMOS Y ESTRUCTURA DE DATOS
19
PROBLEMAS CON PUNTEROS void SoloVocales(char *cad,char *cpas) { char c; int i=0; strlwr(cad); while(*cad!='\0') { c=*cad; if((c=='a') || (c=='e') || (c=='i') || (c=='o') || (c=='u' ))
cpas[i++]=c; cad++;
}
} cpas[i]='\0';
ALGORITMOS Y ESTRUCTURA DE DATOS
20
PROBLEMAS CON PUNTEROS #include <iostream> #include <conio.h> using namespace std; char *MinusculasMayusculas(char *p) { char *x=p; while(*p!=0) { if(*p>='a' && *p<='z') *p-=32; p++; } return x; }
ALGORITMOS Y ESTRUCTURA DE DATOS
21
PROBLEMAS CON PUNTEROS void Leer(char *q) { cout<<"Ingrese la cadena:"; while((*q=getchar())!='\n') q++; *q='\0'; } int Numero(char *s) { int m=0; while(*s!=0) { if(*s>='0' && *s<='9') m=m*10+*s-48; s++; } return m; } ALGORITMOS Y ESTRUCTURA DE DATOS
22
PROBLEMAS CON PUNTEROS //Programa principal int main() { char c[254],cn[254]; Leer(c); cout<<"\n\nCadena actual:"<<c<<endl; cout<<"\nNueva cadena: "<<MinusculasMayusculas(c)<<endl; cout<<endl; cout<<"Ingrese Cadena numerica:";gets(cn); cout<<"El numero es:"<<Numero(cn)<<endl; cout<<endl; system("pause"); }
ALGORITMOS Y ESTRUCTURA DE DATOS
23
PROBLEMAS CON PUNTEROS
ALGORITMOS Y ESTRUCTURA DE DATOS
24