Nociones de BASIC

Por: Javier Gil Chica
Actualizado: 17-04-2019 11:17
Tiempo de lectura estimado: 23 min.

 

Nociones de Basic

(Tomado de los apuntes de la asignatura "Periféricos" de Ingeniería Técnica en Informática de Sistemas, Universidad de Alicante, por Javier Gil Chica, 1995).

1.- ELEMENTOS

1.1. Introducción.

BASIC nació en la Universidad de Hannover en 1969 como un intérprete apto para todos los públicos, incluso personas sin relación directa con la informática. Desde entonces se ha ramificado en multitud de versiones, y durante un tiempo llegó a dominar de forma hegemónica como lenguaje de "todo uso".

La evolución de los ordenadores, mas rápidos, capaces y baratos, impulsó la creación de software de complejidad creciente a lo que BASIC temporalmente no pudo hacer frente de forma competitiva ante compiladores de lenguajes estructurados como Pascal o C.

Puede decirse que el compilador BASIC llegó tarde, y cuando se ha querido reaccionar en los últimos años, incluyendo una versión estructurada, QBasic 1.1, en la entrega 5.0 del sistema operativo de Microsoft, BASIC ya tenía muy poco que hacer en el mercado del DOS frente a productos de la calidad de Turbo Pascal de Borland, por ejemplo.

Sin embargo, el impulso de los entornos gráficos y la complejidad de la programación en Windows han abierto hueco a la programación visual, espacio en el que VisualBasic brilla por su potencia y facilidad de uso. En su última versión va mas allá, incluyendo funciones de base de datos, política reforzada por el hecho de existir en el mercado aplicaciones que incorporan VB como lenguaje de macros.

Daremos aquí un repaso somero y rápido al BASIC standard.

1.2. Tipos de datos básicos.

El siguiente gráfico refleja concisamente los tipos de datos básicos del lenguaje:

                    TIPOS DE DATOS  

  NUMERICOS                            CADENA  

REALES ENTEROS LONGITUD FIJA LONGITUD VARIABLE

a su vez, los datos numéricos pueden ser de simple o de doble precisión.

Existen dos formas principales de declarar las variables:

a) por el carácter final del nombre

     % indica entero simple  
     & indica entero doble  
     ! indica real simple  
     # indica real doble  
     $ indica cadena de longitud variable

b) a través del modificador AS de las sentencias DIM, REDIM

COMMON, SHARED o STATIC. Los distintos tipos de AS son

     AS INTEGER              entero simple  
     AS LONG                 entero doble  
     AS SINGLE               real simple  
     AS DOUBLE               real doble  
     AS STRING               cadena de longitud variable  
     AS STRING * numero      cadena de longitud fija  
     AS var_def_us           variable definida por usuario

1.3. Operadores

BASIC incorpora los operadores habituales de todos los lenguajes:

a) Numéricos

     +   suma  
     -   resta  
     *   multiplicación  
     /   división  
     ^   exponenciación  
     \   división entera     
     MOD resto

b) Alfanuméricos. Solo se incluye el operador + de concatenación de cadenas

c) Relacionales

     =  igual  
     <> distinto  
     >  mayor  
     >= mayor o igual  
     <  menor  
     <= menor o igual

d) Lógicos

     AND  
     OR  
     NOT  
     XOR  
     IMP  
     EQV

Las tablas de verdad de los operadores menos conocidos son las siguientes:

    A  B  A EQV B  A IMP B

    V   V      V         V  
    V   F      F         F  
    F   V      F         V  
    F   F      V         V

1.4. Variables multidimensionales

Las variables multidimensionales se declaran mediante la sentencia DIM, cuya sintaxis es

    DIM <nombre_variable> (rango)

donde <nombre_variable> es un nombre de variable que normalmente incluye como último carácter aquél que determina su tipo y (rango) indica el n

a) Un número simple n, lo que indica los n+1 elementos 0..n

b) p to q, donde p es el primer índice y q el último

c) (rango1,rango2,...rangon) para declarar matrices cuadradas, cúbicas, etc.

Ejemplos:

    DIM matriz! (1 to 20, 1 to 20)  
    DIM pesos! (40)  
    DIM tensor! (2,2,2)

El tipo de elementos de la variable se puede definir mediante el modificador AS . Por ejemplo:

   DIM Lista$ (100) AS STRING*20

1.5. Variables tipo registro.

El usuario puede definir variables tipo registro, donde bajo el mismo nombre se engloba información relacionada pero de naturaleza diferente. La sintaxis de este tipo de declaraciones es la siguiente:

    TYPE nombre_del_tipo  
        nombre_variable1 AS tipo1  
        nombre_variable2 AS tipo2  
        .  
        .  
        .  
    END TYPE

Por ejemplo:

    TYPE Tordenador  
        procesador AS string*5  
        RAM        AS integer  
        HD         AS integer  
        precio     AS real  
    END TYPE

Una vez definido el tipo, pueden declararse variables de dicho tipo mediante DIM, como se muestra a continuación:

   DIM miordenador AS Tordenador  
   DIM INTERNET(1,2000) AS Tordenador

1.6. Funciones numéricas y de cadena de caracteres.

BASIC incorpora las funciones numéricas habituales:

  • SEN seno
  • EXP exponencial
  • COS coseno
  • LOG logaritmo
  • TAN tangente
  • RND número aleatorio
  • ATN arco tangente
  • ABS valor absoluto
  • SQR raiz cuadrada

y algunas otras como FIX, INT y CINT cuyas sintaxis y acciones pueden consultarse en la ayuda en línea de Qbasic.

En cuanto a las funciones de manejo de cadenas, las mas habituales son:

  • VAL devuelve el valor numérico de una cadena
  • STR$ convierte un número en una cadena de caracteres
  • HEX$ convierte decimal a hexadecimal
  • LEN devuelve la longitud de una cadena
  • STRING$ genera una cadena repitiendo un carácter
  • SPACE$ genera una cadena de espacios en blanco

2.- ESTRUCTURAS DE CONTROL

El BASIC clásico controlaba el flujo del programa mediante sentencias como GOTO, GOSUB o ON...GOTO, poco apropiadas para programar estructuradamente. Actualmente se cuenta con instrucciones de control de flujo similares a las de otros lenguajes.

2.1. Ejecución condicional.

Se consigue mediante la sentencia IF.

Su sintaxis es:

IF condicion THEN

Se puede usar en combinación con ELSEIF:

IF condicion1 THEN  
    bloque de sentencias 1  
ELSEIF  
    bloque de sentencias 2  
ENDIF

Pueden escribirse tantos ELSEIF como se desee, pero cuando hay varias posibilidades, es mejor usar la sentencia SELECT CASE, según el modelo siguiente:

SELECT CASE expresion  
    CASE valor1  
        bloque 1  
    CASE valor2  
        bloque 2  
    CASE valor 3  
        bloque 3  
    CASE ELSE  
        bloque alternativo  
END SELECT

2.2. Bloque repetitivos.

La instrucción FOR..NEXT ejecuta un bloque de sentencias un número determinado de veces. Su sintaxis es

FOR contador=inicio TO final (STEP incremento)  
    bloque  
NEXT contador

donde inicio es el valor inicial del contador, fin su valor final y opcionalmente podemos especificar el incremento del contador en cada iteración.

Un grupo de sentencias puede ejecutarse mientras se cumple una determinada condición, o hasta que se cumpla una determinada condición. En el primer caso, se escribe

DO WHILE condicion  
    bloque  
LOOP

y en el segundo

DO UNTIL condicion  
    bloque  
LOOP

En estos dos casos, la condición se evalúa antes de ejecutar el bloque de sentencias. Cuando WHILE o UNTIL se sitúan al final del bloque, tras LOOP, la condición se evalúa después de ejecutar el de ejecutarse el bloque de sentencias:

DO   
    bloque   
LOOP WHILEUNTIL condicion

Es posible forzar la salida del bloque mediante la instrucción DO EXIT. La sintaxis habitual es:

DO   
    bloque   
    IF condicion2 THEN DO EXIT   
LOOP WHILEUNTIL condicion1

La sentencia WHILE..WEND no es necesaria, dada la flexibilidad de la construcción DO..LOOP.

3.- PERIFERICOS Y FICHEROS

3.1. Pantalla.

La sentencia mas habitual es PRINT, que se usa para escribir textos en pantalla. Sus argumentos pueden ser numéricos o de cadena. Puede tener uno, varios o ninguno de ellos, en cuyo caso se escribe una línea en blanco. Los argumentos pueden ir separados por ";" en cuyo caso se escriben uno a continuación de otro, o por ",", y entonces entre el primer carácter de un argumento y el primer carácter del siguiente hay 14 columnas. Un control mas preciso se consigue con la sentencia PRINT USING. Su sintaxis puede buscarse en la ayuda en línea de Qbasic.

La instrucción LOCATE coloca el cursor en una fila y columna determinadas. Puede especificarse si el cursor está visible o nó, así como su tamaño. La sintaxis es

LOCATE fila, columna, cursor, inicio, fin

donde cursor especifica si está visible, 1 o no, 0 e inicio y fin indican la primer y última líneas de exploración del cursor, empezando por la parte inferior.

Otras instrucciones útiles son CSRLIN, que devuelve la línea actual del cursor, y POS, que devuelve la columna actual.

3.2. Teclado.

La forma usual de obtener respuestas a través de teclado es mediante la sentencia INPUT , que permite leer uno o varios datos, que se almacenan en la lista de variables especificadas en la sentencia.

INPUT "Mensaje_optativo" listavariables

Mensaje_optativo es un mensaje que aparece antes de que se introduzcan los datos, haciendo en general referencia a su naturaleza. Si tras él se escribe ";" aparecerá un signo de interrogación.

listavariables es una lista con las variables a leer, separadas por comas.

La sentencia LINE INPUT permite leer desde teclado o fichero una línea de texto. El texto introducido no necesita comillas dobles y puede incluir comas simples, sin que esto signifique que se están introduciendo varias cadenas. Su sintaxis es

LINE INPUT "Texto opcional"; variable$

Tanto INPUT como LINE INPUT esperan la pulsación de para leer la(s) variable(s). La función INPUT$(X) lee las variables después de haber pulsado X caracteres, sin devolver eco a pantalla.

3.3. Ficheros.

Los ficheros en BASIC pueden ser de acceso secuencial o aleatorio. Pueden estar organizados en líneas o en registros, o pueden ser vistos como una simple sucesión de bytes. Se abren con la sentencia OPEN y se cierran con CLOSE. Cuando se abre un fichero, se asigna un "canal" de comunicación con él. Puede haber varios canales abiertos simultáneamente, dependiendo el número máximo de la configuración de nuestro sistema. La sintaxis de OPEN es:

OPEN "nombre_archivo" FOR <modificador> AS #X

donde indica la operación a realizar y X es el número del canal. Pueden usarse los siguientes modificadores:

a) Para archivos de acceso secuencial

  • INPUT solo lectura

  • OUTPUT solo escritura

  • APPEND añadir registros

b) Acceso directo

  • RANDOM lectura y escritura

c) Modo binario

  • BINARY lectura y escritura

Por ejemplo, para crear un archivo de texto en el que vamos a escribir registros:

OPEN "Datos.txt" FOR OUTPUT AS #1

Los ficheros de acceso secuencial están formados por líneas, delimitadas por el carácter salto de carro. Cada una de ellas contiene una o mas variables, que pueden ser campos de una variable de tipo registro.

Para escribir en un fichero abierto para escritura, se usa la sentencia WRITE, con la sintaxis WRITE #X, variable$, donde X es el número del canal y las variables van separadas por ",".

Para leer registros de un fichero secuencial, este se abre con el modificador INPUT. La sentencia que permite leer línea por línea es INPUT, y su sintaxis es:

INPUT #X, variable(s)

donde X es el número de canal y las variables van separadas por comas. Con LINE INPUT #X, variable$ se lee una línea completa del archivo, incorporando todos los registros a una única variable de texto. Como ejemplo, el siguiente fragmento introduce líneas desde teclado para después leer línea a línea y escribirlas en pantalla:

OPEN "FileBas.txt" FOR OUTPUT AS #1  
DO  
LINE INPUT linea$  
WRITE #1, linea$  
LOOP UNTIL linea$=" "  
CLOSE #1  
OPEN "FileBas.txt" FOR INPUT AS #1  
DO UNTIL EOF(1)  
INPUT #1, linea$  
PRINT linea$  
LOOP  
CLOSE #1

Ejemplo: Escribir un archivo de texto conteniendo en cada línea el nombre, dirección y teléfono de una persona. Recuperar después esa información y exponerla en pantalla:

OPEN "FileBas.txt" FOR OUTPUT AS #1  
DO  
INPUT nombre$  
INPUT edad$  
INPUT telefono$  
WRITE #1, nombre$,edad$,telefono$  
LOOP WHILE telefono$<>"0"  
CLOSE #1  
OPEN "FileBas.txt" FOR INPUT AS #1  
DO UNTIL EOF(1)  
INPUT #1, nombre$,edad$,telefono$  
PRINT nombre$,edad$,telefono$  
LOOP  
CLOSE #1

Los ficheros de acceso aleatorio, están formados por registros de longitud fija. Cada registro tiene una serie de campos, también de longitud fija. Lo usual es declarar el tipo de registro y la distribución de campos mediante TYPE. El fichero se abre mediante las instrucciones:

OPEN "nombre_fichero" FOR RANDOM AS#X LEN=LEN(variable)

donde variable es una variable del tipo especificado en el bloque TYPE y LEN es su longitud en bytes. Por ejemplo:

TYPE Tmoto  
marca AS STRING*10  
potencia AS INTEGER  
cilindros AS INTEGER  
tipo AS STRING*10  
END TYPE  

DIM moto AS Tmoto  
OPEN "Motos.dat" FOR RANDOM AS#1 LEN=LEN(moto)

Los ficheros de acceso directo o aleatorio pueden verse como una secuencia de registros, cada uno con la misma longitud, numerados desde el primero al último. Para leer/escribir uno determinado, es necesario referirse a él por su número, usando las sentencias GET y PUT respectivamente. La sintaxis es:

PUT #X, numero_registro, variable

GET #X, numero_registro, variable

Los ficheros binarios pueden considerarse como ficheros de acceso directo donde los registros son de 1 byte. Se lee y escribe con GET y PUT, y cada vez se leen o escriben tantos bytes como la longitud de la variable donde se almacenan los datos. La función SEEK permite colocar el puntero de archivo en el byte que deseemos.

3.4. Periféricos.

Se pueden abrir periféricos específicos mediante OPEN especificando el nombre predefinido para ese periférico. Los periféricos permitidos por QBASIC son los siguientes:

  • COM1 Puerto Serie 1 Entrada/Salida
  • COM2 Puerto Serie 2 Entrada/Salida
  • KYBD Teclado Entrada
  • LPT1 Puerto paralelo 1 Salida
  • LPT2 Puerto paralelo 2 Salida
  • LPT3 Puerto paralelo 3 Salida
  • SCRN Pantalla Salida

3.5. Puertos

BASIC proporciona procedimientos para leer o escribir datos en un puerto. Estos procedimientos son INP y OUT. INP devuelve el valor que se encuentra en el puerto que se especifica como argumento:

INP(puerto%)

donde puerto% es un número entre 0 y 65535 que identifica al puerto. Para enviar información a un puerto se usa OUT, con la sintaxis

OUT puerto%, datos%

donde datos% es un byte que será enviado al puerto puerto%.

3.6. Acceso a memoria.

Las instrucciones PEEK y POKE permiten leer y escribir en posiciones específicas de memoria. Para leer:

PEEK (direccion%)

y para escribir:

POKE direccion%, byte%

donde direccion% es una dirección relativa al segmento actual, definido previamente mediante DEF SEG y byte% es un valor que será escrito en la posición de memoria especificada.

4.- ESTRUCTURA GENERAL DE UN PROGRAMA

BASIC no obliga a escribir los programas con una estructura definida, lo cual, lejos de ser una ventaja, es un inconveniente, como demuestra la experiencia. Por ese motivo, es aconsejable imitar la estructura de un lenguaje fuertemente estructurado, como C. Un programa debe estar constituido por un pequeño bloque de gestión de subprogramas, ocupándose cada uno de ellos de una tarea específica.

4.1. Subprogramas.

Cuando vaya a usarse un subprograma, será necesario declararlo como tal antes del programa principal mediante la sentencia DECLARE:

DECLARE SUB nombre(lista_argumentos)

Desde el programa principal, o desde otro subprograma, un subprograma se llama usando la sentencia CALL:

CALL nombre(lista_argumentos)

El subprograma en sí se escribe entre las sentencias SUB..END SUB:

SUB nombre(argumento1,argumento2...)  
bloque  
END SUB

Por defecto, los argumentos de un subprograma se pasan por dirección, con lo cual, quedan modificados en el programa. Para forzar el paso por valor, de modo que el subprograma opere con una copia de las variables del programa, los argumentos se incluyen entre paréntesis. El siguiente programa, junto con su salida debe ser suficientemente ilustrativo:

DECLARE SUB misub (a%, b%)  
CLS  
a%=23: b%=23  
PRINT a%: PRINT b%  
CALL misub (a%, (b%) )  
PRINT a%: PRINT b%  
pausa$=INPUT$(1)  

SUB misub (a%, b%)  
a%=200: b%=300  
PRINT a%: PRINT b%  
END SUB  

23  
23  
200  
300  
200  
23

4.2. Funciones.

QBASIC proporciona también la posibilidad de definir funciones externas al programa principal. Una función devuelve un único valor, como resultado de un cálculo. Este valor se almacena en una variable especial cuyo nombre es el de la función. Una función se escribe entre FUNCTION y END FUNCTION. En QBASIC, las funciones pueden ser recursivas. El siguiente ejemplo debe ser suficiente:

DECLARE FUNCTION resta(a%, b%)  
CLS  
a% = 34: b% = 20  
PRINT resta (a%, b%)  
pausa$ = INPUT$(1)  

FUNCTION resta(a%, b%)  
resta = a% - b%  
END FUNCTION  

14

4.3. Conclusión.

Con todos estos elementos, podemos estructurar el programa en bloques, escribiéndolos uno a continuación de otro en el orden que se sugiere a continuación:

  • * declaración de procedimientos y funciones
  • * declaración de tipos de variables
  • * dimensionamiento de variables y arrays
  • * asignación de constantes
  • * inicialización de variables
  • * CODIGO DEL BLOQUE PRINCIPAL
  • END
  • * código de las funciones y subprogramas

7900 visitas desde el 17-04-2019