Ir al contenido

Programación en C++/Punteros

De Wikilibros, la colección de libros de texto de contenido libre.

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