Fullscreen
Loading...
 
Imprimir Comparte esta página

Tutorial Cpp

PROGRAMACIÓN ESTRUCTURADA


​​Estructura del Código en C++.​


Los archivos que se van a crear, van a tener la exención C, .cc, .cpp, .CPP, .c++, .cp, o .cxx, y tendrán la siguiente estructura básica:

Hello World
Copy To Clipboard
  1 . #include <iostream>
  2 . using namespace std;
  3 . 
  4 . // This is a tradition
  5 . 
  6 . int main() /* you can comment like this to*/
  7 . {
  8 .    cout << "Hello World\n"; // Print 'Hello Word' 
  9 .    return 0;
 10 . }
 11 . 
 12 . /* The general form is:
 13 .  * int main (int argc, char *argv[] , other_parameters ) { body }
 14 .  * argc -    Non-negative value representing the number of arguments passed 
 15 .  *           to the program from the environment in which the program is run.
 16 .  * argv -    Pointer to the first element of an array of pointers to 
 17 .  *           null-terminated multibyte strings that represent the arguments
 18 .  *           passed to the program from the execution environment (argv[0] 
 19 .  *           through argv[argc-1]). The value of argv[argc] is guaranteed to be 0.
 20 .  * body -    The body of the main function  
 21 .  *   
 22 .  */

y se guardará en helloworld.cpp.

NOTA: En caso de usar el compilador GCC, y dejarlo escoger el lenguaje automáticamente, entonces los archivos .C son C++, mientras que .c son de C.

Temas sugeridos

  1. Identificadores (nombres de variables).
  2. Tipos de variables.
  3. Palabras reservadas en C++.
  4. Uso del ";".


Compilado básico.


Primero se chequea que se tenga un compilador gcc (lo usual es que si). En la consola se escribe lo siguiente

g++
g++ -v


y el resultado debe algo parecido a esto

Resultado de g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 5.3.1-8' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs 
--enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id 
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu 
--enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify 
--enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo 
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar 
--enable-objc-gc --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic 
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.3.1 20160205 (Debian 5.3.1-8)

Ahora, se va a compilar el código que guardamos en el archivo helloword.cpp, y en la consola se escribe:
primera compilación
g++ helloworld.cpp -o helloworld.out

Aquí el compilador es g++, y la opción -o es para decir el nombre del archivo de salida .out (ejecutable), Y este se puede ejecutar por medio de la consola así:
Ejecución
./programa.out

Por el momento esto es todo lo que se va a necesitar del compilador, mas adelante se volverá sobre este asunto.

Operadores.


Un operador le dice al compilador que realice una manipulación determinada. En C++ se puede dividir en seis grupos.
  • Operadores Aritméticos.
    Como su nombre lo indica realizan operaciones aritméticas básicas sobre las variables numéricas. Suponiendo que a las variables X e Y se les asigna los valores de 6 y 4
    • Suma +
    • Resta -
    • Multiplicación *
    • División /
    • Modulo %
    • Incremento ++
    • Decremento --

    Ejemplo:
    Operadores aritmeticos
    #include <iostream>
    using namespace std;
     
    main()
    {
       int a = 21;
       int b = 10;
       int c ;
    
       cout << "a=" << a << endl ;
       cout << "b=" << b << endl ;
       c = a + b;
       cout << "a+b=" << c << endl ;
       c = a - b;
       cout << "a-b=" << c << endl ;
       c = a * b;
       cout << "a*b=" << c << endl ;
       c = a / b;
       cout << "a/b=" << c << endl ;
       c = a % b;
       cout << "a%b=" << c << endl ;
       c = a++; 
       cout << "a++=" << c << endl ;
       c = a--; 
       cout << "a--=" << c << endl ;
       return 0;
    }
    Al compilar este código, y ejecutarlo muestra el resultado de aplicar cada uno de los operadores aritméticos.

  • Operadores Relacionales.
    Estos operadores realizan comparaciones entre las variables y resultan en valores lógicos (TRUE o FALSE).
    • Igual que ==
    • Diferente que !=
    • Mayor que >
    • Menor que <
    • Mayor o igual que >=
    • Menor o igual que <=

    Ejemplo:
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    
    using namespace std;
    
    main(int argc, char *argv[])
    {
      bool c;
    
      cout << "el valor 0 equivale a FALSE, y 1 a TRUE" << endl ;
      
      if(argc != 3)
        {
          fprintf(stdout,"Ingreso %d argumentos, el número de argumentos es 2\n",argc);
          return 1;
        }//endif
      
      int a = atoi(argv[1]);
      int b = atoi(argv[2]);
      
      cout << "a=" << a << endl;
      cout << "b=" << b << endl;
      
      
      c = (a == b);
      cout << "a == b es:" << c << endl ;
      
      c= ( a < b );
      cout << "a < b es:"<< c << endl ;
      
      c= ( a > b );
      cout << "a > b es:"<< c << endl ;
      
      c= ( a <= b );
      cout << "a <= b es:"<< c << endl ;
      
      c= ( b >= a );
      cout << "b >= a es:"<< c << endl ;
      
      return 0;
    }
    Este codigo cuando se compila y se ejecuta recibe dos enteros y los usa para ilustrar el uso de los operadores relacionales.

  • Operadores Lógicos
    Estos operadores actúan sobre las variables lógicas, y tienen como resultado valores lógicos
    • Disyunción &&
    • Conjunción ||
    • Negación !

    Ejemplo:
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    
    using namespace std;
    
    main(int argc, char *argv[])
    {
      if(argc != 3)
        {
          fprintf(stdout,"Ingreso %d argumentos, el número de argumentos es 2\n",argc);
          return 1;
        }//endif
    
      bool a = atoi(argv[1]); /*si es diferente de cero es uno*/
      bool b = atoi(argv[2]);
      
      cout << "a=" << a<< endl;
      cout << "b=" << b<< endl;
    
      if ( a && b )
        {
          cout << "a && b es TRUE" << endl; 
        }else
        {
          cout << "a && b es FALSE" << endl;
        }
       if ( a || b )
        {
          cout << "a || b es TRUE" << endl; 
        }else
        {
          cout << "a || b es FALSE" << endl;
        }
      if ( !(a && b) )
        {
          cout << "!(a && b) es TRUE" << endl; 
        }else
        {
          cout << "!(a && b) es FALSE" << endl;
        }
      if ( !(a || b) )
        {
          cout << "!(a || b) es TRUE" << endl; 
        }else
        {
          cout << "!(a || b) es FALSE" << endl;
        }
     
      return 0;
    }


  • Operadores bit a bit
    Estos operadores realizan acciones sobre las variables bit a bit
    • Disyunción binaria &
    • Conjunción binaria |
    • Complemento binario ~
    • Desplazamiento binario a derecha >>
    • Desplazamiento binario a izquierda <<

    Ejemplo:
    #include <iostream>     /*cin,cout*/
    #include <stdio.h>      /*fprintf */
    #include <stdlib.h>     /* strtol */
    #include <string.h>     /* strcat */
    
    using namespace std;
    
    /*Creamos una función para convertir los numeros a su forma binaria*/
    
    const char *byte_to_binary(int x)
    {
        static char b[64];
        b[0] = '\0';
    
        int z;
        for (z = 1024; z > 0; z >>= 1)
          {				  
          if ((x & z) == z)		  
            strcat(b,"1");
          else
    	strcat(b,"0");
        }
    
        return b;
    }
    
    int main(int argc, char *argv[])
    {
      if(argc != 3)
        {
          cout << "Ingreso" << argc << "argumentos, el número de argumentos es 2"<< endl;
          return 1;
        }//endif
    
      int a = atoi(argv[1]); 
      int b = atoi(argv[2]);
      int c;
      
      if((a>=1024| b>=1024))
        {
          cout << "Alguno de los argumentos,es mayor que 1024"<< endl;
          return 1;
        }//endif
    
      
      printf ("a= %d\n",a);
      printf ("binario: a= %s\n",byte_to_binary(a));
      printf ("b= %d\n",b);
      printf ("binario b=: %s\n",byte_to_binary(b));
      
      c = a & b;
      printf ("a & b= %d\n",c);
      printf ("binario a & b=: %s\n",byte_to_binary(c));
      
      
      c = a | b;             
      printf ("a | b= %d\n",c);
      printf ("binario a | b=: %s\n",byte_to_binary(c));
      
      c = a ^ b;
      printf ("a ^ b= %d\n",c);
      printf ("binario a ^ b=: %s\n",byte_to_binary(c));
      
      c = ~a;               
      printf ("~a= %d\n",c);
      printf ("binario ~a=: %s\n",byte_to_binary(c)); 
    
      c = a << 2;            
      printf ("a << 2= %d\n",c);
      printf ("binario a << 2=: %s\n",byte_to_binary(c));
      
      c = a >> 2;
      printf ("a >> 2= %d\n",c);
      printf ("binario a >> 2=: %s\n",byte_to_binary(c));
      
      return 0;
    }

    Cuando se compila y ejecuta este código se obtiene
    usuario@debian:/C++/Ejemplos$ ./operador_bitwise.out 11 12
    a= 11
    binario: a= 00000001011
    b= 12
    binario b=: 00000001100
    a & b= 8
    binario a & b=: 00000001000
    a | b= 15
    binario a | b=: 00000001111
    a ^ b= 7
    binario a ^ b=: 00000000111
    ~a= -12
    binario ~a=: 11111110100
    a << 2= 44
    binario a << 2=: 00000101100
    a >> 2= 2
    binario a >> 2=: 00000000010

  • Operadores de Asignación
    Estos operadores asignan los valores de las variables
    • Asignación =
    • Operación y Asignación OP=

    Ejemplo:
    #include <iostream>     /*cin,cout*/
    #include <stdlib.h>     /* atoi */
    
    
    using namespace std;
    
    
    int main(int argc, char *argv[])
    {
      if(argc != 3)
        {
          cout << "Ingreso" << argc << "argumentos, el número de argumentos es 2"<< endl;
          return 1;
        }//endif
    
      int a = atoi(argv[1]); 
      int b = atoi(argv[2]);
      int c;
    
      cout << "a= " <<a<< endl ;
      cout << "b= " <<a<< endl ;
      
      c =  a;
      cout << "Operador c = a : entonces c= " <<c<< endl ;
      
      c +=  a;
      cout << "Operador c -+= : entonces c= " <<c<< endl ;
      
      c -=  a;
      cout << "Operador c -=  : entonces c= " <<c<< endl ;
      
      c *=  a;
      cout << "Operador c  *= : entonces c= " <<c<< endl ;
      
      c /=  a;
      cout << "Operador c  /= : entonces c= " <<c<< endl ;
      
      c  = b;
      cout << "Operador c = b : entonces c= " <<c<< endl ;
      
      c %=  a;
      cout << "Operador c %=  : entonces c= " <<c<< endl ;
      
      c <<=  2;
      cout << "Operador c <<= : entonces c= " <<c<< endl ;
      
      c >>=  2;
      cout << "Operador c >>= : entonces c= " <<c<< endl ;
      
      c &=  2;
      cout << "Operador c &=  : entonces c= " <<c<< endl ;
      
      c ^=  2;
      cout << "Operador c ^=  : entonces c= " <<c<< endl ;
      
      c |=  2;
      cout << "Operador c |=  : entonces c= " <<c<< endl ;
      
      return 0;
    }//End_main


  • Otros Operadores
    Éstos operadores no pueden ser clasificados en uno de los anteriores grupos
    • sizeof
    • Condición ? X : Y
    • ,
    • .
    • ->
    • & a un puntero puntero
    • * a un puntero puntero

    Ejemplo 1:
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
    
      int ch=sizeof(char)     ; 
      int in=sizeof(int)      ; 
      int si=sizeof(short int); 
      int li=sizeof(long int) ; 
      int fl=sizeof(float)    ; 
      int du=sizeof(double)  ; 
      int wc=sizeof(wchar_t) ; 
      
      cout << "tamaño de una variable en bytes : " << endl;
      cout << endl;
      cout << "tamaño de una variable tipo char :      " << ch << endl;
      cout << "tamaño de una variable tipo int :       " << in << endl;
      cout << "tamaño de una variable tipo short int : " << si << endl;
      cout << "tamaño de una variable tipo long int :  " << li << endl;
      cout << "tamaño de una variable tipo float :     " << fl << endl;
      cout << "tamaño de una variable tipo double :    " << du << endl;
      cout << "tamaño de una variable tipo wchar_t :   " << wc << endl;
      
      int bch=ch*8; 
      int bin=in*8; 
      int bsi=si*8; 
      int bli=li*8; 
      int bfl=fl*8; 
      int bdu=du*8; 
      int bwc=wc*8;
      
      cout << endl << endl;
    
      cout << "tamaño de una variable en bits : " << endl;
      cout << endl;
      cout << "tamaño de una variable tipo char :      " << bch << endl;
      cout << "tamaño de una variable tipo int :       " << bin << endl;
      cout << "tamaño de una variable tipo short int : " << bsi << endl;
      cout << "tamaño de una variable tipo long int :  " << bli << endl;
      cout << "tamaño de una variable tipo float :     " << bfl << endl;
      cout << "tamaño de una variable tipo double :    " << bdu << endl;
      cout << "tamaño de una variable tipo wchar_t :   " << bwc << endl;
    
      cout << endl << endl;
      
      string flag; //esto es nuevo!! y depende de la librería string
      cout << "Uso operador 'condition? X:Y': " << endl << endl;
      flag= (ch > li) ? "Yes":"No" ; 
      cout << "(char > long int)? " << flag <<endl<< endl<< endl;
    
      int var=0;
      int a=100;
      cout << "Uso operador 'coma': " << endl<< endl;
      cout << "Valor inicial var= "<< var << " ,Valor inicial a= "<< a << endl;
      var = (a--, a+10, a*2);
      cout << "var = (a--, a+10, a*2)" << endl;
      cout << "Valor final var= " <<var<< endl;
      
      cout << endl << endl;
    
      int c;
      float b=2.342345;
      cout << "Uso operador 'cast': " << endl<< endl;
      cout << "b= "<< b << endl;
      
      c = (int) b;
      cout << "(int)b = " << c << endl<< endl ;
    
      
       return 0;
    }
    Ejemplo 2 Punteros:
    #include <iostream>
     
    using namespace std;
     
    int main ()
    {
       int  var;
       int  *ptr; // en ptr se guarda direcciones de memoria
       int  val;
    
       var = 3000;
       ptr = &var;
       val = *ptr;
    
       cout << "var = 3000" << endl;
       cout << "var = " << var << endl;
       cout << "ptr = &var" << endl;
       cout << "ptr = " << ptr << endl;
       cout << "val = *ptr" << endl;
       cout << "val = " << val << endl;
    
       return 0;
    }


Decisiones.​

Ya se ha usado anteriormente, en varios ejemplos. A continuación la sintaxis de los diferentes tipos de decisions:

if



if(expresión lógica)
{
   // Instrucciones que se ejecutan para el caso en que expresión lógica = TRUE
}


if...else


if(expresión lógica)
{
   // Instrucciones que se ejecutan para el caso en que expresión lógica = TRUE
}
else
{
  // Instrucciones que se ejecutan para el caso en que expresión lógica = FALSE
}


switch


switch(expresión){
    case valor-1 :
       Comandos;
       break; //Opcional
    case valor-2  :
       Comandos;
       break; //Opcional
       .
       .
       .
    case valor-n  :
       Comandos;
       break; //Opcional
  
    // Se pueden tener los casos que se quieran.
    default : //Opcional
       Comandos;
}


Loops.


Los loops o bucles, se utilizan cuando es necesario ejecutar cierta parte (o partes) del código un número determinado de veces. A continuación se listan
varios tipos de bucles en C++

whileloop

Ejecuta un grupo de sentencias mientras la condición sea verdadera, dicha condición se evalúa antes de comenzar el loop. La estructura es

Image


y la sintaxis básica en C++ es la siguiente:
while(condition)
{
   statement(s);
}

donde condition es una expresión que se interpreta como verdadero cualquier valor diferente de cero, y cero como falso.

Ejemplo:
#include <iostream>
using std::cout;
using std::endl;

int main ()
{

  int i = 20;

   // while loop execution
   while( i > 1 )
   {
       cout << "i= " << i << endl;
       i=i-1;
   }
 
   return 0;
}



for loop

Ejecuta una secuencia de sentencias un determinado número de veces. La estructura es
Image

y la sintaxis en C++ se muestra a continuación
for ( init; condition; increment )
{
   statement(s);
}

Ejemplo
#include <iostream>

 
int main ()
{
  for( int i = 20; i > 1; i-- )
    {
      std::cout << "i= " << i << std::endl;
    }
  
  return 0;
}


do ... while loop

Como su nombre lo indica, realiza una tarea mientras la condición sea verdadera, se debe de tener en cuenta que la condición se evalúa al final de cada iteración. su estructura es la siguiente

Image

Ejemplo:
{CODE(colors="cpp")}#include <iostream>
using std::cout;
using std::endl;

int main ()
{

  int i = 20;

   // while loop execution
   while( i > 1 )
   {
       cout << "i= " << i << endl;
       i=i-1;
   }
 
   return 0;
}{CODE}


Comandos de Control de loops.

Modifican la manera en como se recorre el loop
  • break: Para el loop, sin importar si se alcanzó o no la condición de parada. La ejecución sigue fuera del loop (diferente de return).
    Sintaxis:
    break;
  • continue: Hace que el la ejecución salte el resto del contenido del loop, y continua después de chequear la condición del loop.
    Sintaxis:
    continue;
  • goto: Hace un salto hacia donde este la etiqueta (label)
    Sintaxis:
    goto label;
    ..
    .
    label: statement;

    Ejemplo:
    #include <iostream>     /*cin,cout*/
    #include <stdlib.h>     /* strtol */
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
      if(argc != 2)
        {
          cout << "Ingreso" << argc << "argumentos, el número de argumentos es un entero"<< endl;
          return 1;
        }//endif
    
      int a = atoi(argv[1]); 
      int i=0;
    
      cout << "Número elegido:" << a << endl;
    
    
     COMP:for( ; ; )//esto es un loop infinito //COMP es la etiqueta para el goto
        {
          i++;
          cout << "Número de loop:" << i << endl;
          cout << "Número:" << a << endl;
          
          if (a>0)
    	{
    	  cout << "a=" << a <<" ,Número mayor que cero (uso continue)" << endl;
    	  a=a-1;
    	  continue;   
    	  
    	}else if (a==0)
    	{
    	  cout << "a=" << a <<" ,Número igual a cero (uso breake)" << endl; 
    	  break;
    	  
    	}else if (a<0)
    	{
    	  cout << "a=" << a <<" ,Numero menor que cero (uso goto)" << endl;
    	  a++;
    	  goto COMP;
    	  
    	  
    	}else
    	{
    	  cout << "Error en el cast" << endl;
    	  return 1;
    	}
          
          
        }
      
      return 0;
    }

Funciones.


Tipo Nombre( lista de parámetros )
{
   Cuerpo de la función
}


Donde:
  • Tipo: Cual es el tipo de dato que devuelve la función i.e. char, int, double, etc.
  • Nombre: Nombre con el cual se va a llamar la función.
  • Parámetros: Entradas de la function de la forma Tipo Nombre
  • Cuerpo: Lo que hace propiamente la función.


Ejemplo:
#include <stdio.h>      /* printf */
#include <string.h>     /* strcat */
#include <stdlib.h>     /* strtol */

// Este codigo convierte enteros en binarios menores de 2^10

const char *byte_to_binary(int x) //Función tipo puntero a char, y tiene un entero como parámetro
{
    static char b[64];
    b[0] = '\0';

    int z;
    for (z = 1024; z > 0; z >>= 1)// 1024 es 2^10 un 1 y 10 ceros en binario
      {                           // z>>= mueve el numero bit por bit a la derecha
      if ((x & z) == z)           // compara (x&z) con z (ver tabla de &)
        strcat(b,"1");
      else
	strcat(b, "0" );
    }

    return b; // devuelve el vector de char 
}

int main(void)
{
  /* byte to binary string */
  
  printf("%s\n", byte_to_binary(250));
  return 0;
}



Arreglos.​


Un arreglo en C++ es una secuencia ordenada de elementos de un tipo, que se organizan consecutivamente en la memoria.

Declarando un arreglo e inicializando

Hay una declarar un arreglo (por el momento estático) en C++

tipo Nombre [ tamaño ];


Donde:
  • tipo: tipo de las variables del arreglo.
  • Nombre: Nombre con el que se llama al arreglo
  • tamaño: cual es el número de elementos del arreglo (>0)

y varias formas de inicializarlas

double arreglo[5] = {200.2, 26.1, 30.24, 12.0, 20.0};

double arreglo[] = {200.2, 26.1, 30.24, 12.0, 20.0};

double otro[5];

otro[0] =200.2;
otro[1] =26.1;
otro[2] =30.24;
otro[3] =12.0;
otro[3] =20.0;


todas estas formas crean exactamente el mismo tipo de arreglo. En la última forma asigna los elementos de manera individual, es bueno tener en cuenta que los indices de los arreglos en C++ comienzan en cero (0).
Ejemplo:
#include <iostream>
using std::cout;
using std::endl;

#include <iomanip>
using std::setw;//esta funcion genera espacios en el output

#include <stdlib.h>     /*atoi*/


int main(int argc, char *argv[])
{
  if(argc != 2)
    {
      cout << "Ingreso" << argc << "argumentos, el número de argumentos es 1"<< endl;
      return 1;
    }//endif

  int n = atoi(argv[1]);
  int m[ 10 ]; // se declara el arreglo 
 
  // se inicializa el arreglo usando un for          
  for ( int i = 0; i < 10; i++ )
    {
      m[ i ] = i* n; 
    }
  cout << "La Tabla de multiplicar del número " << n << endl;
  cout << "Número" << setw( 13 ) << "Valor" << endl;
  
  // output each array element's value                      
  for ( int j = 0; j < 10; j++ )
    {
      cout << setw( 4 )<< j << setw( 13 ) << m[ j ] << endl;
    }
 
   return 0;
}


Arreglos multidimensionales


De forma similar a los de una dimensión se declaran
tipo Nombre[Tamaño1][Tamaño2]...[TamañoN];


Ejemplo:
#include <iostream>
using namespace std;
 
int main ()
{
   // Declaramos e inicializamos una matriz de 4X3 de enteros, llamada a.
  int a[4][3] = { {0,0,0}, {1,2,3}, {2,4,6}, {3,6,9}};
 
   // Ahora se muestran en pantalla                      
   for ( int i = 0; i < 4; i++ )
      for ( int j = 0; j < 3; j++ )
      {
         cout << "a[" << i << "][" << j << "]: ";
         cout << a[i][j]<< endl;
      }
 
   return 0;
}


Uso de punteros en arreglos

Cuando se declara un arreglo, lo que se hace es declarar un puntero constante al primer elemento del arreglo, así si se declara el arreglo double vector[10] ;, entonces vector es un puntero constante a la dirección de memoria &vector[0]

Así se pueden usar nombres de arreglos como punteros constantes, o viceversa. luego es lo mismo vector[4] (que es el nombre del arreglo), que usar la dirección en memoria *(vector +4) (que toma la posición de memoria *vector y la aumenta en 4).

Ejemplo:
#include <iostream>
using namespace std;
 
int main ()
{
  double vector[4] = {10,20,30,40};
  double *p;
  
  p = vector;
  
  cout << "muestro los valores arreglos " << endl; 
   for ( int i = 0; i < 4; i++ )
   {
       cout << "vector[" << i << "]= ";
       cout << vector[i] << endl;
   }

   cout << "muestro los valores usando punteros " << endl; 
   for ( int i = 0; i < 4; i++ )
   {
       cout << "*(p + " << i << ") : ";
       cout << *(p + i) << endl;
   }

   cout << "Muestro los valores usando el nombre como dirección " << endl;
   for ( int i = 0; i < 4; i++ )
   {
       cout << "*(vector + " << i << ") : ";
       cout << *(vector + i) << endl;
   }
 
   return 0;
}


Pasar un arreglo como argumento de una función


Hay tres maneras de pasar un arreglo como argumento a una función:
  • Arreglo definido:
    tipo_funcion nombre_funcion(tipo_arreglo nombre_arreglo[tamaño_arreglo])
    {
    .
    }

  • Arreglo indefinido:
    tipo_funcion nombre_funcion(tipo_arreglo nombre_arreglo[])
    {
    .
    }

  • puntero al arreglo:
    tipo_funcion nombre_funcion(tipo_arreglo *nombre_arreglo)
    {
    .
    }

Funciones que entregan arreglos


Si se quiere que una función devuelva arreglos, se debe de declarar de la siguiente manera
tipo_funcion * nombre_funcion()
{
.
}


Strings.​


Los strings en C son arreglos de chars, que terminan con el símbolo null (\0), y pueden ser asignados de dos formas
char saludo[5] = {'H', 'o', 'l', 'a','\0'};
y
char saludo[] = "Hola";


luego en C++ es posible usar todas las herramientas de C para el manejo de estos elementos, se sugiere que se estudien las siguientes funciones de C para el manejo de chars
  • strcpy
  • strcat
  • strlen
  • strcmp
  • strchr
  • strstr

Strings en C++

En C++, la librería estándar posee una clase (luego se hablará de esto), que permite mucha mas libertad en la manipulación de cadenas de caracteres o strings, solo vasta con incluir la librería <string>.

Ejemplo
#include <iostream>
#include <string>    //llamo la librería

using namespace std;

int main ()
{
   string str1 = "Hola";
   string str2 = "Mundo";
   string str3, str4;
   int  len ;

   //se igualan a los valores

   str3= " "; // guardo un espacio en str3
   
   // se pueden concatenar las cadenas de caracteres
   str4 = str1 + str3 + str2;
   cout << "str1 + str3 + str2 : " << str4 << endl;

   // las funciones asociadas al objeto str4 se llaman con el operador .
   len = str4.size();
   cout << "tamaño" << endl;
   cout << "str4.size() :  " << len << endl;

   return 0;
}



Punteros.​


Sabemos que las variables almacenan diferentes tipos de datos en posiciones bien definidas de la memoria. Estas direcciones pueden se pueden ver usando el operador & como se vio anteriormente.
Ya se ha usado el concepto de puntero, pero para ser mas preciso se intentará hacer una definición:
Puntero: Es una variable cuyo valor es la dirección en memoria de otra variable. La forma en que se declara es
tipo *nombre;

Aunque el tipo de variable que guarda el puntero siempre es el mismo (hexadecimal), la diferencia es el tipo de variable a la que el puntero apunta.
Las acciones que se realizan sobre los punteros son las siguientes:
  • Declarar.
  • Asignar.
  • Acceder.

Ejemplo:

#include <iostream>

using namespace std;

int main ()
{
   int  var = 20;   
   int  *ip;        // Declaración de variable tipo puntero a entero 

   ip = &var;       // Asignación de valor del puntero

   //Muestro el valor almacenado en var
   cout << "Valor de variable var: " << var << endl;

   //Muestro la dirección de memoria de var que está guardada en ip
   cout << "Dirección de memoria guardada en ip: " << ip << endl;

   //Acceso a la valor almacenado en var a través del puntero
   cout << "Valor de *ip: " << *ip << endl;

   //Tambien puedo mostrar la dirección de memoria del puntero
   cout << "Dirección de memoria de ip, &ip : " << &ip << endl;
   

   return 0;
}


Punteros a NULL

Por buena práctica de programación es habitual en el momento de declarar un puntero se le asigna por defecto el valor de NULL, i.e que no apunta a ningun lado (aunque realmente apunte a la dirección 0). Esto se usa para evitar dejar en un programa punteros sin asignar.

Ejemplo:

#include <iostream>
#include <stdlib.h>     /*atoi*/

using namespace std;

int main(int argc, char *argv[])
{

  int  *ptr = NULL;
  
  if(argc >=2)
    {
      int a = atoi(argv[1]);
      ptr = &a;
      
    }  //endif

  if(!ptr)
    {
      cout << "Puntero a NULL"<< endl ; //si trata de acceder a *ptr, Segmentation fault!!!

    }
  if(ptr)
    {
      cout << "Asignado, con valor:" << *ptr << endl;
    }       

  return 0;
}


Aritmética de punteros

Como un puntero es una variable que contiene una dirección en memoria, que en últimas es un número (hexadecimal), luego sobre este número se pueden realizar operaciones algebraicas. Las operaciones permitidas sobre los puntero son cuatro: ++, --, - y + . Además pueden ser comparados por medio de ==,<=,>=, < y >.

Ejemplo:
#include <iostream>

using namespace std;
const int MAX = 4;

int main ()
{
  int  var[MAX] = {1, 3, 5,7};
   int  *ptr;

   ptr = var; //asigna la dirección del primer elemento de var a ptr (ojo var es un arreglo)
   int i = 0;
   while ( ptr <= &var[MAX - 1] ) /* compara la direccion en ptr con la del último
				     elemento del arreglo var, para parar el ciclo*/
   {
      cout << "Dirección de var[" << i << "]: " << ptr << endl;

      cout << "Valor de var[" << i << "]= " << *ptr << endl;

      ptr++;// Aumento el puntero en una pocición (memoria contigua)
      i++;
   }
   return 0;
}


Arreglos de punteros

Siguiendo la lógica de los arreglos, un arreglo de punteros se declara así
tipo *nombre[tamaño];


Ejemplo:

#include <iostream>
using namespace std;

#include <iomanip>
using std::setw;
 
const int MAX = 5;
 
int main ()
{
  //recordando que un string es una cadena de caracteres, caracterizada por un puntero
  const char *nombres[] = {"Camilo","Omar","Abdul","Alejo","Alephys"};
  
   cout << "Número" << setw( 10 ) << "Nombre" << setw( 15 )<< "Direccion" << endl;
   
   for (int i = 0; i < MAX; i++)
     {
       cout << setw( 4 ) << i << setw( 12 ) << nombres[i] << setw( 17 );
       cout << &nombres[i] <<endl;
     }
   return 0;
}


Puntero a puntero


Es un puntero que guarda la dirección de memoria de un puntero que a su vez guarda la dirección de memoria de una variable, se declara así:
tipo**var;


Ejemplo:
#include <iostream>
 
using namespace std;
 
int main ()
{
   int  var;
   int  *ptr;
   int  **pptr;

   var = 3000;

   // La dirección de var se guarda en ptr
   ptr = &var;

   // La direccion de ptr se guarda en pptr
   pptr = &ptr;

   // Accediendo al valor a través de la variable, puntero y puntero a puntero.
   cout << "var= " << var << endl;
   cout << "*ptr= " << *ptr << endl;
   cout << "**pptr= " << **pptr << endl;
   cout << "Direcciones de memoria" << endl;
   
   cout << "&var= " << &var << endl;
   cout << "ptr= " << ptr << endl;
   cout << "*pptr= " << *pptr << endl;
   cout << "pptr= " << pptr << endl;
   cout << "&pptr= " << &pptr << endl;
   
   
   return 0;
}


Pasando un puntero como argumento

Para pasar a una función un puntero (dirección en memoria), simplemente en la declaración de los parámetros de la función el puntero.


Ejemplo:

#include <iostream>
using namespace std;
 
// Declaramos la funcion, encuentra el numero mayor del arreglo
double mayor(double *arr, int tamano);

int main ()
{
  // 
  double arreglo[] = {1,2,15,8,2};
  double M;
  
  // Se pasa el puntero a la funcion como argumento.
  M = mayor( arreglo, 5 ) ;
  
  // output the returned value 
  cout << "El número mayor es: " << M << endl; 
  
  return 0;
}


//Funciones

double mayor(double *arr, int tamano)
{
  double may;          
  may=arr[0]; //le asigno el primer elemento
  
  for (int i = 1; i < tamano; ++i)
    {
      if ( may < arr[i])
	{
	  may = arr[i];	
	}//end if
    }//end for
  
  return may;
}


Funciones que devuelven puntero


De manera similar a como se declara una función que devuelve un tipo definido de dato, se puede hacer que la función devuelva un puntero (dirección de memoria), declarándola así

tipo* nombre(argumentos)
{
.
}


Es buena idea declarar la variable que se va a devolver como estática, pues de otro modo en el momento en que termine la ejecución del programa, la memoria de las variables locales es liberada.
Ejemplo: Ver ejemplo de Funciones, y compilar el código con y sin static en la función byte_to_binary.


Referencias.​



C++ I/O.​

Estructuras.​

Depuración (gdb, valgrind).​


PROGRAMACIÓN BASADA EN OBJETOS

Clases y Objetos.​

- Clase es una estructura abstracta de datos que contiene atributos y metodos
- Objecto es la instancia de una clase, es cuando declaro una variable del tipo de la clase.
- Atributos son las variables de las clases
- métodos son las "funciones" de la clase

Herencia.​

- es tomar todas las propiedades de una clase(Clase base) y pasarlas a una nueva clase(Clase hija).

Sobrecarga de operadores

- es hacer que una clase pueda usar los operadores definidos en c++, con procedimientos definidos dentro de la clase.

Polimorfismo.​

- sobrecargar metodos

Abstracción.​

Encapsulacion.

es darle acceso a los datos en tres niveles​
- public: el objecto puede acceder
- protected: la clase puede acceder desde la herencia
- private: solo se accede en la clase.

ejemplos.​


posicion.h
#ifndef POS_H
#define POS_H

namespace mylib
{
class posicion
{
public:
    posicion():x(0),y(0),z(0){}
    posicion(double _x,double _y,double _z)//constructor
    {
        x=_x;
        y=_y;
        z=_z;
    }
    void setPosicion(double _x,double _y,double _z)//metodo setter
    {
        x=_x;
        y=_y;
        z=_z;
    }
    //metodos getter
    double getX(){return x;}
    double getY(){return y;}
    double getZ(){return z;}
    //sobre carga de operador =
    posicion &operator=(posicion &pos); 
    double distancia(posicion &pos);
protected:
double x,y,z;    
};
}

#endif


posicion.cxx
#include<posicion.h>
#include<cmath>
using namespace mylib;

posicion &posicion::operator=(posicion &pos)
{
    this->x=pos.x;
    this->y=pos.y;
    this->z=pos.z;
    return *this;
}


double posicion::distancia(posicion &pos)
{
    return sqrt(pow(x-pos.x,2)+pow(y-pos.y,2)+pow(z-pos.z,2));
}


main.cxx
#include<posicion.h>
#include<iostream>

int main()
{
    mylib::posicion p1(0,0,0);
    mylib::posicion p2(1,1,1);

    std::cout<<"distancia entre dos puntos = "<<p1.distancia(p2)<<std::endl;
    
    return 0;
}




Makefile


CXXFLAGS=-I.

main: posicion.cxx posicion.h main.cxx
	$(CXX) $(CXXFLAGS) $<  $@.cxx -o $@