Diferencia entre revisiones de «Programación en C++/Punteros»

Contenido eliminado Contenido añadido
Wiki13 (discusión | contribs.)
m Revertidos los cambios de 187.188.154.215 (disc.) a la última edición de 177.240.177.47
Línea 7:
|}
 
== Punteros ==
me gusta el
<div style="background:#fffeee; padding:40px; text-align:justify">
Los punteros permiten simular el paso por referencia, crear y manipular estructuras dinamicas de datos, tales como listas enlazadas, pilas, colas y árboles.
Generalmente las variables contienen valores especificos. Los punteros son variables pero en vez de contener un valor especifico, contienen las direcciones de las variables a las que apuntan. Para obtener o modificar el valor de la variable a la que apuntan se utiliza el operador de indirección.
Los punteros, al ser variables deben ser declaradas como punteros antes de ser utilizadas.
 
=== Sintaxis ===
 
<source lang="cpp">
int *ptrID, ID;
ID = 8;
ptrID = &ID; // puntero a ID
</source>
 
ptrID es un puntero a int, mientras que la variable ID es solo una variable del tipo int. Todo puntero debe ser precedido por un asterisco '''(*)''' en la declaración.
 
Se puede declarar más de un puntero en la misma sentencia. En el ejemplo que sigue se ve la declaración de dos punteros a int.
<source lang="cpp">
int *ptrY, *ptrX;
</source>
 
=== Operadores ===
Existen dos operadores a tener en cuenta cuando trabajamos con punteros. El '''operador de dirección (&)''' que devuelve la dirección de memoria de su operando y el '''operador de indirección (*)''' que devuelve un alias para el objeto al cual apunta el operando del puntero.
 
En el siguiente ejemplo vemos como se inicializa una variable X con el valor 15. Luego se crea un puntero a int y por último el puntero pasa a apuntar a la variable X. Esto es, ptrX es un puntero a X.
<source lang="cpp">
int X = 15;
int *ptrX;
ptrX = &X;
</source>
 
=== Punteros y vectores (arrays) ===
Los vectores son punteros constantes. Un vector sin subindice es un puntero al primer elemento del vector.
Una matriz es un vector de vectores. (Ej: int M[3][3];) de manera que en cada elemento del primer vector "se cuelga"
otro vector, pudiendo hacer así referencia a filas y columnas.
<source lang="cpp">
int X[15];
int *ptrX;
ptrX = X; // ptrX recibe la dirección del primer elemento ( 0 ) de X
</source>
Así como también podría escribirse
<source lang="cpp">
int X[15];
int *ptrX;
ptrX = &X[0]; // ptrX es igual a la dirección del primer elemento de X
</source>
 
Se pueden utilizar distintos elementos del vector teniendo en cuenta la sintaxis de punteros.
<source lang="cpp">
int X[15], Y, *ptrX;
ptrX = X;
 
Y = *( ptrX + 7 );
</source>
En este caso puede verse que Y toma el valor del elemento 7 del vector X, siendo 7 el desplazamiento dentro del vector. El operador de indirección queda fuera del paréntesis porque tiene una prioridad superior a la del operador +. De no existir los paréntesis, se sumaria 7 al elemento X[0].
Teniendo en cuenta que los vectoresson punteros constantes, el nombre del vector puede tratarse como un puntero:
<source lang="cpp">
Y = *( X + 7 );
</source>
 
=== Aritmética de Punteros ===
Al usar punteros a matrices, hay que tener en cuenta que la aritmética cambia sensiblemente.
<source lang="cpp">
#include <iostream>
 
using std::cout;
using std::endl;
 
void main()
{
int X[6] = { 1, 2, 3, 4, 5, 6 };
int *prtX;
 
prtX = X; // incializo el valor del puntero.
 
cout << endl << *prtX;
prtX += 2;
cout << endl << *prtX;
prtX -= 2;
cout << endl << *prtX;
prtX++;
cout << endl << *prtX;
}
 
atte: Oscar Torres & David Paz
</source>
En el siguiente código, primero se crea un puntero a un arreglo de 6 elementos y si inicializa el puntero
''prtX'' al primer elemento del arreglo ''X[0]''.
Si tenemos en cuenta que el siguiente ejemplo se ejecuta en una computadora con enteros de 4 bytes, el segundo
elemento de la matriz tendrá en memoria un desplazamiento de 4 bytes, el 2 de ocho y asi sucesivamente.
La operación ''prtX += 2;'' produce un desplazamiento llevándolo al 3 elemento dentro del arreglo.
Debe entenderse que prtX ahora apunta a una dirección de memoria y la instrucción cambia esta dirección
de memoria sumándole 2 multiplicado por el tamaño del tipo de dato del arreglo que en este supuesto sería de 4.
''(dir = ( dir + 2 * 4 ))'', dando por resultado un desplazamiento de 8 bytes.
Sería igual que ejecutar la operación ''prtX = &X[2];''.
La operación ''prtX -= 2'' obedece a la misma lógica estableciendo el puntero al primer elemento del array ''X[0]'' y el
operador ++ modifica el puntero desplazándolo 4 bytes y asignándole el segundo elemento de la matriz.
 
=== Matrices de punteros ===
Para realizar una estructura de datos dinámica, se puede utilizar una matriz donde sus elementos sean punteros.
Suponiendo que queramos hacer un calendario y lo dividamos por semanas. Podríamos utilizar una matriz con los días de la semana.
<source lang="cpp">
const char *dias[7] = { "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" }
</source>
Cada día de la semana, no es un elemento de la matriz, sino que la expresión dias[7] crea una matriz de siete elementos como punteros a char.
 
=== Formas de pasar un valor por referencia ===
 
'''Un puntero constante a un dato no constante'''
<source lang="cpp">
#include <iostream>
void sumoeldoble( int * ); // prototipo
 
void main ()
{
int X = 15;
sumoeldoble( &X ); // Pasa la dirección de memoria de X .
std::cout << X;
 
}
 
void sumoeldoble( int *ptrX )
{
// Toma el valor de X mediante el operador de indirección
// La funcion no devuelve nada porque modifica el valor por referencia.
*ptrX = *ptrX + ( *ptrX * 2 );
}
</source>
 
'''Un puntero no constante a un dato constante'''
<source lang="cpp">
#include <iostream>
 
void imprimeChars( const char * ); // prototipo
 
void main ()
{
char cFrase[] = "Hola Mundo";
imprimeChars( cFrase );
}
 
void imprimeChars( const char *ptrStr )
{
for ( ; *ptrStr != '\0'; ptrStr++ ) //Sin inicialización
std::cout << *ptrStr;
}
</source>
 
'''Un puntero constante a un dato no constante'''
 
Un puntero es constante cuando apunta siempre a la misma dirección de memoria y si el dato no es constante entonces el valor puede ser modificado.
<source lang="cpp">
void main ()
{
int foo, bar;
int * const ptrFoo = &foo; // Apuntador constante a un entero en la dirección de memoria de foo
 
*ptrFoo = 53;
 
 
// Esto devuelve un error porque es un puntero constante.
// No se puede alterar la dirección de memoria a la que apunta.
ptrFoo = &bar;
}
</source>
 
'''Un puntero constante a un dato constante'''
 
El puntero constante apunta siempre a la misma dirección de memoria y el valor al que apunta dicho puntero no puede ser modificado mediante el puntero.
Este es el metodo en que se debe pasar matrices a funciones que solo leen la matriz y no la modifican.
<source lang="cpp">
#include <iostream>
 
using namespace std;
 
int main ()
{
int foo = 3, bar;
const int * const ptrFoo = &foo;
 
cout << foo;
*ptrFoo = 53; //Error porque no puede alterarse el valor
ptrFoo = &bar; // Error
foo = 23;
 
cout << foo;
 
}
</source>
 
=== Punteros a funciones ===
Teniendo en cuenta que el nombre de una función es en realidad la dirección de memoria donde comienza el código, los punteros a funciones contienen la dirección de memoria de la función a la que apunta, y se pueden pasar y retornar entre funciones.
<source lang="cpp">
#include <iostream>
using namespace std;
 
bool functionA( int, int, bool (*)( int ) ); //Prototipo
bool functionB( int ); //Prototipo
 
void main()
{
int x = 113, y = 226;
if ( functionA( x, y, functionB ) )
cout << "\nEl resultado es verdadero";
else
cout << "\nEl resultado es falso";
}
 
bool functionA( int param1, int param2, bool (*verificar)( int ) )
{
if ( ( (*verificar)( param1 ) ) && ( (*verificar)( param2 ) ) )
return true;
}
 
bool functionB( int param )
{
if ( param > 100 )
return true;
else
return false;
}
</source>
En el ejemplo anterior podrá ver que en la definición de los prototipos, la función functionA recibe tres parámetros, siendo el tercer parámetro un puntero a la funcion functionB, practicamente copiando el prototipo sin el nombre.
Cuando se ejecuta functionA, se le pasa como parametro el nombre de la función
 
=== Ordenamiento burbuja ===
'''Ordenamiento burbuja utilizando punteros'''
<source lang="cpp">
#include <iostream>
#include <iomanip>
 
using namespace std;
 
void orden( int *, const int ); // prototipo
void swap( int * const, int * const ); // prototipo
 
int main()
{
const int nSize = 10;
int a[ nSize ] = { 3, 9, 14, 27, 18, 154, 8, 6, 74, 33 };
 
cout << "\nElementos a ordenar\n";
 
for ( int j = 0; j < nSize; j++ )
cout << setw( 5 ) << a[ j ];
 
orden( a, nSize ); // ordena el arreglo
 
cout << "\nElementos ordenados\n";
 
for ( int j = 0; j < nSize; j++ )
cout << setw( 5 ) << a[ j ];
cout << endl;
 
return 0; // indica terminación exitosa
 
}
 
void orden( int *matriz, const int nSize )
{
for ( int pasada = 0; pasada < nSize - 1; pasada++ )
{
for ( int k = 0; k < nSize - 1; k++ )
{
if ( matriz[ k ] > matriz[ k + 1 ] )
{
swap( &matriz[ k ], &matriz[ k + 1 ] );
}
}
}
}
 
void swap( int * const ptrElemento1, int * const ptrElemento2 )
{
int mantiene = *ptrElemento1;
*ptrElemento1 = *ptrElemento2;
*ptrElemento2 = mantiene;
}
</source>
 
=== Proyecto de colas para un banco ===
'''Por cada 2 clientes normales pasa uno VIP al Cajero'''
 
 
El codigo es muy simple pero muy trabajado y depurado, esta relizado con if/while....
lo mas complicado son los apuntadores, pero nada del otro mundo,
muestra el perfecto uso de funciones, tiene una clave: jahvi, de
todas lo puedes leer en el codigo. Compila perfecto en DEV C++.
Tiene una interfaces muy creativa, ideal para estudiantes que se están
inciando en el desarrollo de software con programación estructurada.
recuerda copiarlo en un pagina en blanco en dev c++ desde aqui: (copialo completo y compilalo)
 
<source lang="cpp">
#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
 
using namespace std;
 
typedef struct nodo
{
int cedula;
struct nodo*siguiente;
}tiponodo;
 
typedef tiponodo *pnodo;
typedef tiponodo *cola;
 
cola cola_n=NULL;
cola cola_vip=NULL;
int solic;
 
void insertar (cola *cola_n)
{
cola aux, creado;
 
creado=(pnodo)malloc(sizeof(tiponodo));
 
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;
cout<<" ||||||||||||||||||||METROPOLI banco universal||||||||||||||||||||"<<endl;
cout<<" |||||||||||||||||||||||Le da la bienvenida|||||||||||||||||||||||"<<endl;
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;
cout<<" Estimado cliente: Introduzca su numero de cedula"<<endl;
cin>> creado->cedula;
cout<<" Pronto sera atendido"<<endl;
 
 
if ((*cola_n)==NULL)
{
creado->siguiente=*cola_n;
*cola_n=creado;
}
else
{
aux=*cola_n;
 
while(aux!=NULL)
{
if(aux->siguiente==NULL)
{
creado->siguiente=aux->siguiente;
aux->siguiente=creado;
aux=aux->siguiente;
}
aux=aux->siguiente;
}
}
}
 
void mostrar_cola (cola cola_n)
{
cola aux;
aux=cola_n;
if(aux==NULL)
{
cout<<"No hay clientes en cola"<<endl;
}
else
{
while(aux!=NULL)
{
cout<<"Cedula: "<<aux->cedula<<endl;
cout<<""<<endl;
aux=aux->siguiente;
cout<<"* Clientes ordenados por orden de llegada((((((SIMCOLAS))))))"<<endl;
}
}
}
//modificado hasta acá... falta de orden por parte del creador
void insertar_vip (cola *cola_vip){
cola aux_2, creado_vip;
creado_vip=(pnodo)malloc(sizeof(tiponodo));
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;//62
cout<<" ||||||||||||||||||||METROPOLI banco universal||||||||||||||||||||"<<endl;
cout<<" |||||||||||||||||||||||Le da la bienvenida|||||||||||||||||||||||"<<endl;
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;
cout<<" Estimado cliente: Introduzca su numero de cedula"<<endl;
cin>> creado_vip->cedula;
cout<<" Pronto sera atendido"<<endl;
if ((*cola_vip)==NULL){
creado_vip->siguiente=*cola_vip;
*cola_vip=creado_vip;
}else{
aux_2=*cola_vip;
while(aux_2!=NULL){
if(aux_2->siguiente==NULL){
creado_vip->siguiente=aux_2->siguiente;
aux_2->siguiente=creado_vip;
aux_2=aux_2->siguiente;
}
aux_2=aux_2->siguiente;
}
}
}
 
void mostrar_cola_vip (cola cola_vip){
cola aux_2;
aux_2=cola_vip;
if(aux_2==NULL){
cout<<"No hay clientes V.I.P en cola"<<endl;
}else{
while(aux_2!=NULL){
cout<<"Cedula: "<<aux_2->cedula<<endl;
cout<<""<<endl;
cout<<"* Clientes ordenados por orden de llegada((((((SIMCOLAS))))))"<<endl;
aux_2=aux_2->siguiente;
}
}
}
void pop (cola *cola_n){
if((*cola_n)==NULL){
cout<<"No hay clientes en cola ((((((SIMCOLAS))))))"<<endl;
cout<<""<<endl;
}
if((*cola_n)!=NULL){
cout<<"Cliente: "<<(*cola_n)->cedula;
cout<<" es su turno"<<endl;
*cola_n=(*cola_n)->siguiente;
free(cola_n);
system("PAUSE");
cout<<""<<endl;
}
if((*cola_n)==NULL){
cout<<"No hay clientes en cola ((((((SIMCOLAS))))))"<<endl;
cout<<""<<endl;
}else{
cout<<"Cliente: "<<(*cola_n)->cedula;
cout<<" es su turno"<<endl;
*cola_n=(*cola_n)->siguiente;
free(cola_n);
system("PAUSE");
cout<<""<<endl;
}
}
void pop_vip(cola *cola_vip){
if(cola_vip!=NULL){
cout<<"Cliente: "<<(*cola_vip)->cedula;
cout<<" es su turno"<<endl;
*cola_vip=(*cola_vip)->siguiente;
free(cola_vip);
}else{
cout<<"No hay usuarios V.I.P en cola ((((((SIMCOLAS))))))"<<endl;
}
}
void menu();
void Insertar();
void insertar_vip();
void mostrar_cola();
void mostrar_colavip();
void solicitar_numero();
void salir();
 
struct perly{
char uxer[];
}data;
 
struct perly *p = &data;
 
 
int main(int argc, char *argv[])
{
system("color 0a");
cout<<" * * * "<<endl;
cout<<" * * "<<endl;
cout<<" * | * * * * "<<endl;
cout<<" * -+- * "<<endl;
cout<<" __ | * * * * "<<endl;
cout<<" ___| | * _|_ * ____ ____ "<<endl;
cout<<" [_]|°°|__ _| |_ * | |....| |....| * * "<<endl;
cout<<" | | _|[] []|_ ___ | |....| | ___|__ "<<endl;
cout<<" [_]| °° |__|_ ______| | | |_| |....| || -- - | * * "<<endl;
cout<<" |________ |__ | |# #| |_| |....| || - -- | _____ "<<endl;
cout<<" [_]| _____ | |__[]| | | |_| |....|__|| -- - | |* * *| "<<endl;
cout<<" | [___] | |__ |# #| |_| |....|__|| -- -_|_|* * *| "<<endl;
cout<<" [_]| | °° | | |__| |__|....| || ___|* *|* * *| "<<endl;
cout<<" | _____ | |__ #|_______|....| | |* *|* *|* * *| "<<endl;
cout<<" [_]| [___] | °° |__|_______|__ | | |* *|* *|* * *| "<<endl;
cout<<" | | __|_____________|__ |* *|* *|* * *| "<<endl;
cout<<" [_]| _____ | °° _|___________________|_ |* *|* *|* * *| "<<endl;
cout<<" | [___] | |_______________________| ______________ "<<endl;
cout<<" __|_______|_________|_______________________| _________________ "<<endl;
cout<<" |_______________________________________________________________|"<<endl;
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;//62
cout<<" ||||||||||||||||||||METROPOLI banco universal||||||||||||||||||||"<<endl;
cout<<" ||||||||||||Sistema Integral para el Manejo de COLAS|||||||||||||"<<endl;
cout<<" |||||||||||||||||||||||||||||SIMCOLAS||||||||||||||||||||||||||||"<<endl;
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;
cout<<" |||||||||Creado por: Javier Rodriguez Caracas-Venezuela||||||||||"<<endl;
cout<<" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"<<endl;
cout<<" Login: ";
char usuario[6] = "jahvi";
cin.getline(p->uxer,6);
if (strcmp(p->uxer,usuario) == 0) {
cout<<"Bienvenid@ al sistema "<<endl; menu();
cout<<""<<endl;
}else{
cout<<"Acceso Denegado. Consulte al Admisnistrador "<<endl;
}
 
system("PAUSE");
return EXIT_SUCCESS;
}
void menu() {
short a;
do {
 
cout<<""<<endl;
cout<< "0 - Agregar Cliente"<<endl;
cout<< "1 - Agregar Cliente V.I.P"<<endl;
cout<< "2 - Solicitar Numero"<<endl;
cout<< "3 - Mostrar Cola"<<endl;
cout<< "4 - Mostrar Cola V.I.P"<<endl;
cout<< "5 - Salir del Sistema"<<endl;
cout<<""<<endl;
 
fflush(stdout);
 
cout<<"Opcion #:";
cin>>a;
cout<<""<<endl;
if (a == 5)
exit(1);
switch(a){
case 0 :
Insertar();
break;
case 1 :
insertar_vip();
break;
 
case 2 :
solicitar_numero();
break;
case 3 :
mostrar_cola();
break;
 
case 4 :
mostrar_colavip();
break;
 
case 5 :
salir();
break;
default :
puts("Usted no ha seleccionado nada, porfavor seleccione algo\n");
break;
};
} while (1);
}
 
void Insertar(){
insertar(&cola_n);
}
void insertar_vip(){
insertar(&cola_vip);
}
void mostrar_cola(){
mostrar_cola(cola_n);
}
void mostrar_colavip(){
mostrar_cola_vip(cola_vip);
}
void solicitar_numero(){
pop(&cola_n);
if(cola_vip!=NULL){
pop_vip(&cola_vip);
}else{
cout<<"No hay cliente V.I.P en cola ((((((SIMCOLAS))))))"<<endl;
}
}
void salir(){
}
</source>
 
 
{| align="center" cellpadding="12"
|-
| &#8592; [[Programación en C++/Funciones virtuales|Funciones virtuales]]
| [[#Punteros|Arriba]]
| &#8592; [[Programación en C++/Estructuras II|Estructuras II]]
|}
 
[[fr:Programmation C++/Les pointeurs]]
[[pl:C++/Referencje]]
[[pt:Programar em C++/Ponteiros e matrizes]]