jueves, 8 de diciembre de 2016

Capítulo 87: Aritmética de punteros en C


Diario de un programador. Día 189


Operaciones de aritmética con punteros en C.


Siguiendo con el tema de los punteros en C, debemos mencionar que se pueden realizar ciertas operaciones aritméticas con los punteros, por ejemplo. Se pueden sumar o restar, debido a esto, se está permitido utilizar los incrementos ++ o decrementos --
Cabe hacer presente que estas operaciones solamente son válidas y tienen sentido cuando se trabajan con arreglos. Vamos a mostrar algunos ejemplos para entender el por qué.
Supongamos que declaramos el siguiente arreglo:

int arreglo[10];

También vamos a suponer, por cuestiones de hacerlo simple, que su primer elemento, o sea arreglo[0], está en la posición de memoria 1000000.
Entonces, crearemos un puntero que apunte a la primera posición del arreglo. Esto lo lograríamos de la siguiente manera:

*pArreglo = &arreglo[0];

Entonces, al tratar de hacer esto...

pArreglo++;

Es lo mismo que estuviera haciendo pArreglo + 1 o en el caso de sumar en la memoria, estaría sumando 1000000 + 1 (suponiendo como dijimos, que la posición estuviese en 1000000).
En aritmética convencional, esto daría como resultado 1000001, pero no es el caso de los punteros. En la aritmética de los punteros, lo que se suma (o resta según el caso) es el tamaño del tipo de dato. Por lo general los enteros tienen un valor de 4 bytes (en algunas máquinas valen 2 mientras que en otras valen 8). Por lo tanto el resultado de esto sería 1000004, y si sumamos pArreglo +2 daría como resultado 1000008, si sumamos +3 daría 1000012 y así sucesivamente. Entonces esto sería algo así:

1000000 + 1 = 1000000 + (1 * 4) = 1000004
1000000 + 2 = 1000000 + (2 * 4) = 1000008
1000000 + 3 = 1000000 + (3 * 4) = 1000012


Con un dibujo quizás quede un poco más claro


Veamos un ejemplo con un código. Voy a crear un arreglo de 5 elementos, luego los voy a rellenar usando un ciclo for y luego veré en qué posición de memoria quedaron alojados esos valores.
El código es el siguiente:

#include<stdio.h>

int main(void){

int arreglo[5];
int *pArreglo = &arreglo[0];
int i;

for (i = 0; i < 5; i++){
    //relleno el arreglo con valores
    arreglo[i] = i;
}
for (i = 0; i < 5; i++){
    //muestro la posición de los valores
    printf("%d\n", &arreglo[i]);
 }
return 0;
}

Al ejecutar este código estas son las posiciones de memoria que me muestra en mi caso:


La primera termina en 508, luego sigue 512 y así sucesivamente se va incrementando de 4 en 4, por lo que se deduce que en este caso, el valor del entero es de 4 bytes.

Ahora voy a modificar este programa, añadiendo un incremento al puntero pArreglo y luego mostraré el resultado. Esto es lo que me muestra el programa:


#include<stdio.h>

int main(void){

int arreglo[5];
int *pArreglo = &arreglo[0];
int i;

for (i = 0; i < 5; i++){
    arreglo[i] = i;
}
for (i = 0; i < 5; i++){
    pArreglo++;
    printf("%d  ", &arreglo[i]);
    printf("%d\n", &pArreglo[i]);
}
return 0;
}


La columna de la izquierda es el valor original, mientras que la columna de la derecha se ve el incremento que se realizó.
La primera posición se aumentó en 4 bytes, la segunda en 8 y así sucesivamente quedando de la siguiente manera:

1 -> 4
2 -> 8
3 -> 12
4 -> 16
5 -> 20

Como mencioné anteriormente, en algunos computadores los enteros son de 4 bytes, mientras que en otros son de 2 o de 8, pero ¿cómo podemos saber el valor de los tipos de datos en nuestro equipo? En casos como estos podemos utilizar el operador sizeof el cual nos sirve para obtener el tamaño de un tipo de datos. Este operador regresa un entero, el cual corresponde al número total del tamaño de bytes.
A continuación un ejemplo:

#include<stdio.h>

int main(void){
  printf("int = %d\n", sizeof(int));
  printf("short = %d\n", sizeof(short));
  printf("long = %d\n", sizeof(long));
  printf("char = %d\n", sizeof(char));
  printf("float = %d\n", sizeof(float));
  printf("double = %d\n", sizeof(double));
  printf("long double = %d\n", sizeof(long double));

return 0;
}

Al compilar y ejecutar este programa, estos son los valores que me muestra:


Dejaremos esto hasta aquí el día de hoy ya que aún hay mucho más que ver con esto de los punteros.
Saludos.


Gustavo J. Cerda Nilo
Diciembre 2016



domingo, 4 de diciembre de 2016

Capítulo 86: Elementos al azar en Java


Diario de un programador. Día 188

Elementos al azar en Java


La clase Random, del paquete java.util, a diferencia del método static de la clase Math(que solamente produce valore de tipo double), es capaz de producir valores de tipo boolean, float, byte, double, int, long y gaussianos.
Para usar esta clase, primer se debe importar. Esto se logra de la siguiente manera:

import java.util.Random;

Luego, la forma de crear el objeto es similar al utilizado para crear un objeto Scanner. Esto se logra de la siguiente manera:

Random azar = new Random();

Ya con esto creado podemos generar todos los tipos de números aleatorios que se mencionaron anteriormente, pero en este caso para simplificar las cosas, vamos a probar con números enteros. Por ejemplo, si hacemos lo siguiente:
int numeroAzar = azar.nextInt();
la variable numeroAzar podría tener un número entre  –2.147.483.648 y 2.147.483.647. Si quisiéramos que nuestro número se encuentre en un rango menor, digamos entre los primeros 10 números, entonces se puede hacer de esta otra manera:
int numeroAzar = azar.nextInt(10);
Al agregar un argumento a nextInt, estamos diciendo que nuestro número sea escogido entre el cero y el nueve. No se incluye el número ingresado en el argumento.
Vamos a ver un pequeño ejemplo:
import java.util.Random;

public class azar{
  public static void main(String[]args){
 
  Random azar = new Random();
  int numeroAzar = azar.nextInt(10);

  System.out.println("El numero escogido es: " + numeroAzar);
  }
}

¿Cómo crearíamos un arreglo con números al azar? Se me ocurre la siguiente alternativa:
Creo un arreglo de 10 elementos y una variable de tipo entero llamada numAzar, en esta última variable se irán generando los números al azar.
Para lograr esto lo que hice fue crear un ciclo for y dentro de él puse numAzar, la cual por cada ciclo irá generando un número al azar. Este número generado es ingresado al arreglo mientras el ciclo continua con su trabajo.
Al finalizar, se crea otro ciclo for, el cual se encarga de mostrar el contenido del arreglo.

import java.util.Random;
public class azar{
  public static void main(String[]args){
 
  //Se crea un objeto random, un arreglo y variables   
  Random azar = new Random();
  int arreglo[] = new int[10];
  int numAzar, i;
 
  //Se crean 10 numeros al azar y se guardan
  //en un arreglo

  for(i = 0;i < 10; i++){
      numAzar = azar.nextInt(10);
      arreglo[i] = numAzar;
  }

  //se muestran los numeros del arreglo
  for(i = 0;i < 10; i++){
      System.out.println("[" + arreglo[i] + "]");
  }
  System.out.println("");
  }
}


Luego de  ejecutar, este es el resultado:


Los elementos al azar se pueden utilizar en múltiples tareas, como por ejemplo, el reproductor de música lo utiliza para poder escoger una canción al azar y así evitar estar escuchando siempre las canciones en el mismo orden.
A continuación pondré un pequeño programa que escoge un número al azar y nosotros trataremos de encontrar ese número. Al final nos dirá cuántos intentos nos tomó.
Este programa consta de dos clases.

//clase pricipal
import javax.swing.JOptionPane;

public class Inicio{
  public static void main(String []args){
     
    String numero;
    int numeroConvertido, intentos = 0;
    Metodos datos = new Metodos();
   
    do{
        //solicitamos un numero en formato String, para que pueda
        //ser aceptado por JOptionPane
        numero = JOptionPane.showInputDialog("Ingresa un numero:");
        //el numero es convertido a int para poder pasarlo como
        //argumento al metodo comparaResultado
        numeroConvertido = Integer.parseInt(numero);
    
        //Se envian los datos al metodo comparaResultado y se recupera
        //un resultado
        JOptionPane.showMessageDialog(null, datos.comparaResultado(numeroConvertido));
        //por cada ciclo agregamos un intento
        intentos++;
       
    //se repetira el ciclo hasta que encontremos el numero   
    }while(numeroConvertido != datos.azar());
   
    //saliendo del ciclo se muestra el numero de intentos
    JOptionPane.showMessageDialog(null, "Nro. de intentos: " + intentos);
  }//fin main
}//fin class

//clase metodos
import java.util.Random;
public class Metodos{
   
  Random azar = new Random();
  private int numeroIngresado;
  private int numAzar;
 
  //constructor
  public Metodos(){
    numeroIngresado = 0; 
    numAzar = azar.nextInt(10);
  }
  //metodo que compara el numero ingresado
  //con el numero al azar
  public String comparaResultado(int num){

    numeroIngresado = num;

    if (numeroIngresado == numAzar){
        return "Son iguales";   
    }//fin if   

    else if(numeroIngresado > numAzar){
        return "El numero ingresado es mayor";   
    }//fin if

    else{
        return "El numero ingresado es menor";
    }//fin if

  }//fin metodo
 
  //para recuperar el numero al azar
  public int azar(){
      return numAzar;
  }
}//fin class

Esto es todo por ahora. Saludos


Gustavo J. Cerda Nilo
Diciembre 2016



C++ El apuntador This

El apuntador This En C++, cada objeto tiene acceso a su propia dirección a través de un puntero o apuntador denominado This. Lo...