sábado, 21 de junio de 2014

EVP 5

VECTORES

Eprogramación, una matriz o vector (llamado en inglés array) es una zona de almacenamiento continuo, que contiene una serie de elementos del mismo tipo, los elementos de la matriz. Desde el punto de vista lógico una matriz se puede ver como un conjunto de elementos ordenados en fila (o filas y columnas si tuviera dos dimensiones).
En principio, se puede considerar que todas las matrices son de una dimensión, la dimensión principal, pero los elementos de dicha fila pueden ser a su vez matrices (un proceso que puede ser recursivo), lo que nos permite hablar de la existencia de matrices multidimensionales, aunque las más fáciles de imaginar son los de una, dos y tres dimensiones.
Estas estructuras de datos son adecuadas para situaciones en las que el acceso a los datos se realice de forma aleatoria e impredecible. Por el contrario, si los elementos pueden estar ordenados y se va a utilizar acceso secuencial sería más adecuado utilizar una lista, ya que esta estructura puede cambiar de tamaño fácilmente durante la ejecución de un programa.
  



Vectores dinámicos y estáticos


Lo habitual es que un vector tenga una cantidad fija de memoria asignada, aunque dependiendo del tipo de vector y del lenguaje de programación un vector podría tener una cantidad variable de datos. En este caso, se les denomina vectores dinámicos, en oposición, a los vectores con una cantidad fija de memoria asignada se los denomina vectores estáticos.
El uso de vectores dinámicos requiere realizar una apropiada gestión de memoria dinámica. Un uso incorrecto de los vectores dinámicos, o mejor dicho, una mala gestión de la memoria dinámica, puede conducir a una fuga de memoria. Al utilizar vectores dinámicos siempre habrá que liberar la memoria utilizada cuando ésta ya no se vaya a seguir utilizando.
Lenguajes más modernos y de más alto nivel, cuentan con un mecanismo denominado recolector de basura (como es el caso de Java) que permiten que el programa decida si debe liberar el espacio basándose en si se va a utilizar en el futuro o no un determinado objeto.

Ejemplos :

  • Declaración en C/C++ de un vector estático.
int main(void)
{
  int i, v[5];  // v[5] es un vector de 5 componentes
 
  for(i=0; i<5; i++)
  {
    v[i] = 0; // Asignamos un valor
    printf("%d\n", v[i]);
    printf("\n");  // Crea una nueva línea
  }
  return 0
}
  • Declaración en C/C++ de un vector estático utilizando aritmética de punteros.
Siendo el identificador del vector, un puntero constante que contiene la dirección del comienzo del vector (vector[0], primer elemento)
int main(void)
{
  int i, v[5];  // v[5] es un vector de 5 componentes
 
  for(i=0; i<5; i++)
  {
    *(v + i) = 0; // Asignamos un valor en la dirección (vector + ((índice * sizeof (int) cantidad de bytes de desplazamiento desde la base.)
    printf("%d\n", *(vector + i));
    printf("\n");  // Crea una nueva línea
  }
  return 0
}
  • Declaración en C++ de un vector de STL:
#include <vector>
 
vector<int> v; // Si no se especifica el tamaño inicial es 0
 
for(int i=0 ;i<5 ;i++)
{
  v.push_back(2*i); // inserta un elemento al final del vector
}
El ejemplo anterior está hecho para el lenguaje C++. En C, para crear vectores dinámicos se tendrían que utilizar las instrucciones malloc y realloc para reservar memoria de forma dinámica (ver biblioteca stdlib.h), y la función free para liberar la memoria utilizada.
Resultado:
01234
02468
El resultado de los dos ejemplos es el mismo vector.

Vectores multidimensionales

En BasicJava y otros lenguajes es posible declarar matrices multidimensionales, entendiéndolas como un vector de x dimensión. En dichos casos en número de elementos del vector es el producto resultante de cada dimensión.
Por ejemplo el vector v(4,1) tiene 10 elementos se calcula del siguiente modo: (0-4) * (0-1). Los elementos de la primera dimensión del vector contiene 5 elementos que van del '0' al '4' y la 2º dimensión tiene 2 elementos que van desde '0' a '1'. Los elementos serían accedidos del siguiente modo:
elemento 1: (0,0)
elemento 2: (0,1)
elemento 3: (1,0)
...
elemento 8: (3,1)
elemento 9: (4,0)
elemento 10: (4,1)



Evp4


FUNCIONES


Las funciones son un conjunto de instrucciones que realizan una tarea específica. En general toman ciertos valores de entrada, llamados parámetros y proporcionan un valor de salida o valor de retorno; aunque en C++, tanto unos como el otro son opcionales, y pueden no existir.


Tal vez parezca un poco precipitado introducir este concepto tan pronto en el curso. Sin embargo, las funciones son una herramienta muy valiosa, y como se usan en todos los programas C++, creo que debemos tener, al menos, una primera noción de su uso. A fin de cuentas, todos los programas C++ contienen, como mínimo, una función.
PROTOTIPO DE FUNCIONES

En C++ es obligatorio usar prototipos. Un prototipo es una declaración de una función. Consiste en una presentación de la función, exactamente con la misma estructura que la definición, pero sin cuerpo y terminada con un ";". La estructura de un prototipo es:
[extern|static] <tipo_valor_retorno> [<modificadores>] <identificador>(<lista_parámetros>); 
En general, el prototipo de una función se compone de las siguientes secciones:
  • Opcionalmente, una palabra que especifique el tipo de almacenamiento, puede ser extern o static. Si no se especifica ninguna, por defecto seráextern. No te preocupes de esto todavía, de momento sólo usaremos funciones externas, lo menciono porque es parte de la declaración.
  • El tipo del valor de retorno, que puede ser void, si no necesitamos valor de retorno. En C, si no se establece, será int por defecto, aunque en general se considera una mala técnica de programación omitir el tipo de valor de retorno de una función. En C++ es obligatorio indicar el tipo del valor de retorno.
  • Modificadores opcionales. Tienen un uso muy específico, de momento no entraremos en este particular, lo veremos en capítulos posteriores.
  • El identificador de la función. Es costumbre, muy útil y muy recomendable, poner nombres que indiquen, lo más claramente posible, qué es lo que hace la función, y que permitan interpretar qué hace el programa con sólo leerlos. Cuando se precisen varias palabras para conseguir este efecto se puede usar alguna de las reglas más usuales. Una consiste en separar cada palabra con un "_". Otra, que yo prefiero, consiste en escribir la primera letra de cada palabra en mayúscula y el resto en minúsculas. Por ejemplo, si hacemos una función que busque el número de teléfono de una persona en una base de datos, podríamos llamarla "busca_telefono" o "BuscaTelefono".
  • Una lista de declaraciones de parámetros entre paréntesis. Los parámetros de una función son los valores de entrada (y en ocasiones también de salida). Para la función se comportan exactamente igual que variables, y de hecho cada parámetro se declara igual que una variable. Una lista de parámetros es un conjunto de declaraciones de parámetros separados con comas. Puede tratarse de una lista vacía. En C es preferible usar la forma "func(void)" para listas de parámetros vacías. En C++ este procedimiento se considera obsoleto, se usa simplemente "func()".

FUNCIONES: PARÁMETROS POR VALOR Y POR REFERENCIA


PARÁMETROS POR VALOR

Dediquemos algo más de tiempo a las funciones.
Hasta ahora siempre hemos declarado los parámetros de nuestras funciones del mismo modo. Sin embargo, éste no es el único modo que existe para pasar parámetros.
La forma en que hemos declarado y pasado los parámetros de las funciones hasta ahora es la que normalmente se conoce como "por valor". Esto quiere decir que cuando el control pasa a la función, los valores de los parámetros en la llamada se copian a "objetos" locales de la función, estos "objetos" son de hecho los propios parámetros.
Lo veremos mucho mejor con un ejemplo:

#include <iostream> 
using namespace std;
 
int funcion(int n, int m);
 
int main() { 
   int a, b; 
   a = 10; 
   b = 20;
 
   cout << "a,b ->" << a << ", " << b << endl; 
   cout << "funcion(a,b) ->" 
        << funcion(a, b) << endl;
   cout << "a,b ->" << a << ", " << b << endl; 
   cout << "funcion(10,20) ->" 
        << funcion(10, 20) << endl; 

   return 0; 
}
 
int funcion(int n, int m) { 
   n = n + 2; 
   m = m - 5; 
   return n+m; 
}

Bien, ¿qué es lo que pasa en este ejemplo?
Empezamos haciendo a = 10 y b = 20, después llamamos a la función "funcion" con las objetos a y b como parámetros. Dentro de "funcion" esos parámetros se llaman n y m, y sus valores son modificados. Sin embargo al retornar a main, a y b conservan sus valores originales. ¿Por qué?
La respuesta es que lo que pasamos no son los objetos a y b, sino que copiamos sus valores a los objetos n y m.
Piensa, por ejemplo, en lo que pasa cuando llamamos a la función con parámetros constantes, es lo que pasa en la segunda llamada a "funcion". Los valores de los parámetros no pueden cambiar al retornar de "funcion", ya que esos valores son constantes.
Si los parámetros por valor no funcionasen así, no sería posible llamar a una función con valores constantes o literales.

PARÁMETROS POR REFERENCIA

Si queremos que los cambios realizados en los parámetros dentro de la función se conserven al retornar de la llamada, deberemos pasarlos por referencia. Esto se hace declarando los parámetros de la función como referencias a objetos. Por ejemplo:

#include <iostream>
using namespace std;
 
int funcion(int &n, int &m);
 
int main() { 
   int a, b;
 
   a = 10; b = 20; 
   cout << "a,b ->" << a << ", " << b << endl;
   cout << "funcion(a,b) ->" << funcion(a, b) << endl; 
   cout << "a,b ->" << a << ", " << b << endl; 
   /* cout << "funcion(10,20) ->" 
           << funcion(10, 20) << endl; // (1)
   es ilegal pasar constantes como parámetros cuando 
   estos son referencias */ 
   
   return 0; 
}
 
int funcion(int &n, int &m) {
   n = n + 2; 
   m = m - 5; 
   return n+m; 
}

En este caso, los objetos "a" y "b" tendrán valores distintos después de llamar a la función. Cualquier cambio de valor que realicemos en los parámetros dentro de la función, se hará también en los objetos referenciadas.
Esto quiere decir que no podremos llamar a la función con parámetros constantes, como se indica en (1), ya que aunque es posible definir referencias a constantes, en este ejemplo, la función tiene como parámetros referencias a objetos variables.
Y si bien es posible hacer un casting implícito de un objeto variable a uno constante, no es posible hacerlo en el sentido inverso. Un objeto constante no puede tratarse como objeto variable.

ALGORITMOS DE FUNCIONES CON PARÁMETROS 

1.INICIO

-(X,Y,Z) enteros
-a,b,c enteros

2,ASIGNACIÓN

 leo (x,y,z)

ingrese  3 notas
x,y,z
ingrese función
 a,b,c

3. PROCESO

x+y+z/3

promedio a,b,c

RETORNAR

                                      DIAGRAMA DE FLUJO FUNCIONES

       DIAGRAMA DE FLUJO FUNCIONES REFERENCIA