miércoles, 2 de noviembre de 2016

Programación del Sinclair QL (II): Formas estructuradas de intrucciones básicas



Arreglos, mas conocidos como arrays, vectores o matrices

Como ingeniero informático llamaré a las cosas por su nombre. Array es una palabra inglesa que no existe en Español, en su lugar hay que usar la palabra arreglo. Se llama vector a un arreglo de una dimensión, y matriz a un arreglo de dos dimensiones, estos nombres se usan por similitud con las estructuras matemáticas del mismo nombre, pero el nombre que debemos usar debe ser arreglo unidimensional o arreglo bidimensional.

SuperBASIC admite arreglos de una y de dos dimensiones, pero con varias diferencia sobre los del  BASIC estandar.

En un arreglo numérico se incluye siempre el elemento cero, pero por compatibilidad se mantiene que el número sea el máximo elemento del arreglo, de forma que cuando se define un arreglo de 10 elementos estos van del 0 al 10, y no del 1 al 10 como en BASIC estándar, o del 0 al 9 como en C.

Los arreglos de caracteres son siempre de elementos de un solo carácter con longitud máxima indicada, y guardando en el elemento cero la longitud real de la cadena, de forma que si creamos un arreglo con DIM a$(10), b$(10,5) lo que hacemos es crear en a$ una variable de cadena de diez posiciones máximo, y en b$ creamos ONCE cadenas de cinco posiciones máximo. En SuperBASIC el nombre del arreglo es una referencia a su contenido, de esta manera si hacemos a$="Hola" o b$(3)="Otra cadena", lo que hacemos es usar cadenas de longitud máxima predefinida. Si hacemos PRINT a$;".";b$(3) en pantalla aparece Hola.Otra sin incluir espacios.

Podemos usar esto para imprimir todos los elementos de un arreglo numérico o de cadena en un PRINT, o para igualar entre si elementos de arreglos de cadena y usar por ejemplo b$(1)=a$, pero esta asignación no funciona con arreglos numéricos. Podemos dar valor a un arreglo de cadena usando por ejemplo INPUT a$ pero esto no funciona con numéricos.

Formas corta y larga de las instrucciones, uso del IF

En el superBASIC hay dos formas de escribir una instrucción, la que denominan forma corta abarca hasta el final de la línea en curso y no necesita cerrarse por tanto, mientras que la forma larga abarca varias líneas. Un ejemplo típico será un pequeño IF que podemos escribir de dos maneras

Forma LARGA     Forma CORTA
130 IF columna > 10 THEN 
140   columna=1
150   linea=linea+1
160 END IF 
   
130 IF columna > 10 THEN columna=1 : linea=linea+1

La forma corta no necesita cierre pues siempre termina en la misma línea en la que está, mientras que la forma larga si necesita siempre cierre. Esto es válido para cualquier instrucción.

En superBASIC existe la forma IF ... THEN ... ELSE ... END IF normal en los BASIC, con la parte ELSE opcional, pero con la particularidad de que el THEN es opcional, por lo que para la forma corta debe reemplazarse por dos puntos, pudiendo escribirse por ejemplo cualquiera de estas dos líneas

IF linea=23 THEN linea=1 : ELSE linea=linea+1
IF linea=23 : linea=1 : ELSE linea=linea+1

Bucle FOR

Los bucles FOR del QL mantienen la compatibilidad con el BASIC estándar pero añaden características adicionales. Veamos un bucle muy básico, presentaremos en pantalla una lista de números del 1 al 20:

BASIC     SuperBASIC
10 FOR i=1 TO 20 
20   PRINT i 
30 NEXT i
   
10 FOR i=1 TO 20
20   PRINT i 
30 END FOR i

Vemos que la única diferencia es como terminamos el bucle, y ya que la instrucción NEXT sigue funcionando en SuperBASIC, aunque añade otro sentido, podemos escribir ambos programas en el QL obteniendo el mismo resultado.

Los bucles en SuperBASIC disponen de dos instrucciones que podemos usar en su interior, la primera es NEXT, que hace que el bucle pase directamente al siguiente ciclo sin pasar por el resto de instrucciones. Si deseamos por ejemplo que el bucle se salte los elementos que sean múltiplos de 3, podemos escribir el código así:

BASIC     SuperBASIC
10 FOR i=1 TO 20 
20   IF (i MOD 3) = 0 THEN GOTO 40
30   PRINT i 
40 NEXT i
   
10 FOR i=1 TO 20
20   IF (i MOD 3) = 0 THEN NEXT i
30   PRINT i 
40 END FOR i

Como vemos ahora se imprimen solo los números 1,2,4,5,7,8,10,11,13,14,16,17,19,20 en ambos casos, pero nos hemos ahorrado el GOTO, y sobre todo, podemos incluir todas las líneas que deseemos en el bucle, sin importarnos cual es la línea que lo termina. Nuevamente podemos teclear ambas variantes del programa en SuperBASIC y funcionan ambas.

La otra instrucción que se puede usar en los bucles es EXIT, que como podemos imaginar hace que nos salgamos del bucle en el lugar en que nos encontremos. Supongamos que deseamos hacer que el bucle termine aleatoriamente, para lo que podemos escribir esto:
BASIC     SuperBASIC
100 CLS
110 FOR i=1 TO 20
120   IF (i MOD 3) = 0 THEN GOTO 160
130   LET a = INT(RND*11)
140   PRINT i, a
150   IF a = 10 THEN GOTO 170
160 NEXT i
170 REM Fin
   
100 CLS
110 FOR i=1 TO 20
120   IF (i MOD 3) = 0 THEN NEXT i
130   a = RND(0 TO 10)
140   PRINT i, a
150   IF a = 10 THEN EXIT i
160 END FOR i

Nuevamente, podemos escribir ambos programas en SuperBASIC con el mismo resultado, pero la segunda forma tiene la ventaja de que no necesitamos conocer donde acaba el bucle para salir de el, ni debe existir siquiera una sentencia posterior. Podemos ver otra característica del lenguaje interesante, la instrucción LET es opcional. Y por último, la instrucción RND es mas completa, si no decimos nada genera un número real entre 0 y 1, pero podemos darle un rango y generará números en ese rango, evitando calcular la parte entera de la multiplicación.

Como característica adicional muy interesante, un bucle FOR puede contener dos formas de marcar los límites, la tradicional del TO-STEP o la posibilidad de indicarle una lista de valores sobre los que iterar, así podemos escribir:

FOR i = 1 TO 20 STEP 3
FOR i = 1,3,7,10,20 TO 25,40,50

Y el bucle iterará por los valores 1, 4, 7, 10, 13, 16 y 19 en el primer caso, y por 1, 3, 7, 10, 20, 21, 22, 23, 24, 25, 40, 50 en el segundo.

Bucle REPeat

En otros lenguajes hay dos construcciones de bucles llamadas normalmente WHILE (condición) - WEND y REPEAT - ULTIL (condición), que se diferencian en cuando se verifica que se cumpla la condición, antes de empezar o tras la primera iteración. En SuperBASIC se dispone del REPeat como la otra forma estructurada de iterar en un bucle, que no verifica las condiciones nunca, debemos añadir un EXIT para poder salir del mismo siempre. Cuando tecleamos el programa, solo es necesario escribir la parte en mayúsculas de comando para que el sistema la complete. Este es un bucle básico que cuenta del 1 al 20:

BASIC     SuperBASIC
100 CLS
110 LET I=0
120   LET I=I+1
130   PRINT I
140 IF (I < 20) THEN GOTO 120
   
100 CLS
110 i=0
120 REPeat bucle
130   i = i + 1
140   PRINT i
150   IF i = 20 THEN EXIT bucle
160 END REPeat bucle

Ambas versiones funcionan en SuperBasic nuevamente. Estos bucles son útiles, pero se echa de menos una condición de entrada o de salida que nos ayude un poco mas, aunque podemos poner el EXIT como la primera instrucción del bucle para simular el WHILE, o como la última para el REPEAT. En estos bucles, la instrucción NEXT funciona pero no sirve para seguir iterando sino que es un sinónimo del EXIT para salir de bucle.

SELect ON

Mientras en BASIC clásico se debe usar ON...GOTO / ON...GOSUB o instrucciones IF, en SuperBASIC se dispone del comando SELect como la forma estructurada de ejecutarlo. Veamos un ejemplo en el que decidimos que hace según el valor de una variable

BASIC     SuperBASIC
100 INPUT "Valor: ";VAR
110 ON VAR GOTO 140,160,180
120 PRINT "Valor no válido ";VAR
130 GOTO 200
140 PRINT "Valor 1"
150 GOTO 200
160 PRINT "Valor 2"
170 GOTO 200
180 PRINT "Valor 3"
190 GOTO 200
200 REM fin
   
100 INPUT "Valor: ";valor
110 SELect ON valor
120   ON valor=1
130     PRINT "Valor 1"
140   ON valor=2
150     PRINT "Valor 2"
160   ON valor=3
170     PRINT "Valor 3"
180   ON valor=REMAINDER 
190     PRINT "Valor no válido: ";valor
200 END SELect 

Ambas versiones funcionan en SuperBasic nuevamente, aunque la primera dará un error si el valor introducido no es 1, 2 o 3 dependiendo de la versión del BASIC que usemos, y lo dará en SuperBASIC. El uso de ON en la primera línea es opcional, y el de REMAINDER nos posibilita tratar cualquier caso no contemplado entre los seleccionados. Además, el sistema puede tratar con listas de valores, por tanto podemos poner por ejemplo:

110 SELect valor
120   ON valor=1,3,5
130     PRINT "Valor impar"
140   ON valor=2,4,6
150     PRINT "Valor par"
180   ON valor=REMAINDER 
190     PRINT "Valor fuera de rango"
200 END SELect 

Esta propiedad de usar rangos usando la forma corta nos permite reemplazar un IF por un SELect

110 SELect valor=1 TO 5, 11 TO 15 : PRINT "Valor fuera de rango"

3 comentarios:

  1. Y además de vectores y matrices, los arreglos (DIM) pueden tener más dimensiones, 3, 4, etc... tantas como de la memoria. Aunque la verdad, más de tres dimensiones es raro que se usen.

    ResponderEliminar
    Respuestas
    1. Efectivamente, SuperBASIC no tiene limitación del número de dimensiones de un arreglo, mas de 3 es muy raro e incluso 3 se usan muy poco.

      Eliminar
  2. Interesante artículo. La verdad es que el SuperBasic tiene muchas curiosidades.

    Otro detalle curioso es que se puede eliminar el ON variable de los bloques interiores de cada selección. Por ejemplo:

    110 SELect valor
    120 =1,3,5
    130 PRINT "Valor impar"
    140 =2,4,6
    150 PRINT "Valor par"
    180 =REMAINDER
    190 PRINT "Valor fuera de rango"
    200 END SELect

    ResponderEliminar