sábado, 30 de noviembre de 2013

Representación de un puntero en memoria

La representación de la memoria para una variable de tipo int se puede entender de forma muy simple, en tiempo de ejecución cuando las variable se crean se les asigna un espacio físico en memoria, así cuando vemos:

//se define la variable a de tipo int
int a;

La variable a tiene reservado un espacio para almacenar su contenido (el valor de la variable) y se sabe que ese contenido tiene que ser de tipo int porque así ha sido definida.

Sin embargo, cuando utilizamos variables de tipo punteros la comprensión de la asignación de la memoria es un poco más complicada, una variable de tipo puntero tiene en su definición "al menos un *", aquí unos ejemplos:

int * b;
int **c;

Cuando se reserva memoria para un puntero, se separa un espacio de memoria pero el contenido debe tener el formato de una dirección de memoria. si tomamos como ejemplo:

int * b;

El primer paso es identificar el nombre de la variable y el tipo de la variable:

nombre de variable: b
tipo de la variable: int *

como el tipo de la variable contiene "al menos un *" entonces el contenido (el valor) tiene el formato de una dirección, esa dirección debe apuntar al tipo de variable al cual apunta.

Para saber el tipo de variable al cual apunta, seguimos el segundo paso, que consiste en leer la misma definición de la variable pero ahora el * pasa a ser parte del nombre de la variable:

nombre de variable: *b
tipo de la variable: int

Ahora vemos que la dirección a la que apunta el contenido de b (el valor de b) apunta a una dirección de memoria cuyo nombre se puede interpretar como *b y cuyo tipo es int.

Para verlo de una forma más práctica representaremos las siguientes líneas de código:

int a = 5:
//reserva memoria para el puntero, esta asignación varía según el lenguaje de programación
int* b = new int(); 
     *b = 3;

En una tabla:

Podemos ver que para la variable b el contenido es la dirección 0003, y en la dirección 3 se encuentra la variable *b de tipo int en la que se guarda el contenido 3.

Podríamos aprovechar el espacio de memoria de a para guardar el contenido de b:

int a = 5;
int* b;
     *b = a; //*b y a son del mismo tipo por eso se puede realizar la instrucción de asignación.

La representación en la tabla de memoria sería:


Podemos ver que en este caso: a y *b están en la misma dirección de memoria.





sábado, 19 de octubre de 2013

Estructuras (Struct)

Cuando programamos hacemos uso de tipos básicos de datos, como enteros, decimales, caracteres, cadenas de caracteres, fechas. Pongo un ejemplo simple:

    //definición de nombre y edad de la persona
    char *nombre;
    int edad;
    //instanciación del nombre y la edad de la persona
    nombre = "Juan";
    edad = 21;

digamos que ahora queremos trabajar con la información de 2 personas:

    //definición de nombre y edad de las personas
    char *nombre1;
    int edad1;
    char *nombre2;
    int edad2;
    //instanciación del nombre y la edad de las personas
    nombre1 = "Juan";
    edad1 = 21;
    nombre2 = "Pedro";
    edad2 = 25;

¿Qué pasaría si queremos trabajar con 100 personas? ¿Crearíamos 100 variables para el nombre y 100 variables para la edad?

Lo primero que se nos ocurre es que si son muchos elementos iguales podemos utilizar un Array, pero los elementos de un Array deben ser todos del mismo tipo por ejemplo char * para guardar un array de nombres o int para guardar un Array de edades. Así podríamos modificar nuestro programa para poder manejar la información de las 100 personas:

//instanciación de los Arrays de nombres y de edades
    char * nombres[100];
    int edades[100]; 

Con esto tendríamos resuelto el manejo de la información de 100 personas con nombre y edad, pero qué pasaría si ahora además del nombre y la edad queremos saber: el apellido, la fecha de nacimiento, el número de identificación, el email, etc. ¿Tendríamos que crear un Array para cada dato?

La solución para esto son las estructuras (se llaman también registros o tuplas), son agrupaciones de tipos de datos para crear un nuevo tipo de dato definido por el programador, así con un único tipo de dato crearíamos un solo Array.

Para el ejemplo nuestro nuevo tipo de dato sería Persona y lo definiríamos así:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//nombre y edad quedan dentro de la estructura Persona
typedef struct Persona {
   char * nombre;
   int edad;
   //si quisiéramos agregar más información a la persona la agregaríamos aquí y no modificaríamos la definición del Array
} Persona;


int main(int argc, char *argv[])
{
    //Definimos un Array de 100 elementos de tipo Persona
    //Persona es el tipo de variable
    //listaPersonas es el nombre de la variable
    Persona listaPersonas[100];
}

Las estructuras se utilizan normalmente en la programación estructurada y su concepto es similar al de las clases (programación orientada a objetos).

viernes, 13 de septiembre de 2013

Números primos

Empiezo un nuevo curso y revisando el material que debo tratar con una de mis alumnas de este semestre me encuentro con un problema clásico, un enunciado que se repite mucho ya que mezcla conceptos de estructuras de control (condicionales e iterativas) y aplica conceptos matemáticos, este post va de los números primos.

El problema busca determinar si un número es primo o no, por lo tanto, preparamos la información del problema:

¿Qué tengo?
Tengo un número entero positivo mayor que 1

¿Que quiero?
Determinar si dicho número es primo o no

¿Cómo lo hago?
Primero debemos tener claro lo que es un número primo, dejamos el enlace a wikipedia, en el que dice: un número primo es un número natural mayor que 1 que tiene únicamente dos divisores distintos: él mismo y el 1. 
Para que quede más claro:
5 es primo, porque sólo es divisible entre 1 y 5, no es divisible entre 2, ni 3 ni 4 y no consideramos evaluar si es divisible entre 6, 7 o más porque el divisor de un número debe ser siempre menor o igual a él.
6 no es primo, porque es divisible entre 2 y 3.

Generalizando, basta con encontrar un número entre 1 y N que sea divisor de N, para decir que N no es primo.

Analizamos, todo lo que hemos dicho hasta ahora:
1. Basta con encontrar un número: esto se traduce en una iteración con condicionante booleana que se detendrá cuando encuentre un divisor.
2. Entre 1 y N: esto se traduce como que la iteración tendrá el condicionante que el divisor buscado debe iterar entre 1 y N.

Planteamos el pseudocódigo:
//asumimos que tenemos una función con parámetro N que es un entero mayor a 1
//definimos la condicionante booleana
bool esPrimo = true; //asumimos que es primo a menos que encontremos un divisor
//definimos variable que itera entre 1 y N buscando un divisor
int iDivisor = 2;
//iteración
mientras(esPrimo AND iDivisor < N)
{
    //condicionante que puede hacer que esPrimo cambie: cuando encuentra un divisor
    SI (N % iDivisor == 0) //la operación % indica que calcula el residuo de la división de N entre iDivisor
    {
      esPrimo = false;
    }fin_SI
    iDivisor++; //incrementa el iDivisor para continuar la búsqueda
}fin_mientras
//puede salir de la iteración porque encontró un divisor, en ese caso esPrimo será falso
//puede salir de la iteración porque no encontró divisor, en ese caso iDivisor es igual a N
//condicionante
SI(esPrimo)
{
   imprime("Es Primo")
}
Caso contrario
{
  imprime("No es primo")
}

Este problema, como todos, se puede resolver de distintas formas, si revisáis el enlace de wikipedia por ejemplo, podréis ver que los números primos cumplen muchas propiedades que pueden aplicarse al programa para mejorar el rendimiento (por ejemplo reducir el número de iteraciones), sobretodo si se quieren evaluar números muy grandes.

miércoles, 7 de agosto de 2013

Vectores: Ordenamiento por Intercambio

En este post veremos paso a paso cómo ordenar un vector de números de 5 elementos de forma ascendente. Luego generalizaremos la solución a un vector de N elementos.

Planteamiento del Problema

¿Qué tengo?
Un vector de 5 números



¿Qué quiero?
Ordenar el vector de forma ascendente



¿Cómo lo hago?
- Tenemos 5 elementos, de los cuales iremos ordenando posición a posición (empezando por la posición 0)
- Una posición está ordenada cuando todos los elementos de las posiciones posteriores son mayores que el elemento de la posición que se está ordenando.
<imagen de posición i ordenada>
- Si ordenamos posición a posición, vemos que si ordenamos de la posición 0 a la 3, la cuarta quedará ordenada automáticamente (no hay posiciones posteriores con la cual compararla)

Siguiendo estas pautas, haremos el procedimiento para el vector de 5 elementos, razonando a cámara lenta:
(ver enlace)

Ahora que hemos visto poco a poco cómo sería la ejecución del algoritmo, planteamos el pseudocódigo para el vector de 5 elementos:

/***Método de Ordenamiento General***/
iPos = 0; //representa cada posición del vector
Para cada elemento del Vector hasta la posición 3
  OrdenarDesde(iPos); //Ordena el vector a partir de la posición iPos
Fin Para

/***Método OrdenarDesde***/
iPosCompara = iPos + 1; //esta variable es la que recorre las posiciones posteriores a iPos para comparar
elemento1 = Vector[iPos];
Mientras (iPosCompara <= 4)
   elemento2 = Vector[iPosCompara];
   //Se comparan: elemento1 y elemento2
   Si elemento1<= elemento2 //no tiene que cambiar de posición
      iPosCompara++
   Caso Contrario
      Intercambia(iPos, iPosCompara) //intercambia los elementos
      iPosCompara =  iPos + 1; //vuelve a empezar el ordenamiento desde la posición iPos
      elemento1 = Vector[iPos];
   Fin Si
Fin Mientras

/***Método Intercambia***/
aux = Vector[iPos]; //guarda temporalmente el valor de la posición iPos
Vector[iPos] = Vector[iPosCompara];
Vector[iPosCompara] = aux; //utiliza el valor guardado en aux para el intercambio

Para terminar, os dejo el mismo código como un proyecto de consola en c# generalizado para vectores de N elementos.
- Programa Principal
- Clase con Algortimo de Ordenamiento

martes, 4 de junio de 2013

Sumatorio de valores de un vector


En esta ocasión, trabajaremos con un ejemplo práctico para explicar cómo hacer la sumatoria de valores de un vector.
En este ejemplo tenemos una factura de este estilo:

Descripción Precio unitario Cantidad Total
Boligrafo 1,50 2 3,00
Papel A4 (pack. 100) 4,75 1 4,75
Total 7,75

Si tenemos una clase que representa cada linea del detalle de la factura, seria de este estilo:

Class Detalle{
  private String descripción;
  private float precioUnitario;
  private int cantidad;
  private float totalLinea;

  //y los respectivos métodos gets y sets para cada atributo
}

Por otra parte tenemos una clase que representa la factura y que tiene varias lineas en el detalle (array de Detalle)

Class Factura{
  private Detalle[100] lineas; //como máximo tiene 100 líneas de detalle
  private int numLineas; //esta variable indica el número de líneas que tiene la factura, siempre <= 100
  private float totalFactura; //esta variable contendrá el total de la factura
}

Desde nuestro programa principal suponemos que la se han cargado los datos de la factura, por tanto tendríamos:

Factura miFactura = new Factura(); //instanciamos el objeto miFactura de tipo Factura
//...
//aquí rellenamos la información en cada linea de detalle
//...
//ahora calculamos el total de la factura
//recorremos todas las lineas de la factura
int numLineasFactura = miFactura.getNumLineas();
float totalCalculoFactura = 0; //inicializamos a 0
for(int i = 0; i < numLineasFactura; i++)
{
   totalCalculoFactura += miFactura.getDetalle()[i].getTotalLinea();
}
//al terminar el for, la variable totalCalculoFactura contiene el total
//guardamos el total en la factura
miFactura.setTotalFactura(totalCalculoFactura);

La clave de este ejemplo está en dos líneas:
1. Sumar el total de cada linea:
    totalCalculoFactura += miFactura.getDetalle()[i].getTotalLinea();

En cada iteración se va incrementando la variable totalCalculoFactura con el valor del total de cada linea. Para acceder al total de cada linea se hace a través de método getDetalle() que retorna el vector de Detalles de la factura, utilizamos el índice i para posicionarnos linea a linea en cada iteración y estando en la linea accedemos al total de la linea mediante el método getTotalLinea().

2. Inicialización de la variable acumuladora:
    float totalCalculoFactura = 0;

La variable totalCalculoFactura es la que va acumulando el total de la suma de cada linea, es muy importante que esté inicializada a 0, debido a que no todos los lenguajes de programación inicializan a 0 cuando se define la variable, es decir, si sólo la definimos y no la inicializamos nada nos garantiza que esa variable contenga el valor 0.

Finalmente, hacemos una variación al problema y suponemos que las lineas de la factura contienen la descripción, el precio unitario, la cantidad pero no tienen calculado el total por linea, en ese caso se podría modificar el programa para realice el cálculo del total en cada línea y a la vez el total de la factura:

int numLineasFactura = miFactura.getNumLineas();
float totalCalculoFactura = 0; //inicializamos a 0
float precioUnitarioLinea;
int cantidadLinea;
for(int i = 0; i < numLineasFactura; i++)
{
   //obtiene el precio unitario y la cantidad por linea
   precioUnitarioLinea = miFactura.getDetalle()[i].getPrecioUnitario();
   cantidadLinea = miFactura.getDetalle()[i].getCantidad();
   //calcula el total de linea y lo guarda en la linea
   miFactura.getDetalle()[i].setTotalLinea(precioUnitarioLinea  * cantidadLinea );
 
   //como el total de linea ya está calculado y guardado se puede utilizar para calcular el total de la factura
   totalCalculoFactura += miFactura.getDetalle()[i].getTotalLinea();
}
//al terminar el for, la variable totalCalculoFactura contiene el total
//guardamos el total en la factura
miFactura.setTotalFactura(totalCalculoFactura);


viernes, 17 de mayo de 2013

Búsqueda del valor máximo

Uno de los problemas académicos más comunes es el de la búsqueda del valor máximo o mínimo dentro de una lista. Una aplicación que podríamos darle a este problema sería por ejemplo con fines estadísticos, calcular para una muestra de datos: el máximo, el mínimo y el valor medio.

Antes de plantear el problema vamos a intentar "pensar en cámara lenta" y preguntarnos qué haría nuestra cabeza si tuviésemos que encontrar el valor máximo de una muestra de datos. Suponemos la siguiente muestra de datos:

2, 5, 10, 1, 7

A simple vista diríamos que el máximo es 10, pero ¿Cómo es que lo hemos determinado? si lo vemos en cámara lenta nos daríamos cuenta que:

1. Comparamos el 2 y el 5, como el 5 es mayor, nos quedamos con el 5 y descartamos el 2.
2. Comparamos el 5 con el 10, como el 10 es mayor, nos quedamos con el 10 y descartamos el 5.
3. Comparamos el 10 con el 1, como el 10 es mayor, nos quedamos con el 10 y descartamos el 1.
4. Comparamos el 10 con el 7, como el 10 es mayor, nos quedamos con el 10 y descartamos el 7.

Finalmente el último con el que nos quedamos fue el 10, por tanto, es el 10 el valor máximo.

Si analizamos cada uno de los pasos, vemos que en cada uno de ellos se compara un elemento de la lista con el valor con el que nos hemos quedado en el paso anterior. Si llevamos esto a lenguaje de programación  se puede plantear como un recorrido por todos los elementos de una lista en la que cada iteración realza una comparación entre el valor actual con el máximo de la iteración anterior, por tanto sabemos que debemos tener una estructura así:

//creamos la muestra de datos
int listaNumeros [5]; 
listaNumeros[0] = 2;
listaNumeros[1] = 5;
listaNumeros[2] = 10;
listaNumeros[3] = 1;
listaNumeros[4] = 7;

//tenemos un recorrido de la muestra
for(int i=0; i<5;i++)
{
  //comparamos el valor actual con el resultado de la iteración anterior
  if (listaNumeros[i] > valor_maximo)
  {
    //esta linea representa el "nos quedamos con" de cada paso
    valor_maximo = listaNumeros[i]; 
  }
}

Hasta aquí tenemos la estructura básica del algoritmo, ahora le hacemos algunos ajustes, teniendo en cuenta que la variable valor_maximo no la hemos inicializado.
Si la inicializaramos con 0, nos corremos el riesgo de que para otra muestra tengamos valores negativos y en ese caso el máximo siempre sería 0, lo mejor es tomar como máximo algún valor de la muestra, por ejemplo el primero.

//inicializamos el valor máximo con el primer elemento de la muestra
int valor_maximo = listaNumeros[0];

//tenemos un recorrido de la muestra
for(int i=0; i<5;i++)
{
  //comparamos el valor actual con el resultado de la iteración anterior
  if (listaNumeros[i] > valor_maximo)
  {
    //esta linea representa el "nos quedamos con" de cada paso
    valor_maximo = listaNumeros[i]; 
  }
}

Ahora que nos aseguramos que el valor_maximo de la muestra sea uno de los elementos de la muestra, vemos que la primera iteración comparará listaNumeros[0] y valor_maximo y que siempre serán iguales en la primera iteración, por tanto el código que está dentro del if núnca se ejecutará en la primera iteración, así que podemos aplicar una optimización haciendo que empiece la iteración a partir del segundo elemento, de la siguiente forma.


//inicializamos el valor máximo con el primer elemento de la muestra
int valor_maximo = listaNumeros[0];

//el recorrido se inicia en el segundo elemento
for(int i=1; i<5;i++)
{
  //comparamos el valor actual con el resultado de la iteración anterior
  if (listaNumeros[i] > valor_maximo)
  {
    //esta linea representa el "nos quedamos con" de cada paso
    valor_maximo = listaNumeros[i]; 
  }
}

Finalmente, aprovecharemos el mismo recorrido para calcular el máximo, el mínimo y la media:

//creamos la muestra de datos
int listaNumeros [5]; 
listaNumeros[0] = 2;
listaNumeros[1] = 5;
listaNumeros[2] = 10;
listaNumeros[3] = 1;
listaNumeros[4] = 7;

int valor_maximo = listaNumeros[0];
int valor_minimo = listaNumeros[0];
int media = listaNumeros[0];

for(int i=1; i<5;i++)
{
  //Búsqueda del máximo
  if (listaNumeros[i] > valor_maximo)
  {
    valor_maximo = listaNumeros[i];
  }

  
  //Búsqueda del mínimo
  if (listaNumeros[i] < valor_minimo)
  {
    valor_minimo = listaNumeros[i] ;
  }

  //cálculo de media
  media +=  listaNumeros[i] ;

}

//al terminar el recorrido la variable media contiene la suma de todos los elementos
//dividimos entre el número de elementos para calcular la media
media = media/5;

//En este punto tenemos calculado los tres valores estadísticos de la muestra, los imprimimos en pantalla
printf("valor_maximo: ", valor_maximo);
printf("valor_minimo: ", valor_minimo);
printf("media: ", media);



martes, 16 de abril de 2013

Búsqueda con recorrido secuencial

Uno de los problemas más frecuentes es el tratamiento de vectores (Array), para esto es necesario tener claros los siguientes conceptos:

- El vector es una lista de elementos, donde todos los elementos son del mismo tipo.

- El vector tiene un número de elementos fijos, cuando se crea, se reserva memoria para todos esos elementos. Por ejemplo, definimos un vector de 15 elementos de tipo unsigned char (1 byte), entonces estaremos reservando 15 bytes en la memoria.

- Es muy importante tener clara la diferencia entre posición y valor. Si el vector tiene N elementos, entonces tendremos posiciones que variarán entre 0 y N-1, y los valores en cada posición dependerán del tipo de elementos del vector.

Para el vector:

int listaNumeros [5]; //vector de 5 elementos de tipo int

Se ha reservado memoria para 5 variables de tipo int, para acceder a los valores de esas variables lo hacemos de la siguiente forma:

listaNumeros[0] = 2; //el valor en la posición 0 es 2

listaNumeros[1] = 5; //el valor en la posición 0 es 5
listaNumeros[2] = 4; //el valor en la posición 0 es 4
listaNumeros[3] = 3; //el valor en la posición 0 es 3
listaNumeros[4] = 1; //el valor en la posición 0 es 1

Se comete mucho el error de acceder a listaNumeros[5], esto dará un error de fuera de rango del vector, porque las posiciones varían entre 0 y 4, por tanto:

listaNumeros[5] = 3; //ERROR!!! no se puede realizar esta asignación porque se encuentra fuera de rango

Para buscar un elemento en un vector que cumpla ciertas características, debemos recorrer uno a uno cada elemento y determinar si el valor en cada posición cumple con las características que estamos buscando. Este recorrido uno a uno de los elementos se le denomina recorrido secuencial.

Por ejemplo, si queremos imprimir por pantalla los números del vector listaNumeros que son pares, haremos:

int N = 5;
for(int i=0; i<N; i++)
{
    //listaNumeros[i] contiene el valor en la posición i
    if(listaNumeros[i] % 2 == 0) //verifica si el valor es par, en ese caso imprime
       printf(listaNumeros[i]);
}

la variable i nos ayuda a recorrer las posiciones del vector (i varía desde 0 hasta N-1).
la variable N representa el número de elementos del vector, notar que las iteraciones del for sólo se ejecutan si i<N
La característica que buscamos es que el valor sea par, para eso utilizamos la operación % que calcula el resto de dividir listaNumeros[i] entre 2, en el caso que sea par ese resto es 0 y en ese caso imprimimos.

Si modificamos el problema y ahora sólo nos interesa mostrar el primer valor par, ¿Qué modificación tendríamos que hacer a programa anterior?

Ahora la característica no es sólo que sea par sino que además sea el primero, por tanto introducimos una variable booleana que nos indique si es el primero en encontrarse o no.

int N = 5;
boolean bPrimerPar = false
for(int i=0; i<N && !bPrimerPar; i++)
{
    //listaNumeros[i] contiene el valor en la posición i
    if(listaNumeros[i] % 2 == 0) //verifica si el valor es par, en ese caso imprime
    {   printf(listaNumeros[i]);
         bPrimerPar = true;
    }
}

Cuando se encuentra el primer valor par, la variable se vuelve true y la validación !bPrimerPar se hace falsa por tanto termina de ejecutar el bucle.

Hemos visto que se pueden realizar búsquedas en las que es necesario recorrer todos los elementos del vector y otras en las que sólo lo recorreremos hasta que encontremos el valor que estamos buscando.




domingo, 24 de marzo de 2013

Lo que no debemos olvidar en una iteración

Este post intenta dar las 3 claves principales que no debemos olvidar nunca al realizar iteraciones:

1. Definir e inicializar la variable que itera: Esta variable será la que determine en qué iteración nos encontramos y servirá para terminar la iteración.

2. La condición tope para que termine la iteración: Esta condición evalúa la variable itera y determina si debe continuar iterando o no.

3. La variación de la variable que itera: Esta variación se debe realizar en cada iteración para asegurar que la variable en algún momento cumplirá la condición tope.

Un ejemplo sencillo: Sumar los 10 primeros números enteros positivos:

//variable que acumula la suma
int Suma = 0;
//variable que itera: se inicializa con el primer entero positivo
int i = 1;

//la condición es que la variable iteradora no supere 10, así asegura que se suman los 10 primeros números
while (i <= 10)
{
    suma += i;
    //variación de la variable i, se incrementa en 1
    i++;
}

//cuando salimos del while la variable i vale 11 y la variable suma contiene la suma desde 1 hasta 10

Ahora haremos un ejemplo un poco más complejo, haremos una función que calcule la integral entre 0 y 1 de la función f(x) = x^2

El método que utilizaremos será discretizar la función en incrementos de h = 0.001

float inicio = 0;
float final = 1;
float h = 0.001; //variaciones 
float integral = 0; //en esta variable se guarda el valor calculado de la integral
int it = 0; //esta variable guarda el número de iteraciones que se realicen

float i = inicio; //variable que itera y que se evalúa en la condición tope
//la condición que marca el tope es que no sobrepase el final = 1
while (i <= final)
{
    integral += i * i ; //la evaluación de la función f(x)=x^2 en el punto i es f(i) = i^2 = i*i
    i += h; //incremento de la variable iteradora
    it++;
}
//cuando termina el bucle la variable i contiene un número > a final
//la variable integral contiene la suma de la evaluación de la función en todos los puntos i
//la variable it contiene el número total de iteraciones que se realizaron, que es igual al número de veces que //se evaluó f(i)

//para terminar de calcular la integral se divide entre el número de iteraciones
integral = integral / it;






martes, 5 de marzo de 2013

Las variables booleanas

Nos referimos a variables booleanas a aquellas que utilizamos para indicar que algo es verdadero o falso.

Lo importante de estas variables es que sólo pueden tomar dos valores: verdadero o falso, no hay más posibilidades y esta propiedad la utilizaremos para tomar decisiones, por ejemplo: tengo una variable que se llama bTarifaMenor y que es verdadera si tengo una variable edad de tipo entero <= 12 y en caso contrario será falsa. Podríamos decir que si la variable bTarifa Menor es verdadera aplicaremos un descuento del 20% en el precio de un producto.

La definición de estas variables dependerá del lenguaje de programación que estemos utilizando. No podemos encontrar con los tipos: booblean, bool, Boolean, Bool. En cuanto tengamos claro cual de los tipos es el que utiliza el lenguaje con el que estamos programando definiremos la variable:

Para c# definiríamos así:
bool bTarifaMenor; //definimos la variable booleana
bTarifaMenor = False; //inicializamos la variable con valor falso

int edadCliente = 13; //definimos e inicializamos la variable edad en 13

Para aplicar la lógica de decisión que evalúa el valor de la variable edadCliente utilizamos la instrucción if que sigue la siguiente sintaxis:

if (condición que se evalúa)
{
  //Entre estas llaves va el conjunto de instrucciones que se ejecutan si se cumple
  //la condición que se evalúa
}

aplicando la instrucción de evaluación if en el ejemplo:

//la condición de evaluación es que la edad del cliente sea menor o igual que 12
//dejamos la referencia de los operadores disponibles que iremos aplicando en los ejemplos
if (edadCliente <= 12)
{
  bTarifaMenor = True; //asignamos el valor de verdadero a la variable booleana
}

Las llaves “{“ y “}” contienen un conjunto de instrucciones que sólo se ejecutarán si se cumple la condición que se evalúa dentro del paréntesis, si ese conjunto de instrucciones consta de una sola instrucción como es el caso del ejemplo, se pueden obviar las llaves:

if (edadCliente <= 12)
  bTarifaMenor = True; //asignamos el valor de verdadero a la variable booleana

Sin embargo, si Ud. está empezando a programar le recomiendo que utilice siempre las llaves,  así podrá distinguir claramente cuáles son las instrucciones que se ejecutarán en el caso que se cumpla la condición del if.


Para terminar el ejemplo, aplicaremos el descuento a los menores utilizando como condicional a la variable booleana:

if (bTarifaMenor)
{
 //aquí hace las instrucciones necesarias para aplicar el 20% de descuento en el precio
}

En el caso de este if la condición que se evalúa es simplemente una variable booleana, por que en sí esta variable es True o False, en el caso que su valor sea True se ejecutará el bloque de instrucciones que se encuentra entre las llaves (descuento en el precio).


Aquí más información sobre la instrucción if

domingo, 10 de febrero de 2013

Instrucción de Asignación


Ahora que tenemos claro lo que es una variable veremos cómo almacenar información en ellas, para esto utilizamos la instrucción de asignación.

La instrucción de asignación se encarga de guardar un valor en una variable, para esto es importante tener en cuenta que el valor que se guarde debe ser del mismo tipo que se ha definido a la variable, es decir, si defino una variable de tipo entero no podré asignarle un decimal.

La instrucción de asignación tiene la siguiente sintaxis:

nombre variable receptora = valor que se le asigna;

Siempre la variable que recibe el valor va del lado izquierdo al “=”.

Cuando nos referimos a valor que se le asigna puede ser representado de varias formas, que describiremos a continuación:

Asignación de un valor fijo
Se asigna directamente un valor, por ejemplo:
edad = 18;
nombre = “juan”;
precio = 3.5;

Asignación del valor de una variable
Se asigna el valor que contiene otra variable
int edad, edad2; //definimos 2 variables de tipo entero
edad = 18; //inicializamos la variable edad con un valor fijo
edad2 = edad; //inicializamos la variable edad2 con el valor de la variable edad, es decir con 18

Asignación del valor del resultado de una operación
Se asigna el valor del resultado de una operación

Ejemplo con una variable de tipo entero
int edad, edad2; //definimos 2 variables de tipo entero
edad = 18 + 2; //inicializamos la variable edad con el valor resultante de la suma, edad = 20
edad2 = edad - 2; //inicializamos la variable edad2 con el valor de la operación resultante de la resta, edad2 = 18

Ejemplo con una variable de tipo cadena de caracteres
String cadena, cadena2; //definimos 2 variables de tipo cadena de caracteres
cadena = “Juan”;//se incializa con el valor fijo “juan”
cadena2 = cadena + “ “ + “Pérez”; //se inicializa con e valor resultante de la concatencación con “ “ y “Pérez”, queda como resultante “Juan Pérez”

Asignación del valor del resultado de una función
Se asigna el valor del resultado de una función, para esto es necesario que el tipo de dato que retorna la función sea del mismo tipo que el de la variable.

float area, lado; //definimos 2 variable de tipo decimal
lado = 3.5; //inicializamos el la variable lado con la longitud del lado de un cuadrado
area = calcularAreaCuadrado(lado); //invocamos a la función calcularAreaCuadrado que retorna una variable de tipo decimal con el resultado del cálculo del aréa de un cuadrado cuyo lado tiene el valor almacenado en la variable lado


lunes, 28 de enero de 2013

Variables

Las variables son elementos imprescindibles en la programación, son las encargadas de almacenar la información que se va calculando en un programa en tiempo de ejecución.

Las variables se definen con un tipo específico según la información que se quiera almacenar, por ejemplo si se quiere almacenar un precio definiremos una variable de tipo decimal (float, double, etc), si se quiere almacenar una edad definiremos una variable de tipo entero (int), si se quiere almacenar un nombre definiremos una variable de tipo cadena de caracteres (string, char[], char*).


Cuando se define una variable se reserva el espacio de memoria que la variable necesita según su tipo, sólo reserva el espacio pero no se coloca ningún valor en ella. 


Para definir una variable es necesario:

- Tener claro el tipo de información que se quiere almacenar en la variable para escoger el tipo.
- Escoger un nombre de variable, se recomienda que el nombre describa la información que se almacenará.

Ejemplos de definición de variables


//int: tipo de datos entero porque almacenará la cantidad de alumnos

//numAlumnos: nombre de la variable, que representa el número de alumnos
int numAlumnos; 

//float: tipo de datos decimal porque almacenará un precio

//precio: nombre de variable que representa el precio de un producto
float precio;

Hasta aquí hemos visto qué es una variable, cómo se define y que debemos tener en cuenta para definir una variable. 
En la próxima entrada veremos cómo asignar valores a las variables.

jueves, 10 de enero de 2013

¿Por dónde empiezo?

Antes de empezar a programar se debe "Plantear el problema"


Para plantear el problema debemos preguntar 3 cosas (en este orden):
1. ¿Qué quiero conseguir?
2. ¿Qué tengo para conseguirlo?
3. ¿Cómo lo hago?

Nuestro problema es una caja que recibe información, la procesa y retorna un resultado.



Ejemplo. Hacer un programa que calcule el área de un cuadrado

1. ¿Qué quiero conseguir? El área de un cuadrado (en m2)
2. ¿Qué tengo para conseguirlo? La medida del lado de un cuadrado (en m)
3. ¿Cómo lo hago? Utilizo la fórmula de cálculo de área: área = lado al cuadrado



L es una variable, que puede tomar muchos valores, pero sea el valor que sea, la caja devolverá el área A calculada en función al lado L.

Implementación del ejemplo




f: función que calcula el área a la que llamaremos calcular_area.
L: parámetro de entrada de la función, contiene un valor numérico (puede tener decimales).
A: variable de salida, contiene un valor numérico (puede tener decimales).

En C, la estructura de definición de una función es la siguiente:

//¿Qué tengo? nombre_parametro1
tipo nombre_función ( tipo nombre_parametro1, ... )
{
      tipo nombre_variable_retorno;
      //¿Cómo lo hago?
      //aquí se hacen los cálculos

      //¿Qué quiero?
      return nombre_variable_retorno;
}

para el problema del ejemplo sería:

//¿Qué tengo? L
float calcular_area ( float L )
{
     float A;
     //¿Como lo hago?
     A = L * L;


     //¿Qué quiero?
     return A;

Presentación

Hola a todos,
Después de tres años dando clases particulares de programación, he decidido empezar este Blog que contendrá los problemas más típicos con los que se encuentran los alumnos, que en sí no son de sintaxis (que eso ya lo resuelve el compilador) sino de algoritmia.
Espero que les sea de ayuda...