Programación en C++/Punteros
Editores:
← Funciones virtuales | ← Estructuras II |
Punteros
[editar]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
[editar]int *ptrID, ID;
ID = 8;
ptrID = &ID; // puntero a ID
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.
int *ptrY, *ptrX;
Operadores
[editar]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.
int X = 15;
int *ptrX;
ptrX = &X;
Punteros y vectores (arrays)
[editar]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.
int X[15];
int *ptrX;
ptrX = X; // ptrX recibe la dirección del primer elemento ( 0 ) de X
Así como también podría escribirse
int X[15];
int *ptrX;
ptrX = &X[0]; // ptrX es igual a la dirección del primer elemento de X
Se pueden utilizar distintos elementos del vector teniendo en cuenta la sintaxis de punteros.
int X[15], Y, *ptrX;
ptrX = X;
Y = *( ptrX + 7 );
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 vectores son punteros constantes, el nombre del vector puede tratarse como un puntero:
Y = *( X + 7 );
Aritmética de Punteros
[editar]Al usar punteros a matrices, hay que tener en cuenta que la aritmética cambia sensiblemente.
#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;
}
copiado del Internet para una tarea
atte: Oscar Torres & David Paz
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
[editar]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.
const char *dias[7] = { "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" }
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
[editar]Un puntero constante a un dato no constante
#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 );
}
Un puntero no constante a un dato constante
#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;
}
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.
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;
}
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.
#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;
}
Punteros a funciones
[editar]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.
#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;
}
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
[editar]Ordenamiento burbuja utilizando punteros
#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;
}
Proyecto de colas para un banco
[editar]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)
#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(){
}
← Funciones virtuales | Arriba | ← Estructuras II |