miércoles, 16 de julio de 2014

EVAP 7


METODOS DE ORDENAMIENTO



METODOS DE ORDENAMIENTO 

Debido a que las estructuras de datos son utilizadas para almacenar información, para poder recuperar esa información de manera eficiente es deseable que aquella esté ordenada. Existen varios métodos para ordenar las diferentes estructuras de datos básicas.
En general los métodos de ordenamiento no son utilizados con frecuencia, en algunos casos sólo una vez. Hay métodos muy simples de implementar que son útiles en los casos en dónde el número de elementos a ordenar no es muy grande (ej, menos de 500 elementos). Por otro lado hay métodos sofisticados, más difíciles de implementar pero que son más eficientes en cuestión de tiempo de ejecución.

Los métodos sencillos por lo general requieren de aproximadamente n x n pasos para ordenar n elementos.

Los métodos simples son: insertion sort (o por inserción directa) selection sort, bubble sort, y shellsort, en dónde el último es una extensón al insertion sort, siendo más rápido. Los métodos más complejos son el quick-sort, el heap sort, radix y address-calculation sort. El ordenar un grupo de datos significa mover los datos o sus referencias para que queden en una secuencia tal que represente un orden, el cual puede ser numérico, alfabético o incluso alfanumérico, ascendente o descendente.

Se ha dicho que el ordenamiento puede efectuarse moviendo los registros con las claves. El mover un registo completo implica un costo, el cual se incrementa conforme sea mayor el tamaño del registro. Es por ello que es deseable evitar al máximo el movimiento de los registros. Una alternativa es el crear una tabla de referencias a los registros y mover las referencias y no los datos. A continuación se mostrarán los métodos de ordenamiento empezando por el más sencillo y avanzando hacia los mas sofisticados 
La eficiencia de los algoritmos se mide por el número de comparaciones e intercambios que tienen que hacer, es decir, se toma n como el número de elementos que tiene el arreglo a ordenar y se dice que un algoritmo realiza O(n2) comparaciones cuando compara n veces los n elementos, n x n = n2. 

ORDENAMIENTO DE BURBUJA

La Ordenación de burbuja (Bubble Sort en inglés) es un sencillo algoritmo de ordenamiento. Funciona revisando cada elemento de la lista que va a ser ordenada con el siguiente, intercambiándolos de posición si están en el orden equivocado. Es necesario revisar varias veces toda la lista hasta que no se necesiten más intercambios, lo cual significa que la lista está ordenada. Este algoritmo obtiene su nombre de la forma con la que suben por la lista los elementos durante los intercambios, como si fueran pequeñas "burbujas". También es conocido como el método del intercambio directo. Dado que solo usa comparaciones para operar elementos, se lo considera un algoritmo de comparación, siendo el más sencillo de implementar.

Burbuja

#include<stdio.h> 
#include<conio.h> 
int a[3]={3,2,1}; 
int i,j,aux,n=3; 
void main(){ 
clrscr(); 
for(i=0;i<=n;i++){ 
for(j=0;j<n-1;j++){ 
if(a[j]>a[j+1]){ 
aux=a[j]; 
a[j]=a[j+1]; 
a[j+1]=aux; 



for(i=0;i<3;i++) 

printf("%d",a);
}
getch();

ORDENAMIENTO SHELL El ordenamiento Shell (Shell sort en inglés) es un algoritmo de ordenamiento. El método se denomina Shellen honor de su inventor Donald Shell. Su implementación original, requiere O(n2) comparaciones e intercambios en el peor caso. Un cambio menor presentado en el libro de V. Pratt produce una implementación con un rendimiento de O(n log2 n) en el peor caso. Esto es mejor que las O(n2) comparaciones requeridas por algoritmos simples pero peor que el óptimo O(n log n). Aunque es fácil desarrollar un sentido intuitivo de cómo funciona este algoritmo, es muy difícil analizar su tiempo de ejecución. El algoritmo Shell sort mejora el ordenamiento por inserción comparando elementos separados por un espacio de varias posiciones. Esto permite que un elemento haga "pasos más grandes" hacia su posición esperada. Los pasos múltiples sobre los datos se hacen con tamaños de espacio cada vez más pequeños. El último paso del Shell sort es un simple ordenamiento por inserción, pero para entonces, ya está garantizado que los datos del vector están casi ordenados.
 
#include<stdio.h>
#include<conio.h>
int a[5];
int n=5;
void main()
{
int inter=(n/2),i=0,j=0,k=0,aux;
clrscr();
for (i=0; i<5; i++)
{
printf("INSERTA UN VALOR DEL INDICE %d", i);
scanf("%d",& a);
}
while(inter>0){
for(i=inter;i<n;i++)
{
j=i-inter;
while(j>=0) {
k=j+inter;
if(a[j]<=a[k]){
j--;
}
else{
aux=a[j];
a[j]=a[k];
a[k]=aux;
j=j-inter;
}
}
}
inter=inter/2;
}
for(i=0;i<5;i++)
{
printf("%d n",a);
getch();
}
}  
 
ORDENAMIENTO POR INSERCIÓN  
El ordenamiento por inserción (insertion sort en inglés) es una manera muy natural de ordenar para un ser humano, y puede usarse fácilmente para ordenar un mazo de cartas numeradas en forma arbitraria. Requiere O(n²) operaciones para ordenar una lista de n elementos.

Inicialmente se tiene un solo elemento, que obviamente es un conjunto ordenado. Después, cuando hay k elementos ordenados de menor a mayor, se toma el elemento k+1 y se compara con todos los elementos ya ordenados, deteniéndose cuando se encuentra un elemento menor (todos los elementos mayores han sido desplazados una posición a la derecha) o cuando ya no se encuentran elementos (todos los elementos fueron desplazados y este es el más pequeño). En este punto se inserta el elemento k+1 debiendo desplazarse los demás elementos.



Inserccion 
#include<stdio.h> 
#include<conio.h> 
int a[4]={4,1,7,2}; 
int n=4; 
int i,j,aux; 
void main(){ 
clrscr(); 
for(i=1;i<n;i++) 

j=i; 
aux=a;
while(j>0 && aux<a[j-1])
{
a[j]=a[j-1];
j--;
}
a[j]=aux;
}
for(i=0;i<4;i++)
{
printf("%d",a);
}
getch();


ORDENAMIENTO POR SELECCION  
El ordenamiento por selección (Selection Sort en inglés) es un algoritmo de ordenamiento que requiere operaciones para ordenar una lista de n elementos.

Su funcionamiento es el siguiente:

  • Buscar el mínimo elemento de la lista
  • Intercambiarlo con el primero
  • Buscar el mínimo en el resto de la lista
  • Intercambiarlo con el segundo
Y en general:

  • Buscar el mínimo elemento entre una posición i y el final de la lista
  • Intercambiar el mínimo con el elemento de la posición i
De esta manera se puede escribir el siguiente pseudocódigo para ordenar una lista de n elementos indexados desde el 1:

para i=1 hasta n-1
    minimo = i;
    para j=i+1 hasta n
        si lista[j] < lista[minimo] entonces
            minimo = j /* (!) */
        fin si
    fin para
    intercambiar(lista[i], lista[minimo])
fin para 
 

 
 Seleccion #include<stdio.h> #include<conio.h>  int x[4]={1,4,8,6};  int n=4,j=0,i=0;  int temp=0,minimo=0; void main() clrscr();  for(i=0;i<n-1;i++) minimo=i; for(j=i+1;j<n;j++)  if(x[minimo] > x[j]) minimo=j;  temp=x[minimo]; x[minimo]=x x=temp;  }  for(i=0;i<n;i++)  {  printf("%d",x);  }  getch();  }

EVAP6

MATRICES

Una matriz en programación no es mas que un conjunto de vectores o arreglos multidimensionales,donde cada dimensión tiene su propio rango.
Existen conjuntos de datos que por su naturaleza son mejor representados mediante tablas o matrices multidimensionales que por vectores.

Por ejemplo, se puede representar las calificaciones de 4 asignaturas cursadas por 6 estudiantes mediante una tabla, donde cada fila correspondería a un estudiante y cada columna a una asignatura. Cada dato individual (la calificación de un estudiante en una asignatura dada) es un elemento de esta tabla y ocupa una celda identificable por el número de la fila y el número de la columna.
De esta manera, cada elemento de la tabla queda completamente identificado mediante dos subíndices: el primero para identificar la fila y el segundo para identificar la columna.

El programador debe tener presente que la memoria de las computadoras es lineal, por lo que la mayoría de los compiladores almacenan en memoria los elementos de una matriz linealizandola por filas; es decir, todos los elementos de la primera fila primero, los de la segunda después y así sucesivamente.
EJEMPLO:
El siguiente programa, utiliza el operador el operador sizeof() para determinar


el número de bytes que utilizan diferentes clases de arreglos declarados.

#include <iostream.h>

void main(void)
 {
 int caja[3][3];
 float salarioAnual[52][5];
 char paginas[40][60][20];

 cout << "Numero de bytes utilizado por caja[3][3] = "
 << sizeof(caja) << endl;
 cout << "Numero de bytes utilizado por salarioAnual[52][5] = "
 << sizeof(salarioAnual)<< endl;
 cout << "Numero de bytes utilizado por paginas[40][60][20] = "
 << sizeof(paginas)<< endl;

 }//Fin de main()

EVAP5


VectoresCadenas de caracteres →

Los vectores son una forma de almacenar datos que permiten contener una serie de valores del mismo tipo, cada uno de los valores contenidos tiene una posición asociada que se usará para accederlos. Está posición o índice será siempre un número entero positivo.
En C la cantidad de elementos que podrá contener un vector es fijo, y en principio se define cuando se declara el vector. Los vectores se pueden declarar de la siguiente forma:
 tipo_elemento nombre[largo];
Esto declara la variable nombre como un vector de tipo_elementos que podrá contener largo cantidad de elementos, y cada uno de estos elemento podrá contener un valor de tipo tipo_elemento.
Por ejemplo:
 double valores[128];
En este ejemplo declaramos un vector de 128 elementos del tipo double, los índices de los elementos irían entre 0 (para el primer elemento y 127 para el último).
De la misma forma que con las otras declaraciones de variables que hemos visto se le puede asignar un valor iniciar a los elementos.
O también se pueden declarar:
 tipo_elemento nombre[largo]={valor_0, valor_1, valor_2};
En caso estamos asignadole valores a los primeros 3 elementos del vector nombre. Notar que largo debe ser mayor o igual a la cantidad de valores que le estamos asignando al vector, en el caso de ser la misma cantidad no aporta información, por lo que el lenguaje nos permite escribir:
 tipo_elemento nombre[]={valor_0, valor_1, valor_2};
Que declarará nombre como el vector de largo 3.
Para acceder a un elemento accederemos a través de su posición. Es decir:
 tipo_elemento elemento;
 ...
 elemento = nombre[2];
Asumiendo que tenemos el vector anterior definido estaríamos guardando valor_2 en elemento.
Veamos algunos ejemplos:
/*
 * Ejemplo : El producto escalar de dos vectores
 */
#include <stdio.h>
 
double producto_escalar(double v1[], double v2[], int d);
 
int main()
{ 
 const int largo = 3;
 double vector_1[] = {5,1,0};
 double vector_2[] = {-1,5,3};
 
 double resultado = producto_escalar(vector_1, vector_2, largo);
 
 // imprime el resultado
 printf("(%f, %f, %f) . (%f, %f, %f) = %f\n",
  vector_1[0], vector_1[1], vector_1[2],
  vector_2[0], vector_2[1], vector_2[2],
  resultado);
 return 0;
}
 
/* producto escalar entre dos vectores */
double producto_escalar(double v1[], double v2[], int d)
{
 double resultado = 0;
 int i;
 for (i=0; i < d; i++) {
  resultado += v1[i] * v2[i];
 }
 return resultado;
}
En el ejemplo anterior usamos los vectores de C para representar vectores matemáticos y calcular el producto escalar entre ellos. Una peculiaridad que se puede notar es que al recibir un arreglo en una función no se especifica el largo, volveremos a esto en un capítulo posterior.
Otra función clásica es la búsqueda de un máximo o mínimo, que podemos escribirla de la siguiente manera:
int buscar_maximo(double valores[], int num_valores)
{
 int maximo_pos = 0;
 for (int i = 1; i < num_valores; i++) {
  if (valores[i] > valores[maximo_pos]) {
   maximo_pos = i;
  }
 }
 return maximo_pos;
}
Otro ejemplo sencillo, calcular el promedio de los valores.
double promedio(double valores[], int largo)
{
 double suma=0;
 for (int i=0;i<largo;i++) {
  suma+=valores[i];
 }
 return suma/largo;
}
Cuando una función recibe un vector por parámetro y cambia su contenido y el cambio es permanente (se ve aún fuera de la función). Esto puede parecer extraño después del énfasis que pusimos en resaltar que todos los parámetros de una función se reciben por valor, pero se aclarará en el siguiente capitulo.
Mientras tanto usemos esto para definir una función que le aplique otra función que recibe por parámetro a cada elemento del vector, guardando el resultado en el mismo vector y una llamada de ejemplo a esta.
void cuadrados(double vector[], int largo)
{
 for (int i=0;i<largo;i++) {
  vector[i]=cuadrado(vector[i]);
 }
}
...
double cuadrado(double valor) {
 return valor*valor;
}
...
 cuadrados(elementos,num_elem);
...
De la misma forma que venimos usando vectores de tipos básicos, podemos tener vectores de vectores, estos se declaran de la siguiente forma:
int matriz[3][7];
int tabla[3][4]={ { 1, 2, 3, 4},
    { 5, 6, 7, 8}, /* los espacios y saltos de líneas no son tomados en cuenta */
    { 9,10,11,12} };
double v[2][2][2];
...
printf("tabla[0][1]: %i\n", tabla[0][3]); // Imprime 4
printf("tabla[2][0]: %i\n", tabla[2][0]); // Imprime 9 
...
En este ejemplo tabla es un vector de longitud 3, cuyos elementos son vectores de longitud 4 de elementos de tipo int.
En resumen, suponiendo que v[n] es un vector de cualquier tipo de dato con n cantidad de posiciones, al vector v se le aplican las siguientes reglas:
  1. La primera posición siempre será v[0]
  2. La última posición es v[n-1]
  3. En versiones previas a C99 n es una constante definida antes de la declaración de v[n]

EVAP4

Funciones

Definiendo una función

Modelo de programación estructurada
Una función es un conjunto de líneas de código que realizan una tarea específica y puede retornar un valor. Las funciones pueden tomar parámetros que modifiquen su funcionamiento. Las funciones son utilizadas para descomponer grandes problemas en tareas simples y para implementar operaciones que son comúnmente utilizadas durante un programa y de esta manera reducir la cantidad de código. Cuando una función es invocada se le pasa el control a la misma, una vez que esta finalizó con su tarea el control es devuelto al punto desde el cual la función fue llamada.

<tipo> [clase::] <nombre> ( [Parámetros] )
{
    cuerpo;
}
Ejemplo de una función
Para comenzar, vamos a considerar el caso en el cual se desea crear la función cuadrado(), que deberá devolver el cuadrado de un número real (de punto flotante), es decir, cuadrado() aceptará números de punto flotante y regresará una respuesta como número flotante.
Nota: aunque para la función que veremos el tipo de retorno coincide con el tipo de parámetro pasado, algunas veces las cosas pueden cambiar, es decir, no es obligatorio que una función reciba un parámetro de un tipo y que tenga que regresar una respuesta de dicho tipo.
// regresar el cuadrado de un número
double Cuadrado(double n)
{
    return n*n;
}

Parámetros[editar]

Normalmente, las funciones operan sobre ciertos valores pasados a las mismas ya sea como constantes literales o como variables, aunque se pueden definir funciones que no reciban parámetros. Existen dos formas en C++ de pasar parámetros a una función; por referencia o por valor. El hecho es que si en una declaración de función se declaran parámetros por referencia, a los mismos no se les podrá pasar valores literales ya que las referencias apuntan a objetos (variables o funciones) residentes en la memoria; por otro lado, si un parámetro es declarado para ser pasado por valor, el mismo puede pasarse como una constante literal o como una variable. Los parámetros pasados por referencia pueden ser alterados por la función que los reciba, mientras que los parámetros pasados por valor o copia no pueden ser alterados por la función que los recibe, es decir, la función puede manipular a su antojo al parámetro, pero ningún cambio hecho sobre este se reflejará en el parámetro original.
Parámetros por valor
La función cuadrado() (ver arriba) es un clásico ejemplo que muestra el paso de parámetros por valor, en ese sentido la función cuadrado() recibe una copia del parámetro n. En la misma función se puede observar que se realiza un calculo ( n*n ), sin embargo el parámetro original no sufrirá cambio alguno, esto seguirá siendo cierto aún cuando dentro de la función hubiera una instrucción parecida a n = n * n; o n*=n;.
Parámetros por referencia
Para mostrar un ejemplo del paso de parámetros por referencia, vamos a retomar el caso de la función cuadrado, salvo que en esta ocasión cambiaremos ligeramente la sintaxis para definir la misma. Veamos:
// regresar el cuadrado de un número
double cuadrado2(double &n)
{
    n *= n;
    return n;
}
Al poner a prueba las funciones cuadrado() y cuadrado2() se podrá verificar que la primera de estas no cambia el valor del parámetro original, mientras que la segunda sí lo hace.

Llamar a una función[editar]

para llamar a la función cuadrado() vista anteriormente, podemos emplear:
cout << cuadrado(25);
cout << cuadrado(X);
R = cuadrado(X); // guardar en R el cuadrado de X

Funciones void[editar]

Bajo ciertas circunstancias se deseará escribir funciones que no regresen valor alguno (esto sería algo parecido a escribir procedures en Pascal) y para ello podemos declarar a la función como void. La palabra reservada void es utilizada para declarar funciones sin valor de retorno y también para indicar que una función específica no requiere de parámetros. Por ejemplo, la función pausa() que se verá en seguida, no devolverá valor alguno y la misma no requiere de parámetros.
// esta función requiere de la librería iostream
void pausa(void)
{
    cout << "Por favor presione <Enter> HOLA...";
    cin.get();
    cin.ignore(255, '\n');  // rechazar caracteres introducidos antes de <Enter>
}
Notas: se debe de aclarar que el uso de la palabra void dentro de los parentesis es opcional al momento de declarar una función. Así, la función pausa() podría haberse declarado como void pausa(), y la misma puede invocarse como: pausa();.

Funciones anidadas[editar]

A diferencia de Pascal, el lenguaje C, C++ no permite anidar funciones, sin embargo, dentro de una funcíon puede existir la llamada a una o más funciones declaradas previamente.

Funciones de tipo puntero (*)[editar]

En muchas ocasiones se desea que ciertas funciones regresen una referencia o puntero hacia un tipo (sea este estructurado o no) específico de dato en lugar de un valor específico. En tales casos, la función se deberá declarar como para que regrese un puntero. Por ejemplo, supongamos que deseamos crear una función para convertir un número entero en notación decimal a una cadena de caracteres en forma de números binarios, luego, la función mencionada podría escribirse para que reciba el número entero como parámetro y regrese un puntero a una cadena de caracteres conteniendo la conversión. Para ser más puntuales, vamos a escribir un programa en donde se verá la función binstr(), y cuyo objetivo será precisamente convertir números decimales en cadenas binarias.
Nota: observe que en la sintaxis para declarar funciones tipo puntero se debe de poner el símbolo * despues del tipo y antes del nombre de la función que se está declarando. Esto se puede ver en el programa, ya que la función binstr se declara como: char *binstr(unsigned int);
#include <iostream>
#include <string.h>
 
using namespace std;
 
// declaración de prototipo
char *binstr(unsigned int);
 
// punto de prueba
int main()
{
    int n = 128;
    cout << "decimal = " << n << ",  binario = " << binstr(n) << endl;
    cin.get();
}
 
// definición de función binstr()
// nota: esta funcion requiere de la librería estándar string
char *binstr(unsigned int n)
{
    static char buffer[65];
    int i = 0;
 
    strcpy(buffer, "0");
 
    if (n > 0) {
        while (n > 0) {
            buffer[i] = ( n & 1 ) + '0';
            i++;
            n >>= 1;
        }
        buffer[i] = '\0';
        strrev(buffer);
     }    // fin (n > 0)
    return buffer;
}

Variables estáticas y automáticas[editar]

Dentro de una función, las variables y/o constantes pueden ser declaradas como: auto (por omisión) o como static. Si una variable dentro de una función es declarada como estática significa que la misma retendrá su valor entre las llamadas a la función. Por otro lado, la variables automáticas pierden su valor entre las llamadas. En el programa anterior puede verse que el arreglo de caracteres (buffer[65]) se ha declarado como estático para garantizar que dicho buffer retenga los datos aún despues de que la función termine. En el mismo ejemplo, si el buffer no se declara como estático, el contenido del mismo podría ser destruido al salir de la función y los resultados obtenidos podrían ser no deseados.

Parámetros constantes[editar]

Los parámetros usados por una función pueden declararse como constantes ( const ) al momento de la declaración de la función. Un parámetro que ha sido declarado como constante significa que la función no podrá cambiar el valor del mismo ( sin importar si dicho parámetro se recibe por valor o por referencia ).
Ejemplo:
int funcionX( const int n );
void printstr( const char *str );

Parámetros con valor por defecto[editar]

Los parámetros usados por una función pueden declararse con un valor por defecto. Un parámetro que ha sido declarado con valor por defecto es opcional a la hora de hacer la llamada a la función. Ejemplo: Dada la función:
void saludo( char* mensaje = "Hola sudafrica 2010" );
la misma puede ser invocada como:
saludo();  // sin parámetro
saludo("Sea usted bienvenido a C++"); // con parámetro
Para ver un ejemplo más, vamos a considerar el caso de la función binstr() del programa funciones01. Ahora, vamos modificar dicha función, salvo que esta ocasión nos interesa que la misma sirva para convertir números decimales en cadenas numéricas y cuya base de conversión sea pasada como parámetro. Es decir, la función de la que estamos hablando podrá convertir números decimales a: binario, octal, decimal, hexadecimal, etc.; y la única condición será que la base indicada esté entre el 2 y el 36, inclusive.
Nota: Ya que la función servirá para convertir números a cualquier representación la nombraremos como numstr() en lugar de binstr(). Si la función es invocada sin el parámetro base regresará una cadena de digitos decimales.
#include <iostream>
#include <stdlib.h>
 
using namespace std;
 
// declaración de prototipo
char *numstr(unsigned int, const int base = 10);
 
// punto de prueba
int main()
{
    int n = 128;
    cout << "decimal = " << n << ",  binario = " << numstr(n, 2) << endl;
    cout << "decimal = " << n << ",  octal.. = " << numstr(n, 8) << endl;
    cin.get();
}
 
// definición de función numstr()
// nota: esta funcion requiere de la librería stdlib.h
char *numstr(unsigned int n, const int base)
{
    static char buffer[65];
    itoa(n, buffer, base);
    return buffer;
}

Parámetros de tipo puntero[editar]

Anteriormente se mencionó que en C++ los parámetros a una función pueden pasarse por valor o por referencia, al respecto, podemos agregar que los parámetros también pueden pasarse como punteros. El paso de parámetros de punteros es bastante parecido al paso de parámetros por referencia, salvo que el proceso de los datos dentro de la función es diferente. Por ejemplo, las funciones:
void referencia( int &X ) { X = 100; }
void puntero( int *X ) { *X = 100; }
ambas reciben un puntero o referencia a un objeto de tipo entero, por lo tanto cualquiera de las funciones del ejemplo puede cambiar el valor de la variable entera apuntada por X, la diferencia radica en la forma en que cada una de las mismas lleva cabo la tarea. Si en la función puntero() en lugar de usar *X = 100; se usara X = 100; se le asignaría 100 al puntero X, más no al objeto apuntado por X, y esto podría ser la causa de que el programa se terminara de manera abrupta.

Parámetros estructurados[editar]

Al igual que cualquier otro tipo los parámetros de tipo estruturado pueden pasarse por valor o por referencia, sin embargo, podría ser que si una estructura es pasada por valor el compilador mostrara una advertencia ( warning ) indicando que se pasado por valor una estructura, puesto que el paso de estructuras por valor es permitido usted puede ignorar la advertencia, pero lo mejor es pasar estructuras por referencia. Si una estructura es pasada por valor y si esta es muy grande podria ser que se agotara la memoria en el segmento de pila ( Stack Segment ), aparte de que la llamada a la función sería más lenta.
Para ver un ejemplo, consideremos el caso del siguiente tipo estructurado:
struct empleado {
    char nombre[32];
    int  edad;
    char sexo;
};
Ahora, pensemos que deseamos escribir una función para imprimir variables del tipo empleado. Así, la función puede escribirse de las tres maneras siguientes:
void ImprimeEmpleadoV( empleado e)
{
 cout << "Nombre: " << e.nombre << endl;
 cout << "Edad: " << e.edad << endl;
 cout << "Sexo: " << e.sexo << endl;
 
}
 
// Parametro empleado pasado por referencia
void ImprimeEmpleadoR( empleado &e )
{
 cout << "Nombre: " << e.nombre << endl;
 cout << "Edad: " << e.edad << endl;
 cout << "Sexo: " << e.sexo << endl;
 
}
 
// Parametro empleado pasado como puntero
void ImprimeEmpleadoP( empleado *e )
{
 cout << "Nombre: " << e->nombre << endl;
 cout << "Edad: " << e->edad << endl;
 cout << "Sexo: " << e->sexo << endl;
}

Funciones sobrecargadas[editar]

C++, a diferencia del C estándar, permite declarar funciones con el mismo nombre y a esto se conoce como sobrecarga de funciones. Las funciones sobrecargadas pueden coincidir en tipo, pero al menos uno de sus parámetros tiene que ser diferente. En todo caso, si usted trata de declarar funciones sobrecargadas que coincidan en tipo y número de parámetros el compilador no se lo permitirá. Para poner un ejemplo vamos a considerar el caso de dos funciones cuyo nombre será divide, ambas regresarán el cociente de dos números, salvo que una de ellas operará sobre números enteros y la otra lo hará sobre números reales ( de punto flotante ).
Nota: cuando en los programas se hace una llamada a una función sobrecargada, el compilador determina a cual de las funciones invocar en base al tipo y número de parámetros pasados a la función.
#include <iostream.h>
#include <stdlib.h>
 
using namespace std;
 
// divide enteros
int divide(int a, int b)
{
    cout << "división entera" << endl;
    return ( (b != 0) ? a/b : 0);
}
 
// divide reales
double divide(double a, double b)
{
    cout << "división real" << endl;
    return ( (b != 0) ? a/b : 0);
}
// punto de prueba
int main()
{
    cout << divide(10, 3) << endl;
    cout << divide(10.0, 3.0) << endl;
    cin.get();
}

Número variable de parámetros[editar]

En C,C++ se pueden crear funciones que operen sobre una lista variable de parámetros, es decir, en donde el número de parámetros es indeterminado. En esta sección se mostrará un ejemplo de la manera en que podemos crear funciones para manejar tales asuntos, y para ello haremos uso de tres macros soportadas por C++:
  1. va_list puntero de argumentos
  2. va_start inicializar puntero de argumentos
  3. va_end liberar puntero de argumentos
La sintaxis que usaremos para declarar funciones con lista de parámetros variables es:
1) tipo nombrefuncion(...)
2) tipo nombrefuncion(int num, ...)
donde:
  1. tipo es el tipo regresado por la función
  2. nombrefuncion es el nombre de la función
  3. int num es el número de parámetros que la función procesará
  4. ... esta notación se emplea para indicar que el número de parámetros es variable
Nota: observe que la primera forma de declaración es realmente variable el número de parámetros a procesar y en estos casos se debe establecer el mecanismo para determinar cuando se ha procesado el último de los argumentos, en el segundo tipo de declaración el número total de parámetros a procesar es igual al valor del parámetro num.
En el siguiente programa, por ejemplo, se define una función ( printstr ) que despliega una lista variable de cadenas de caracteres.
#include <iostream.h>
#include <stdarg.h>
 
// despliega una lista de cadenas, la ultima debe ser NULL
void printstr(...)
{
   va_list ap;
   char    *arg;
   va_start(ap, 0);
   while ( (arg = va_arg(ap, char*) ) != NULL) {
      cout << arg;
   }
   va_end(ap);
}
 
int main()
{
    printstr("Hola, ", "Esta es\n", "una prueba\n", NULL);
    cin.get();
    return 0;
}
En el programa que se listará en seguida, se define la función suma(), misma que operará sobre listas de números enteros, la función devolverá la suma de dichos números.
#include <iostream>//entrada y salida
#include <stdarg.h>
 
using namespace std;
 
// Esta función opera sobre una lista variable de números enteros
int suma( int num, ... )
{
    int total = 0;
    va_list argptr;
    va_start( argptr, num );
 
    while( num > 0 ) {
    total += va_arg( argptr, int );
    num--;
    }
 
    va_end( argptr );
    return( total );
}
 
int main()
{
    cout << suma(4, 100, 200, 300, 400) << endl;
    cin.get();
    return 0;
}