AnteriorPosterior

8. Saltos: GOTO y GOSUB

Por: Nacho Cabanes
Actualizado: 19-04-2019 22:35
Tiempo de lectura estimado: 10 min.

 

BASIC

8. Saltos: GOTO y GOSUB

En ocasiones nos puede interesar saltar a una parte distinta del programa. Esto será especialmente útil después de comprobar una cierta condición, por ejemplo: "si las ganancias han sido superiores a 1000, saltar a la parte de programa que decide cómo desglosar los beneficios".

Para saltar usaremos la orden GOTO (del inglés "go to", ir a; de hecho, alguna versión de BASIC permite o incluso exige que GO TO se escriba como dos palabras separadas). Después de esta orden detallaremos el número de línea a la que deseamos saltar. Un ejemplo puede ser el siguiente programa, que escribe indefinidamente la palabra "Hola", porque la línea 40 hace que el programa vuelva a la línea 30 una y otra vez:

10 REM Un programa sin salida 
20 REM Cuidado - se quedara "colgado" 
30 PRINT "Hola" 
40 GOTO 30

(Fuente "0801.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

Es muy fácil que este programa no se pueda interrumpir y deje el ordenador "colgado". En algún ordenador (y alguna versión de BASIC), se podría interrumpir pulsando dos veces la tecla Esc, o las teclas Ctrl+C, o alguna otra combinación similar de teclas. En otros puede no haber más remedio que apagar el equipo.

Basic256 (y alguna otra versión moderna de BASIC) no permite números de líneas, pero aun así permite usar GOTO, si indicamos una etiqueta (una palabra terminada con el símbolo de "dos puntos") a la que saltar:

REM Un programa SIN salida 
REM Cuidado - se quedara "colgado" 
repetir: PRINT "Hola" 
GOTO repetir

(Fuente "0802.bas". Probado en Basic256)

En este caso, el programa no terminará hasta que no pulsemos el botón "STOP" de nuestro entorno de desarrollo.

Ejercicio propuesto 8.1: Crea un programa que escriba tu nombre una cantidad indeterminada de veces (hasta que el usuario lo interrumpa).

Es importante recordar que GOTO es un salto incondicional, de modo que podemos "saltarnos" un trozo de un programa sin darnos cuenta si no llevamos cuidado, como en el siguiente ejemplo:

10 REM Este programa no escribe "Hola" 
20 GOTO 40 
30 PRINT "Hola" 
40 PRINT "Adios"

(Fuente "0803.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

Si nos equivocamos y saltamos a una línea, que no existe, el intérprete de BASIC daría un mensaje de error parecido a "Undefined line 50" o "Line does not exist in 10"

10 PRINT "Hola" 
20 GOTO 50

(Fuente "0804.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

Ejercicio propuesto 8.2: Crea un programa que escriba una cantidad indeterminada de asteriscos, sin avanzar de línea (hasta que el usuario lo interrumpa).

Es muy habitual usar GOTO en conjunción con IF, para hacer que un bloque de un programa se repita mientras se cumpla una cierta condición, por ejemplo:

10 PRINT "Introduzca el numero 5" 
20 INPUT x 
30 IF x <> 5 THEN GOTO 10
40 PRINT "Correcto!"

(Fuente "0805.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

(Dentro de poco veremos alternativas más elegantes a este uso de GOTO)

Además, alguna versión de BASIC antigua puede permitir sólo la sintaxis "IF condición THEN GOTO linea" o cualquiera de dos versiones abreviadas de la misma: "IF condición THEN linea" o "IF condición GOTO linea", y no permitir ninguna otra orden en una condición IF. En este caso, el programa 0701, que decía si un número es mayor que 10, sería más incómodo y menos legible:

10 PRINT "Introduzca un numero" 
20 INPUT x 
30 IF x > 10 THEN GOTO 50 
40 END 
50 PRINT "Es mayor que 10" 

(Fuente "0806.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

Ejercicio propuesto 8.3: Crea una programa que te pida un número y diga si es negativo, es cero o es positivo, usando GOTO en vez de ELSE

La orden GOTO tiene una gran carencia: el programa sigue avanzando después del salto, como si no hubiera ocurrido ningún salto. Pero a veces no es eso lo que más nos interesa, sino que nos encontraremos con tareas repetitivas, y querremos que nuestro programa salte a una zona en la que le hayamos indicado cómo dar esos pasos repetitivos, pero después vuelva y siga trabajando normalmente. En estos casos en que queremos que salte y vuelva, emplearemos la orden GOSUB, e indicaremos el punto de retorno con RETURN, así:

10 ' Ejemplo de GOSUB y RETURN
20 ' Vamos a saludar
30 GOSUB 100
40 PRINT "Juan"
50 GOSUB 100: ' volvemos a saludar
60 PRINT "Alberto"
70 END
100 PRINT "Hola"
110 PRINT "Como estas?"
120 RETURN

(Fuente "0807.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Msx Basic 2.1, Commodore 64 Basic V2 -si se cambian los apóstrofes por REM-)

Las líneas 100 a 120 forman la "subrutina" (de ahí viene la palabra GOSUB: de "go subroutine", ir a una subrutina) a la que saltamos cada vez que nos interesa, y de la que volvemos para que el programa siga por donde estaba. En este caso hemos indicado dónde está el final del programa con la orden END, para evitar que después de la línea 60 el programa siga avanzando y pase a la línea 100 (la subrutina) sin que nosotros se lo pidamos.

El programa anterior sería equivalente a este otro:

30 PRINT "Hola" 
35 PRINT "Como estas?" 
40 PRINT "Juan" 
50 PRINT "Hola" 
55 PRINT "Como estas?" 
60 PRINT "Alberto"

(Fuente "0808.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

He eliminado las líneas con REM, que sólo son aclaraciones para nosotros; cada GOSUB es equivalente a que se dieran todos los pasos que hay entre el punto de comienzo del salto (en este caso, la línea 100) y la línea de RETURN.

El equivalente en Basic256 del primer programa con GOSUB sería

REM Ejemplo de GOSUB y RETURN 
REM Vamos a saludar 

GOSUB saludo 
PRINT "Juan" 

GOSUB saludo
PRINT "Alberto" 

END 

saludo:
PRINT "Hola" 
PRINT "Como estas?" 
RETURN

(Fuente "0809.bas". Probado en Basic256)

Ejercicio propuesto 8.4: Crea una subrutina que escriba 10 asteriscos en la misma línea. Úsala para pedir al usuario 3 nombres y mostrarlos "subrayados".

Existe otro uso adicional de GOSUB en los BASIC antiguos: si "hacemos demasiadas cosas" en la misma línea de un IF, no sólo el programa acabará resultando más difícil de leer, sino que además, en muchos BASIC clásicos había un límite de tamaño relativamente pequeño para cada línea de programa, típicamente cerca de 256 letras. Por eso, si tenemos que hacer muchas cosas que dependan de la condición, será mejor moverlas a una subrutina:

10 PRINT "Dime tu nombre" 
20 INPUT nombre$ 
30 IF nombre$="Nacho" THEN GOSUB 100
40 END 
100 REM Saludar 5 veces
110 FOR i = 1 TO 5
120   PRINT"HOLA"
130 NEXT i
140 RETURN

(Fuente "0810.bas". Probado en GwBasic 2.02, Locomotive Basic de Amstrad CPC, Commodore 64 Basic V2, Msx Basic 2.1)

Notas: Casi todas las versiones de BASIC permiten la orden GOTO; pero algunas antiguas no permiten GOSUB. En algunas versiones de BASIC se podía (o incluso se debía) escribir estas órdenes como dos palabras separadas: GO TO y GO SUB.

Las órdenes GOTO y GOSUB se usan cada vez menos, porque en versiones modernas de BASIC tendremos alternativas más elegantes para estructuras repetitivas, como la orden WHILE, que veremos pronto. También tendremos formas más eficientes de crear subrutinas, que conoceremos poco después.

8617 visitas desde el 19-04-2019

AnteriorPosterior