Lunes 14 de Junio

Temas:


Solución del ejercicio de la clase anterior:

    TextReader lect= new TextReader("feriados.txt");
    String lin= lect.readLine();
    Fecha ant= decodFecha(lin); // Supone que hay al menos un feriado
    while (true) {
      lin= lect.readLine();
      if (lect.eofReached())
        break;
      Fecha feriado= decodFecha(lin);
      Fecha fecha= ant;
      int ndias= 0;
      while (fecha.compare(feriado)<0) {
        fecha= fecha.mannana();
        ndias= ndias+1;
      }
      println("Entre el "+ant.diaSemana()+" "+ant.toString()+" y el "+
              feriado.diaSemana()+" "+feriado.toString()+": "+ndias+" dias");
      ant= feriado;
    }
La función decodFecha:

    Fecha decodFecha(String lin) {
      FieldParser decod= new FieldParser(lin,"/");
      int dia= decod.readInt();
      int mes= decod.readInt();
      return new Fecha(dia, mes, 2000);
    }
Observación: la función decodFecha se pudo haber reemplazado por una función leeFecha que en vez de recibir como parámetro una línea del archivo, recibe el lector del archivo. El problema es que hacer cuando se encuentra el fin de archivo:

    Fecha leeFecha(TextReader lect) {
      String lin= lect.readLine();
      if (lect.eofReached())
        return ???;
      FieldParser decod= new FieldParser(lin,"/");
      ...
      return new Fecha(dia, mes, 2000);
    }
Sería ilegal tratar de construir un decodificador de una línea inexistente (se producirá un error en tiempo de ejecución). Más adelante veremos que en este caso se debe retornar la referencia nula (null).


Problemas tipo

Aprender a descomponer convenientemente un problema en sus partes toma bastante tiempo. No elegir adecuadamente las partes puede originar un problema que es aún más difícil que el original. Por esta razón, en este curso en la mayoría de los problemas la descomposición en subproblemas estará dada en el enunciado.

Los típicos problemas que Ud. verá en los controles, tareas y ejercicios serán:

Más adelante se preguntarán problemas de definición de clase y problemas completos acerca de clases.


Arreglos Nativos

Los arreglos asociativos de la clase Map no son nativos de Java, es decir no vienen incluidos en forma estándar en el lenguaje. La clase Map ha sido introducida en este curso como una forma de facilitar el aprendizaje de los arreglos en general. Pero esta clase ha sido definida (implementada) en términos de otros objetos que sí son nativos en Java.

Java ofrece a los programadores arreglos nativos, es decir que vienen integrados al lenguaje Java. La ventaja de estos arreglos es doble: (i) son mucho más eficientes que los de la clase Map, y (ii) se manipulan más cómodamente gracias a reglas sintácticas especiales que ofrece Java. Sin embargo, los arreglos nativos tienen la desventaja de ser menos poderosos que los arreglos de la clase Map. Las siguientes son las caraterísticas de los arreglos nativos (que los diferencian de los arreglos de la clase Map):

Construcción:

Sintaxis:

exp -> new tipo[ exp ]

Ejemplo 1: new int[20]

Construye un arreglo de 20 enteros. Los índices están en el rango [0,19]. Los valores almacenados en el arreglo serán enteros (inicialmente todos en 0).

Ejemplo 2: new String[10]

Construye un arreglo de 10 strings. Los índices están en el rango [0,9]. Los valores almacenados en el arreglo serán strings (no inicializados).

Declaración de variables:

Sintaxis:

inst -> tipo[ ] ident= exp ;

Ejemplos:

    int[ ] a= new int[20];
    String[ ] b= new String[10];
    int a2= new int[20]; // error en compilación!
    String[ ] b2= new int[10]; // error en compilación!
En la primera instrucción se declara una variable a que referenciará arreglos de enteros. La variable referencia inicialmente un arreglo de 20 enteros. En la segunda instrucción la variable b referencia un arreglo de 10 strings. Las dos últimas instrucciones son ilegales porque el tipo de la variable no coincide con el tipo de la expresión de inicialización.

Cambiar el valor de un elemento en un arreglo:

Sintaxis:

exp-arreglo [ exp-índice ] = exp-valor;

en donde exp-arreglo corresponde típicamente a una variable que referencia un arreglo.

Ejemplos:

    a[0]= 5;
    a[1]= 10;
    a[i]= 20;
    a[20]= 0; // error en tiempo de ejecución!
    a[3]= "hola"; // error en compilación!
El primer error se debe a que el índice está fuera del rango válido para el arreglo a. El segundo se debe a que el tipo del valor asignado no es entero.

Inicialización de los elementos de un arreglo (de strings):

    int i=0;
    while (i<10) {
      b[i]= "";
      i= i+1;
    }
Obtener el valor de un elemento en un arreglo:

Sintaxis:

exp-arreglo [ exp-índice ]

Ejemplo:

    int x= a[0];
    int i= 0;
    while (i<20) {
      println(a[i]);
      i= i+1;
    }

Uso de arreglos nativos

Todos los programas que hemos visto hasta ahora y que usan la clase Map se pueden transformar trivialmente de modo que utilicen arreglos nativos de Java. La siguiente es una receta para transformarlos en programas que usan arreglos nativos. Por simplicidad consideraremos un programa que usa sólo un arreglo, además el tipo de los valores es siempre de tipo String (podría ser también entero, real o boolean) y que el intervalo de llaves usadas es [0,100].

(En realidad los arreglos de la clase Map permiten mezclar valores de distinto tipo usar llaves dispersas, sin estar contenidas en un intervalo fijo. Sin embargo, no vimos ningún ejemplo que usara esta propiedad de la clase Map.)

Haga las siguientes transformaciones en el programa:

Con la clase Map Con arreglos nativos
Map tab= new Map() String[] tab= new String[101];
tab.put(i,v); tab[i]= v;
... tab.getString(i) ... ... tab[i] ...