Beruflich Dokumente
Kultur Dokumente
control de flujo, estructuras sencillas y un buen conjunto de operadores. Es un lenguaje que no está
especializado en ningún tipo de aplicación. Esto lo hace un lenguaje versátil y potente, con un
campo de aplicación ilimitado y, sobre todo, se puede aprender rápidamente. En poco tiempo, un
programador puede utilizar la totalidad del lenguaje.
El lenguaje BASIC es, originalmente, un lenguaje interpretado. Existen dos tipos de lenguaje:
interpretados y compilados. Los interpretados son aquellos que necesitan del código fuente para
funcionar (por ejemplo, GW-BASIC y QBasic). Los compilados, convierten el código fuente en un
archivo objeto y éste en un archivo ejecutable. Este es el caso del lenguaje C y de las versiones más
completas y recientes del BASIC.
sistema de TRAducción de
1956 FORTRAN IBM
FORmulas matemáticas
1956 COBOL Compilador
1958 ALGOL 58
Intérprete orientado a la Inteligencia
1960 LISP
Artificial
sistema de TRAducción de
1961 FORTRAN IV IBM
FORmulas matemáticas
1961 COBOL 61 Extendido
1960 ALGOL 60 Revisado
1964 PASCAL Niklaus Wirth programación estructurada
Universidad de
Beginners All Purpose Symbolic
1964 BASIC Dartmouth
Instruction Code
(california)
1
1965 SNOBOL
1965 APL sólo anotación
1965 COBOL 65
1966 PL/I
sistema de TRAducción de
1966 FORTRAN 66 IBM
FORmulas matemáticas
1967 SIMULA 67
1968 ALGOL 68
1968 SNOBOL4
1970s GW-BASIC antiguo y clásico BASIC
1970 APL/360
Centro de
1972 SMALLTALK Investigación de pequeño y rapido
Xerox en Palo Alto
1972 C Laboratorios Bell lenguaje con tipos
1974 COBOL 74
1975 PL /I Lenguaje sencillo
sistema de TRAducción de
1977 FORTRAN 77 IBM
FORmulas matemáticas
1980s SMALLTALK/V Digitalk pequeño y rapido
1980 C con clases Laboratorios Bell lenguaje con clases
Ministerio Japonés
de Comercio Lenguaje estandar para la Inteligencia
1981 PROLOG
Internacional e Artificial
Industria (MITI)
Ministerio de
1982 ADA Defensa de los lenguaje muy seguro
EE.UU
AT&T Bell
1984 C++ Laboratories (Bjarne compilador
Stroustrup)
1985 CLIPPER compilador para bases de datos
1985 QuickBASIC 1.0 Microsoft® compilador de BASIC
1986 QuickBASIC 2.0 Microsoft® soporte de tarjeta gráfica EGA
1987 QuickBASIC 3.0 Microsoft® 43 lineas con la tarjeta EGA
1987 QuickBASIC 4.0 Microsoft® tarjetas Hercules, VGA
1987 CLIPPER SUMMER '87 compilador para bases de datos
1988 QuickBASIC 4.5 Microsoft® tarjeta SVGA
1989 QuickBASIC 7.1 Microsoft® ultima version de QuickBASIC
1989 ASIC v5.0 interprete tipo QBASIC shareware
1990s VISUAL C++
1990s VISUAL BASICScript Microsoft® lenguaje de script
1990 HTML Tim Berners-Lee para internet
para MS-DOS 5.0. Compatible 99.9%
1991 QBasic 1.0 Microsoft®
con QuickBasic
C. M. Sperberg-
1993 XML para internet
McQueen
1993 SGML Charles F. Goldfarb para internet
1993 QBasic 1.1 Microsoft® para MS-DOS 6.0
1990s WML para internet
2
1990s ASP Microsoft® para internet
1990s PHP para internet
1995 JAVA Sun Microsystems para internet y proposito general
1995 CLIPPER 5.01 compilador para bases de datos
Ministerio de
1995 GNAT ADA95 Defensa de los lenguaje muy seguro
EE.UU
sistema de TRAducción de
1995 FORTRAN 95 IBM
FORmulas matemáticas
1991 VISUAL BASIC 1.0 Microsoft®
1992 VISUAL BASIC 2.0 Microsoft®
1993 VISUAL BASIC 3.0 Microsoft®
1994 VISUAL BASIC 4.0 Microsoft®
1995 VISUAL BASIC 5.0 Microsoft®
1998 VISUAL BASIC 6.0 Microsoft®
1990s C#
2001 VISUAL BASIC .NET Microsoft® La evolución de Visual Basic
QuickBasic es un lenguaje de programación de alto nivel, que se puede utilizar de forma compilada.
Tiene varios predecesores. El primero fue BasicA, desarrollado por Microsoft a principios de los
80. Sus características principales:
• los archivos fuente se guardaban en un formato de texto regular, legibles por otros
programas
• la interfaz de programación era ligeramente más amigable
GW-Basic no era todavía demasiado adecuado para un uso masivo, de modo que Microsoft en 1987
crea una actualización de Basic denominada QuickBasic, con las siguientes ventajas:
Microsoft incluyó con el sistema operativo MS-DOS 5.0 una versión reducida de QuickBasic
denominada QBasic 1.0. Esta versión y su actualización posterior, 1.1, se utilizaban sólo de forma
interpretada pero sus posibilidades eran todavía bastante amplias. En lo que resta nos referiremos
específicamente a la implementación de BASIC denominada QBasic por su versatilidad y sencillez
de uso.
3
La mejor forma de aprender un lenguaje es programando con él. El programa más sencillo que se
puede escribir en BASIC es el siguiente:
Como podemos imaginar, este programa sin una sola instrucción no hace nada, pero se interpreta
correctamente y nos da una idea de que no se necesita mucho para empezar a programar en BASIC.
Esto no es cierto en otros lenguajes como C, en los que hay que utilizar obligatoriamente
encabezados de programa y limitadores de bloques de sentencias.
CLS
PRINT "Bienvenido a la programación en lenguaje BASIC"
END
CLS
Esta línea constituye una sentencia. La sentencia consta únicamente de la instrucción CLS , y ésta
produce el resultado de borrar la pantalla.
La siguiente sentencia incluye la instrucción PRINT. Ésta toma como argumento una cadena de
caracteres limitados por dobles comillas " " y la imprime en la salida habitual, que generalmente es
la pantalla del PC en el que trabajamos.
La instrucción END termina el programa. Ni siquiera es obligatorio finalizar con END, aunque es
conveniente por una cuestión de claridad. De cualquier manera, si extraemos esa sentencia, el
programa funcionará exactamente igual (el programa finaliza automáticamente cuando no se
encuentran más líneas de código).
Antes de continuar hagamos un inciso sobre la nomenclatura utilizada en QBasic para designar a
distintos elementos del lenguaje:
4
Elemento Definición
Sentencia Es una instrucción que realiza una operación. Se utilizan estas palabras de forma
Instrucción intercambiable. Se usa mucho la forma comando debido a su utilización en
(Comando) inglés.
Una palabra que forma parte del lenguaje QBasic. Cuando se utiliza una palabra
Palabra clave clave en una sentencia, QBasic automáticamente la convierte a mayúsculas. No
Keyword se puede utilizar una palabra clave para dar nombre a una constante o variable
(palabra reservada).
Cadena Una cadena de texto (caracteres). En Qbasic se delimita con comillas, por
String ejemplo, "Bienvenido". La cadena "" (vacía) es válida.
Designa a números enteros, decimales de precisión simple y decimales de
Número
precisión doble.
Un valor (cadena o número) que no cambia a lo largo de la ejecución del
programa. Hay dos clases de constantes; las constantes literales están escritas
directamente en el código: "Hola", 16; las constantes simbólicas o con nombre
Constante
son valores constantes a los que se les asigna un nombre. Por ejemplo,
LONG_MAX en lugar de 16. Las constantes simbólicas se definen usando la
palabra clave CONST.
Un contenedor con nombre para un número o una cadena. Son el medio para que
Variable el programa "recuerde" datos. Se pueden crear variables de varias maneras:
calculando un valor, tomando una entrada de usuario, leyendo un archivo, etc.
Designa una operación matemática. Los operadores pueden ser aritméticos,
Operador
relacionales o lógicos.
Devuelve una cadena o un número. Puede tomar uno o más parámetros de
Función
entrada para calcular el resultado.
No hace nada en el programa. Se utiliza como una nota explicativa que
Comentario
contribuye a clarificar el código y a recordar más tarde lo que se hizo.
Designa a un conjunto de líneas dentro de la estructura del programa, que
Bloque
guardan una relación de algún tipo entre sí.
Bucle Designa a un grupo de líneas que se ejecutan una serie de veces.
declaración de variables
sentencias
END SUB
FUNCTION Funcion1 ( )
declaración de variables
sentencias
5
END FUNCTION
...
...
...
SUB Subprograman( )
declaración de variables
sentencias
END SUB
FUNCTION Funcionn ( )
declaración de variables
sentencias
END FUNCTION
Cuando la envergadura del programa es grande se suele fragmentar el módulo en varias partes,
incluyendo cada parte en un fichero separado. Normalmente colocaremos en cada fichero todas las
subrutinas y funciones que se encarguen de una tarea del programa. Por tanto, un programa en
QBasic puede estar formado por diferentes módulos o fuentes. Es conveniente mantener los fuentes
de un tamaño no muy grande -para encadenar la ejecución de los diferentes módulos se utiliza la
instrucción CHAIN (CHAIN nombre.archivo$-.
Introducción
Si se deseara imprimir los resultados de multiplicar un número fijo por otro que adopta valores entre
0 y 9, la forma normal de programar esto sería crear una constante para el primer número y un par
de variables para el segundo y para el resultado del producto. Una variable no es más que un
nombre para identificar una (o varias) posiciones de memoria donde el programa guarda los
distintos valores de una misma entidad . En un programa BASIC es conveniente definir todas las
variables que se utilizarán antes de comenzar a usarlas, a fin de indicarle al intérprete o compilador
de que tipo serán y, por tanto, cuánta memoria debe destinar para albergar a cada una de ellas,
aunque en QBasic no es obligatorio. Veamos un ejemplo:
Así, una variable es un lugar donde se puede almacenar temporalmente un dato. En BASIC las
variables tienen un nombre que las identifica, y sirve para hacer referencia a ellas. También tienen
un tipo, que es el tipo de datos que puede almacenar. El valor de las variables es, como su propio
nombre indica, variable. Podemos alterar su valor en cualquier punto del programa.
6
Identificadores, tipos y tamaños
Para dar un nombre a una variable tenemos que usar un identificador. La longitud de un
identificador puede variar entre uno y varios caracteres, por lo general, 40. En la mayoría de los
casos el primer carácter debe ser una letra. A continuación se muestran varios ejemplos de nombres
de identificadores correctos e incorrectos:
Correcto Incorrecto
cuenta 1cuenta
prueba23 prueba*
puerto.paralelo puerto_paralelo
El lenguaje QBasic no es sensible a mayúsculas y minúsculas (no es case sensitive), de modo que
para el intérprete es lo mismo el identificador cuenta que otro denominado Cuenta.
Los intérpretes y compiladores reservan determinados términos ó palabras claves (keywords), para
el uso sintáctico del lenguaje, tales como: CLS, PRINT, END, etc. y no se pueden utilizarla en
nombres de variables.
Para crear una variable en un lugar determinado del un programa escribiremos primero el tipo de
variable y luego el identificador con el que queremos nombrar la variable. A esto se le denomina
definir una variable. La forma general de la definición es:
Por ejemplo:
DIM numero AS INTEGER ' crea la variable numero, de tipo número entero
DIM numero% ' crea la variable numero, de tipo número entero
En QBasic, las variables no se pueden inicializar (es decir, establecer un valor inicial) en el
momento de creación. Por ejemplo, es incorrecto:
La asignación de valores a las variables hay que realizarla posteriormente a la definición de las
mismas.
• cadenas de caracteres
• números enteros
7
• números en coma flotante
Su
Tipo fij Tamaño Intervalo Descripción
o
Las variables string
son las
que almacenan
texto.
Ejemplos: "¿Qué
conjunto de
estás haciendo?",
STRING $ caracteres 0 a 32 767 caracteres
"Alpha Sigma Pi",
(de 8 bits)
"323"
(esto no es un
número porque se
delimita con
comillas).
Las variables
enteras almacenan
números enteros
(sin parte decimal).
INTEGE
R % 16 bits -32 768 a 32 767 Ejemplos: 4323, 1,
-7543, 30000 (
no se utilizan
separadores de
millares).
Almacenan también
enteros.
LONG & 32 bits -2 147 483 648 a 2 147 483 647
Ejemplos: 54500, 0,
123456789.
Las variables de
precisión simple
almacenan números
de coma flotante
3.4 E-38 a 3.4E+38 con 6 dígitos de
SINGLE ! 32 bits
(aprox. 6 dígitos de precisión) precisión.
Ejemplos: 123.456,
12300000000000, .
0000000000000008
.
DOUBLE # 64 bits 1.7 E-308 a 1.7 E+308 Las variables de
(aprox. 12 dígitos de precisión) precisión doble
almacenan números
de coma flotante
con 12 dígitos de
precisión.
Ejemplos:
1000000000000000
0000000000000000
8
000000000000, .
0000000000000004
00005.
END
En Qbasic no es obligatorio definir el tipo de datos de una variable antes de utilizarla, aunque si es
conveniente. De hecho, el programa anterior también funciona así:
END
En este caso es el intérprete el que asigna automáticamente el tipo de los datos a las variables. Esto
facilita bastante la tarea de programar, sobre todo a usuarios inexpertos, aunque no es lo más
eficiente.
La instrucción LET
expresión es una expresión del mismo tipo que la variable - número o string -. No se puede poner
un valor string en una variable numérica y viceversa. La palabra clave LET es opcional. En la
mayor parte de los usos se prescinde de LET y de deja sólo variable = expresión (es más claro
9
y sencillo). Si se intenta poner un valor decimal en una variable entera el valor se redondea. Se
pueden poner valores enteros en variables Single y Double.
Ejemplos:
Otra característica de las variables es su alcance. El alcance se refiere a los lugares de un programa
en los que podemos utilizar una determinada variable. Distinguiremos así dos tipos principales de
variables:
• globales
• locales
Una variable es global cuando es accesible desde todo el programa, y es local cuando solo puede
acceder a ella la función que la creó.
Muestra Muestra
END END
SUB Muestra SUB Muestra
PRINT x1% PRINT x2%
END SUB END SUB
100
La palabra clave SHARED consigue que la variable x1 sea global, es decir, accesible en todo el
código (todos los subprogramas) del módulo. Por el contrario, x2 es local y sólo se conserva su
valor en el programa principal, no siendo accesible desde los subprogramas.
Otro ejemplo:
10
' Muestra un número entero ' Muestra un número entero
Valor Valor
PRINT x1% PRINT x2%
END END
SUB Valor SUB Valor
SHARED x1% ' Aquí sólo se escribe SHARED, DIM x2%
' no DIM SHARED PRINT x2%
x1% = 100 END SUB
END SUB
100
Unas de las principales vías de comunicación de un programa con el usuario son la pantalla
(terminal) y el teclado. La entrada y salida de datos por estos medios se pueden realizar mediante
varias instrucciones de QBasic. Las fundamentales son:
• PRINT
• INPUT
• PRINT USING
• LINE INPUT
• LOCATE
• CLS
La función PRINT escribe texto y/o números en la pantalla (aunque también en un archivo). Su uso
en sencillo, sólo hay que añadir detrás de la palabra clave la lista de datos que se desea visualizar.
Por ejemplo:
PRINT "Hola"
PRINT "mundo"
11
END
El resultado es:
Hola
mundo
Nótese que PRINT imprime un salto de línea tras el texto. Se puede inhibir el salto automático de
línea si se añade ; tras el texto:
PRINT "Hola";
PRINT "mundo"
END
Hola mundo
a% = 50
b% = 100
END
Nótese que al concatenar el texto con los números mediante ; se añade automáticamente un espacio
en blanco antes de cada valor numérico.
a% = 50
b% = 100
END
el resultado es:
12
El valor de a es 50 y el valor de b es 100
Algo muy usual en un programa es esperar que el usuario introduzca datos por el teclado. Para ello
contamos con la instrucción INPUT. Un ejemplo:
Introduce un número? 23
Has tecleado el número 23
De esta forma, cuando el usuario ejecuta el programa debe introducir los tres datos separados por
una coma y finalizar con un retorno de carro.
Es muy común escribir un mensaje con PRINT antes de realizar un INPUT, como en los dos
ejemplos anteriores. Pero INPUT facilita la labor si se utiliza así:
13
END
Introduce un número: 23
Has tecleado el número 23
DIM palabra AS STRING*5 ' Define palabra como una cadena de texto
' de una longitud máxima de 6 caracteres
...
...
PRINT USING
Esta instrucción es similar a PRINT pero es capaz de dar un formato especificado de salida a los
datos. La sintaxis de uso es:
donde formato es una cadena de texto que contiene distintos especificadores que aplican formato a
la lista_de_expresiones. Esta lista no es más que un conjunto de expresiones numéricas o de
texto concatenadas con ; o ,.
14
# Posición de dígito. ¦ - Después del
dígito, imprime
. Posición de punto decimal. ¦ el signo para
los números
, A la izquierda del punto decimal, ¦ negativos.
imprime una coma cada 3 dígitos. ¦ $$ Imprime $
adelante.
+ Posición del signo de número. ¦ ** Llena espacios
adelante con *
^^^^ Imprime con formato exponencial. ¦ **$ Combina ** y $$.
Caracteres que dan formato a una expresión de texto
& Imprime la cadena completa. ¦ \ \ Imprime los
primeros n
! Imprime sólo el primer carácter ¦ caracteres,
donde n es el
de la cadena. ¦ número de
espacios entre
Caracteres utilizados para imprimir caracteres literales
_ Imprime el carácter de formato ¦ Cualquier
carácter que no
siguiente como literal. ¦ esté en la tabla
será
¦ impreso como
literal.
PRINT
PRINT "Producto Cantidad Importe Importe Total"
PRINT "-------- -------- --------- -------------"
15
LINE INPUT
Esta instrucción es sumamente similar a INPUT, si bien almacena en una sola variable toda la
entrada proporcionada desde teclado hasta encontrar un retorno de carro y no considera las comas
(,) separadores de variables (como sucedía con INPUT).
Por ejemplo:
Hemos visto que cuando usamos PRINT se escribe en la posición actual del cursor y se mueve éste
al final de la cadena que hemos escrito. Pero ¿qué sucede cuando queremos escribir en una posición
determinada de la pantalla?. La solución está en la función LOCATE. Supongamos que queremos
escribir 'Hola' en la fila 20, columna 10 de la pantalla:
LOCATE 20, 10
PRINT "Hola"
END
Obsérvese que primero se indica la fila (y) y luego la columna (x). La esquina superior izquierda es
la posición (1, 1).
CLS
16
Ahora ya sólo resta saber cómo se limpia la pantalla. Ello es tan fácil como usar:
CLS
Esta función no sólo borra la pantalla, sino que sitúa el cursor en la posición (1, 1), en la esquina
superior izquierda.
CLS
PRINT "Hola"
END
Introducción
Los subprogramas y funciones son rutinas, procedimientos o conjuntos de sentencias que realizan
una labor específica. Los subprogramas o subrutinas nacieron de la necesidad de no repetir
innecesariamente un trabajo ya hecho. Pueden invocarse desde el cuerpo del programa principal
cuantas veces se desee. Están en el núcleo de lo que se denomina programación estructurada.
Los subprogramas y las funciones admiten parámetros (argumentos), que son datos que le pasan al
procedimiento las sentencias que la llaman.
donde:
hola
END
END SUB
que simplemente es una función que cuando es llamada imprime en pantalla un mensaje de saludo.
Cuando el programa al ejecutarse alcanza el cierre del procedimiento (END SUB), éste finaliza y
devuelve el control al punto del programa que lo llamó.
nombre_de_la_función = expresión
bloque_de_código
END FUNCTION
donde:
El tipo es opcional. La lista de argumentos es también opcional. Podemos escribir como ejemplo:
' Función que suma dos enteros y devuelve la suma como otro entero
FUNCTION Suma% (s1%, s2%)
END FUNCTION
Cuando el programa al ejecutarse alcanza el cierre del procedimiento (END FUNCTION), éste finaliza
y devuelve un valor de tipo entero al programa que lo llamó.
Retorno de valores
18
Cuando la función finaliza hemos dicho que se devuelve un valor. Para obligar a la función a
retornar un determinado valor se utiliza la sentencia
nombre_de_la_función = expresión
FUNCTION lista%
lista% = 1
END FUNCTION
devuelve el entero 1 cada vez que es llamada. En QBasic podemos devolver cualquier tipo de datos
de los llamados escalares. Los tipos de datos escalares son los tipos numéricos y el tipo string. En
QBASIC no se pueden devolver vectores (array).
Utilizando la lista de argumentos podemos pasar parámetros a una función. En esta lista se suele
colocar un conjunto de identificadores, separados por comas, que representan cada uno de ellos a
uno de los parámetros de la función. Obsérvese que el orden de los parámetros es importante. Para
llamar a la función habrá que colocar los parámetros en el orden en que la función los espera.
Cada parámetro puede tener un tipo diferente. Para declarar el tipo de los parámetros añadiremos su
tipo tras el identificador. Así:
END SUB
es una función que admite dos variables, una entera y otra de tipo cadena.
En los lenguajes de programación estructurada hay dos formas de pasar variables a una función:
• por referencia, o
• por valor
Cuando la variable se pasa por referencia, la función puede acceder a la variable original. Este
enfoque es habitual en lenguajes como el BASIC. (En C, sin embargo, todos los parámetros se
pasan por valor. La función recibe una copia de los parámetros y variables, y no puede acceder a las
variables originales. Cualquier modificación que efectuemos sobre un parámetro no se refleja en la
variable original. Esto hace que no podamos alterar el valor de la variable por equivocación.)
CLS
PRINT n%
imprime n%, l$
PRINT n%
END
numero% = 2
END SUB
da como resultado:
1
2 A
2
Es decir, la variable n, que originalmente valía 1, toma el valor 2 tras la llamada al procedimiento
imprime.
Al igual que para las variables, cuando un procedimiento (función o subprograma) se va a usar en
un programa, o cuando un procedimiento se define en otro fichero (procedimiento externo), se debe
declarar antes del lugar donde se define. La declaración de un procedimiento consiste en especificar
el tipo de datos que va a retornar, cuando se trata de una función, y el número de argumentos y su
tipo. Una declaración típica de función es:
La lista de parámetros con tipo difiere de la lista de argumentos antes presentada en que el tipo de
cada argumento se coloca dentro de la lista, tras de su correspondiente identificador, como
hacíamos en la definición de variables. Por ejemplo:
declara una función que devuelve un carácter y tiene dos parámetros, un entero y un carácter.
NOTA:
DECLARE es requerido si se hace una llamada a un procedimiento FUNCTION o a uno SUB sin CALL
20
(véanse los ejemplos). QBasic generara automáticamente instrucciones DECLARE cuando se
guarda un programa.
' Ejemplo
DIM caracter AS STRING
CLS
imprime$ = letra
END FUNCTION
Ejemplos
Este programa llama a la función BorraPantalla que despeja la pantalla mediante la orden CLS
(clear screen) y muestra el mensaje "la pantalla está limpia". Por supuesto, es de nula utilidad pero
sirve para empezar.
SUB BorraPantalla
CLS
PRINT "La pantalla está limpia"
END SUB
compara num1, num2 ' Llamamos al subprogramas con sus dos argumentos
' También podríamos escribir: CALL compara(num1,
num2)
END
IF a > b THEN
PRINT a; " es mayor que "; b
ELSE
PRINT b; " es mayor que "; a
END IF
END SUB
Este ejemplo es como el anterior pero devuelve como resultado el mayor de los dos números.
END
IF a > b THEN
compara% = a
ELSE
compara% = b
END IF
END FUNCTION
De esta forma nos hubiésemos ahorrado tener que definir la variable resultado.
22
Introducción
Las expresiones son sentencias que tras realizar una determinada acción devuelven un resultado.
Consideraremos a continuación dos tipos fundamentales de expresiones:
• la asignación
• las que utilizan operadores
Asignación
El primer tipo a considerar dada su importancia es la asignación. La sintaxis de una asignación es:
expresión es una expresión del mismo tipo que la variable -- número o string. No se puede poner un
valor string en una variable numérica y viceversa. La palabra clave LET es opcional. En la mayor
parte de los usos se prescinde de LET y de deja sólo variable = expresión (es más claro y
sencillo). Si se intenta poner un valor decimal en una variable entera el valor se redondea. Se
pueden poner valores enteros en variables Single y Double.
Ejemplos:
Operadores
El segundo tipo de expresiones son los operadores. Hay varios tipos de operadores:
• aritméticos
• relacionales y lógicos
• de manipulación de bits
Operadores aritméticos
Los cuales realizan las operaciones aritméticas básicas. Estas expresiones tienen como sintaxis:
23
+ adición, operador de suma
- substracción, operador de diferencia
* multiplicación
/ división
\ división entera (redondea la división al entero inferior más próximo)
MOD resto de la división (operador módulo)
Por ejemplo:
i% = a% + 1
j = b * 4 + 10 / 2
AND Y
OR O
NOT NO
Por ejemplo:
Por supuesto, expresión1 y expresión 2 pueden contener variables, no sólo valores literales.
24
Operadores de manipulación de bits
Los operadores Booleanos realizan un manejo de bits, es decir, operaciones Booleanas. Generan un
valor verdadero (no cero) o falso (cero) que puede ser utilizado al tomar una decisión.
Para el manejo de dichos bits, contamos con los operadores descritos en la siguiente tabla .
Estos operadores general los resultados esquematizados en la tabla siguiente ( V es verdadero -no
cero- y F es falso -cero-):
expresión expresión
AND OR XOR NOT EQV IMP
1 2
V V V V F V V V
F F F V V F F F
V V F V V F F V
F F F F F F V V
Las operaciones Booleanas se realizan después de las operaciones de las aritméticas y relacionales,
en el orden de precedencia.
Como los operadores Booleanos realizan cálculos bit a bit, el uso de valores que no sean 0 para
falso y -1 para verdadero puede producir resultados inesperados.
Estos operadores muestran manipulan internamente, es decir bit a bit , las variables. Estos
operadores sólo se aplican a expresiones de tipo entero o entero largo, de modo que las expresiones
se convierten en enteros antes de realizar una operación booleana.
Describiremos mediante unos pocos ejemplos la operatoria de manejo de bits. Analicemos primero
como funciona el operador ANDSi suponemos tener dos variables del tipo char, una de ella de valor
85 (hex. 55 ), otra de valor 71 (hex. 47) y realizamos el Y a nivel bits de ellas, obtendremos :
Nótese que la operación es del tipo lógico entre bits, por lo que los resultados numéricos tienen
poco ó ningún significado y sólo se han puesto con fines de ejemplo.
De la misma manera para la operación OR (O inclusiva), para las mismas variables anteriores
obtendremos el resultado:
0 1 0 1 0 1 1 1 87 57
25
Analizando ahora la XOR (O exclusiva) tendremos, para las mismas variables anteriores:
0 0 0 1 0 0 1 0 18 12
Introducción
En Qbasic las sentencias se ejecutan sucesivamente una tras otra (secuencialmente). Esto define un
camino o dirección según la cual se va desarrollado el programa. Sin embargo, habrá momentos en
que el programa deba ejecutar determinadas partes dependiendo del estado en el que se halle el
propio programa o las variables externas. Esto permitir modificar el orden de la ejecución para
adaptarse al estado del programa y bifurcar hacia nuevas subrutinas cuando se cumplan ciertas
condiciones, que el programador fija de antemano. Los mecanismos en QBasic que permiten llevar
esto a cabo son:
• la instrucción IF
• el bucle WHILE
• el bucle DO - WHILE
• el bucle FOR
• la instrucción EXIT
• la selección múltiple SELECT CASE
La instrucción IF
o también:
IF expresión THEN
[bloque_sentencias_1]
[ELSEIF expresion_2 THEN
[bloque_sentencias_2]]...
ELSE
[bloque_sentencias_n]
END IF
Esta sentencia es equivalente a la que poseen la mayoría de lenguajes de programación y sirve para
bifurcar en un punto de programa. Permite al programa tomar decisiones. En su primera forma, la
sentencia_1 sólo se ejecuta si el resultado de evaluar la expresión es verdadero (no cero); en
caso contrario, se ejecuta sentencia_2. En la segunda forma, tenemos varias posibilidades: si al
evaluar la expresión el resultado es verdadero se ejecutan las instrucciones bloque_sentencias_1,
pero si el resultado es falso se evalúa la expresión_2 y si ésta es verdadera se ejecuta
bloque_sentencias_2, y así sucesivamente. En cualquier caso sólo una de los bloques de
sentencias se ejecuta.
26
IF num% = 1 THEN PRINT "la variable num vale 1" ELSE PRINT "la
variable num no vale 1"
Tras evaluarse la expresión IF y ejecutarse la sentencia adecuada, el programa continúa con la línea
siguiente a la de la última sentencia del IF. Para la sentencia IF vale como expresión cualquiera
válida en QBasic, incluso las llamadas a funciones:
Como sentencias valen cualquier tipo de sentencia válida en QBasic, entre ellas la propia sentencia
IF. En este caso hablaremos de sentencias IF anidadas. Por ejemplo:
En este caso, si la variable num es menor o igual que cero el programa no mostrará ningún mensaje,
y en caso contrario se mostrará el mensaje correspondiente a la comparación del valor con la
unidad.
El bucle WHILE
Un bucle es un conjunto de sentencias que se ejecutan repetidamente hasta que se alcanza una
condición de fin de bucle, o condición de salida. El bucle while es el tipo de bucle más sencillo. En
su modo más simple se escribe:
WHILE expresión
bloque_sentencias
WEND
variable% = 10
variable% = variable% -1
27
WEND
En este caso se imprime el valor de la variable hasta que se llega a 1. Normalmente, en las
sentencias del bucle WHILE se coloca alguna instrucción que modifique la expresión de control,
como vemos en el ejemplo anterior.
El bucle DO - WHILE
o también:
DO
bloque_sentencias
LOOP [{WHILE | UNTIL} expresión]
Su funcionamiento es análogo el del bucle WHILE, salvo que la expresión de control se puede
evaluar al final del bucle (si se utiliza la segunda opción de sintaxis). Esto nos garantiza que el
bucle DO_WHILE se ejecuta al menos una vez. Incluye también la posibilidad de ejecutar el bucle
mientras (WHILE) expresión sea verdadera o hasta (UNTIL) que expresión sea verdadera.
Por ejemplo:
n% = 9
DO
PRINT "número actual "; n%
n% = n% -1
LOOP WHILE n% >= 0
este programa muestra el valor de n hasta que vale 0. Y el siguiente produce el mismo resultado.
n% = 9
DO
PRINT "número actual "; n%
n% = n% -1
LOOP UNTIL n% = -1
El bucle FOR
28
La sintaxis del bucle FOR es:
Este bucle se utiliza para realizar un conjunto de acciones un número determinado de veces.Su
versión más sencilla es:
FOR i% = 0 TO 10
PRINT "i vale "; i%
NEXT i%
Esta versión del bucle imprime el valor de i desde 0 con un incremento de una unidad mientras que
esta variable no alcance el valor 10.
FOR i% = 1 TO 10 STEP 2
PRINT "i vale "; i%
NEXT
contador = inicio
WHILE contador <= fin
bloque_sentencias
contador = contador + incremento
WEND
Este bucle WHILE puede servirnos para salir fácilmente de dudas al escribir un bucle FOR, ya que se
ve claramente el orden de ejecución de las expresiones y sentencias dentro del bucle FOR. Como se
ve, en cada pasada del bucle FOR se sigue el orden: evaluación del valor del contador, ejecución de
bloque_sentencias y e incremento del contador.
Hay veces en que interesa romper un bucle en una determinada posición, para finalizar su
ejecución. Esto suele ser habitual cuando el bucle tiene una gran complicación o cuando
necesitamos salir "por las malas" de él. Esto último suele ser frecuente cuando en el bucle se
producen "condiciones de error". Para este tipo de salto disponemos de la sentencia EXIT.
Su sintaxis es:
29
a% = 10
DO WHILE 1
PRINT a%
IF a% <= 1 THEN EXIT DO
a% = a% -1
LOOP
Aunque en apariencia este es un bucle sin fin, ya que la condición WHILE 1 es siempre cierta, este
bucle se acaba cuando la variable a valga 1. El bucle simplemente imprime su valor y decrementa la
variable.
Otro ejemplo:
FOR i% = 1 TO 10
PRINT i%
INPUT a$
IF a$ = "S" THEN EXIT FOR
NEXT
el cual imprime enteros entre 1 y 10 hasta que se introduce por teclado la la pulsación S.
EXIT también se utiliza con procedimientos SUB o FUNCTION, para abandonar el procedimiento antes
de ejecutar todas las sentencias que preceden al correspondiente END {SUB | FUNCTION}.
Esta sentencia sirve para agrupar varias sentencias IF en una sola, en el caso particular en el que
una variable es comparada a diferentes valores, todos ellos constantes, y que realiza acciones si
coincide con ellos. Su sintaxis es:
Su sintaxis es más complicada que la de anteriores bucles, ya que agrupa un mayor número de
acciones y posibilidades en una sola sentencia. El modo de funcionamiento es el siguiente:
IF num = 1 THEN
PRINT "Es un 1"
ELSEIF num = 2 THEN
PRINT "Es un 2"
ELSEIF num = 3 THEN
PRINT "Es un 3"
ELSE
PRINT "No es ni 1, ni 2, ni 3"
END IF
END
Introducción
"Un conjunto de datos del mismo tipo, identificados por el mismo nombre, y que se pueden
distinguir mediante un número de índice."
Pero ¿qué quiere decir esto y para qué lo queremos?. Pues bien, supongamos que queremos
almacenar la temperatura media de cada hora del día y la temperatura promedio del día. Con lo que
sabemos hasta ahora podríamos hacer algo así:
Los puntos ... se utilizan por brevedad en el ejemplo; no constituyen una expresión válida en QBasic.
Observamos que hay que realizar un notable trabajo repetitivo de escritura de código. Precisamente
es aquí donde son de utilidad los arrays. Vamos a repetir el programa anterior con un array:
El programa resulta más rápido de escribir y más cómodo para el usuario que el anterior.
Como ya hemos comentado, cuando declaramos una variable lo que estamos haciendo es reservar
una zona de la memoria para ella. Cuando declaramos el array de este ejemplo reservamos espacio
en memoria para 24 variables de tipo SINGLE. El tamaño del array (24) lo indicamos entre
paréntesis al definirlo. Esta es la parte de la definición que dice: Un array es un conjunto de datos
del mismo tipo identificados por el mismo nombre.
32
La parte final de la definición dice: y se distinguen mediante el índice. En el ejemplo recorremos la
matriz mediante un bucle FOR y vamos dando valores a los distintos elementos de la matriz. Para
indicar a qué elemento nos referimos usamos un número entre paréntesis (en este caso la variable
hora), este número es lo que se llama índice del array.
En el ejemplo anterior el primer elemento de una matriz tiene el índice 0, el segundo tiene el 1, y así
sucesivamente. De modo que si queremos dar un valor al elemento 4 (índice 3) haremos:
temp!(3) = 20
No hay que confundirse. En la declaración del array el número entre corchetes es el número total de
elementos; en cambio, cuando usamos la matriz, el número entre corchetes es el índice.
Declaración de un array
donde:
Como se ha indicado antes, al declarar un array reservamos en memoria tantas variables del
tipo_de_dato como las indicada en dimensión.
dimensión también se puede especificar dando los límites superior e inferior de los subíndices del
array:
DIM temp(0 TO 23) AS SINGLE ' Con esto declaramos las 24 variables
Inicialización de un array
En QBasic se inicializan los arrays al asignar valores a cada elemento de los mismos. Es decir, por
ejemplo:
33
temp!(9) = 20
temp!(12) = 25
temp!(20) = 23
Ahora el elemento 10, es decir, temp!(9), valdrá 20. El elemento 13 valdrá 25, y el elemento 21
valdrá 23. El resto, si no se asignan, tomarán valor 0 por defecto. Por ejemplo, el programa:
temp!(9) = 20
temp!(12) = 25
temp!(20) = 23
FOR hora% = 0 TO 23
PRINT "La temperatura a las";hora%;" era de"; temp!(hora
%);"grados."
NEXT hora%
Vemos que los elementos a los que no se ha asignado valor inicial son nulos
En las secciones anteriores veíamos ejemplos de matrices con una sola dimensión (un sólo índice o
subíndice). Pero las matrices pueden contar con más dimensiones. La utilización de matrices
multidimensionales no es más que la extensión natural de la correspondiente a unidimensionales.
Supongamos que deseamos controlar mensualmente las temperaturas registradas durante todo un
mes. Podemos definir una matriz que dependa de dos índices: el día del mes y la hora del día. Por
ejemplo:
34
PRINT "Introduzca la temperatura del día";dia%;"a las";
hora%; "horas: ";
INPUT "", temp!(dia%,hora%)
DIM matriz(dimension1,dimension2)
o también:
Y para acceder al elemento caracterizado por los subíndices i,j de la matriz no hay más que
escribir la expresión matriz(i,j).
En QBasic podemos pasar un array entero a una función. Lo que tenemos que hacer es poner como
argumento de la función el identificador del array seguido de () para que se reconozca como tal.
Considérese este ejemplo:
DECLARE FUNCTION sumar% (m() AS INTEGER) ' Declara la función cuyo argumento
es una matriz
FOR contador% = 1 TO 10
matriz(contador%) = 2*contador% ' Asigna valores a
los elementos
PRINT contador%, matriz(contador%)
NEXT contador%
PRINT "La suma es "; sumar(matriz())
END
suma% = 0
FOR i% = 0 TO 10
suma% = suma% + m(i%)
NEXT i%
sumar = suma%
END
35
Este programa muestra los 10 elementos de un array y halla su suma. Obsérvese que en el
argumento de la función sumar se especifica el array pero sin dimensiones, para que tome la
dimensión del array utilizado en la llamada al procedimiento en el programa principal.
Los archivos o ficheros brindan una forma de guardar permanentemente los datos y resultados de
nuestros programas.
Es importante indicar que los ficheros no son únicamente los archivos que guardamos en el disco
duro. En QBasic algunos dispositivos del ordenador (como el puerto serie de comunicaciones) se
tratan como ficheros.
Para comenzar, vamos a analizar un ejemplo que lee un fichero de texto (origen.txt) y muestra su
contenido en la pantalla:
Ahora es preciso abrir el fichero. Para ello usamos la función OPEN. Esta sentencia tiene el siguiente
formato:
36
OPEN nombre_archivo$ [FOR modo] AS [#]nº_archivo%
En el ejemplo usábamos:
El nombre de fichero se puede indicar directamente (como en el ejemplo) o usando una variable y
se puede abrir de diversas formas. Esto se especifica con el parámetro modo. Los modos posibles
son:
INPUT
especifica que el archivo va a ser abierto para leer información
de forma secuencial.
OUTPUT
especifica que el archivo va a ser abierto para escribir información de
forma secuencial.
RANDOM
especifica que el archivo va a ser abierto en el modo de acceso
aleatorio. RANDOM es el modo de archivo predeterminado.
especifica que el archivo va a ser abierto para añadir información de
APPEND salida secuencial y coloca el puntero de archivo al final del archivo. Una
instrucción PRINT # o WRITE # añade la información al archivo.
especifica el modo de archivo binario. En este modo, es posible
BINARY leer o escribir información en cualquier posición de byte del archivo
usando instrucciones GET o PUT.
nº_archivo es un identificador que permite distinguir los distintos ficheros que se utilizan, cuando
se usan varios simultáneamente.
Ahora ya podemos empezar a leer el fichero. Para ello podemos utilizar la función LINE NPUT #,
que lee las líneas de texto del archivo de una en una. Se puede usar también la función INPUT # que
lee texto del archivo hasta que encuentra una coma (,).
donde linea es una variable string. Tomamos una línea de fichero, la almacenamos en linea y el
puntero del fichero se coloca al principio de la línea siguiente.
37
Cuando entramos en el bucle WHILE, la lectura se realiza hasta que se encuentre el final del fichero.
La detección del final del fichero se puede llevar a cabo con la función EOF().
EOF(nº_archivo)
Esta función comprueba si se ha llegado al final de nº_archivo, en cuyo caso devuelve un valor
verdadero (no 0). Si no se ha llegado al final de fichero devuelve falso (0). Por eso lo usamos del
siguiente modo:
DO UNTIL EOF(1)
Una vez realizadas todas las operaciones deseadas sobre el fichero hay que cerrarlo. Es importante
no olvidar este paso pues el fichero podría corromperse. Al cerrarlo se vacían los buffers y se
guarda el fichero en disco. Un fichero se cierra mediante la instrucción CLOSE. Esta función tiene el
siguiente formato:
CLOSE [#]nº_archivo
Aquí nº_archivo es el identificador del archivo indicado en OPEN cuando el archivo se abrió:
CLOSE #1
Esta función es muy útil para leer caracteres un nº de caracteres determinado del archivo. Su
formato es:
INPUT(nº_caracteres, [#]nº_archivo)
Esta función lee desde el fichero nº_archivo el número de bytes especificado por
nº_caracteres.
Vamos a completar ahora la parte que faltaba en la sección anterior: escribir en un fichero. Vamos a
hacerlo de nuevo mediante un ejemplo. En éste, abrimos un fichero origen.txt y lo copiamos en
otro destino.txt. Además, el fichero se muestra en pantalla (las partes nuevas se han destacado en
negrita).
CLOSE #1, #2
END
Como en el caso de la lectura de archivos, analizaremos este ejemplo poco a poco deteniéndonos
en:
39
El siguiente paso, como antes, es abrir el fichero usando OPEN. La diferencia es que ahora tenemos
que abrirlo en modo escritura. Usamos el modo OUTPUT (crea el fichero, o lo vacía si existe) porque
queremos crear un fichero:
Como se puede observar en el ejemplo, la lectura del fichero se hace igual que antes, con LINE
INPUT #. Para la escritura usamos la función PRINT , cuya sintaxis es:
De esta forma vamos escribiendo en el fichero destino.txt el contenido del fichero origen.txt.
(nótese el ; final) en el archivo destino.txt las líneas del archivo origen aparecerían concatenadas
(es decir, no se producirían saltos de línea)
Como siempre que leemos datos de un fichero debemos comprobar si hemos llegado al final. Sólo
debemos comprobar si estamos al final del fichero que leemos. No tenemos que comprobar el final
del fichero en el que escribimos puesto que lo estamos creando y aún no tiene final.
Y, por fin, lo que nunca debemos olvidar al trabajar con ficheros: cerrarlos. Debemos cerrar tanto
los ficheros que leemos como aquellos sobre los que escribimos.
CLOSE #1, #2
40
Otras funciones para el manejo de ficheros
• WRITE #
• GET y PUT
• Posicionamiento en el archivo: SEEK
WRITE
Sin embargo, WRITE inserta comas (,) entre los datos y comillas (") alrededor de cadenas de texto.
Para notar la diferencia considérese el siguiente ejemplo:
CLOSE #1
1 2 Tecnología
1,2,"Tecnología"
GET y PUT
GET lee información de un archivo colocándola en un buffer de acceso aleatorio o en una variable.
PUT escribe una variable o un buffer de acceso aleatorio en un archivo.
La sintaxis es:
GET [#]numarchivo%[,[numregistro&][,variable]]
PUT [#]numarchivo%[,[numregistro&][,variable]]
41
variable generalmente tiene el tipo de datos definido por el usuario.
Por ejemplo:
Supongamos que queremos posicionarnos en un byte concreto de un archivo para leer o escribir en
dicha posición. La función LOC devuelve la posición actual del puntero del archivo identificado por
nº_archivo. Su sintaxis es:
LOC(nº_archivo%)
La instrucción SEEK establece la posición del archivo para la siguiente acción de lectura o escritura:
FOR i% = 1 TO 10
PUT #1, , i%
NEXT i%
42
SEEK #1, 2 ' Se posiciona en el segundo registro
GET #1, , i% ' Lee el registro donde se halla posicionado
PRINT "Datos: "; i%; " Registro actual: "; LOC(1)
Este programa escribe secuencialmente 10 registros con los enteros entre 1 y 10, se posiciona en el
segundo registro y lo lee; proporciona la salida:
Introducción
Para intercambiar información con dispositivos exteriores, el computador utiliza los puertos de
entrada y salida (E/S). Estos puertos se caracterizan por la dirección que tienen asignada en el mapa
de memoria, y es posible la comunicación con los mismos enviando o recogiendo bytes a/en dicha
dirección. Así, nos centraremos ahora en las funciones de acceso a los puertos hardware que
proporciona Qbasic.
Para recoger información procedente de un puerto hardware (lectura del puerto), Qbasic
proporciona la funciñon INP. Esta función devuelve un byte leído del puerto (hardware) de E/S.
valor% = INP(puerto_dir)
donde:
43
puerto_dir es la dirección (valor entero: 0-65.535) que identifica el puerto hardware de la cual se
quiere leer y valor% y es una variable entera en la que se almacena el byte leído (0-255).
En el siguiente ejemplo vamos a obtener un byte del puerto paralelo (bidireccional) instalado en el
PC (en la dirección de E/S 378h):%
valor = INP(puerto)
PRINT "El byte leído del puerto "; puerto; " es "; valor
END
Escritura en el puerto
donde:
• puerto_dir es la dirección del puerto hardware en la cual se quiere escribir (un entero: 0-
65.535);
• valor es el byte (0-255) que se envía al puerto.
En el siguiente ejemplo vamos a enviar la letra C al primer puerto paralelo bidireccional instalado en
el PC (en la dirección de E/S 378h):
Acceso a la memoria
• Lectura de la memoria
• Escritura en la memoria
44
Lectura de la memoria
Para leer la información almacenada en la memoria, QBasic proporciona la función PEEK. Ésta
devuelve el valor de byte almacenado en la posición de memoria designada por segmento:offset
(direccionamiento segmentado de la memoria).
valor% = PEEK(dirección%)
donde:
NOTA: DEF SEG establece el segmento de memoria sobre el que se realizará la operación de lectura
(un valor entre 0 y 65.535). Por ejemplo DEF SEG = 0.
Como ejemplo, veamos cómo se determina cuántos puertos paralelo se hallan instalados en un PC,
y qué direcciones de E/S tienen asignadas. Para ello, es preciso leer en la posición de memoria 408h
una tabla de 3 palabras de 16 bits (2 bytes) que contienen las direcciones de los puertos paralelo
presentes en el sistema:
NEXT puerto%
END
Escritura en la memoria
donde:
Como ejemplo, veamos cómo se fuerza por software la activación de "Bloq Mayús". Para ello hay
que cambiar el bit 6 de la posición 417h, lugar de las variables de la BIOS donde residen los
banderines de estado del teclado:
DEF SEG = 0
Trataremos de dar unas breves indicaciones acerca de cuál es la forma más correcta de programar.
Qué aspecto dar al código fuente para que sea más legible y elegante, cómo distribuir el código
fuente, etc
Parece claro que la segunda es más conveniente. Desde luego no es la única forma, ni la más
correcta; es, simplemente, un estilo. Cada uno tiene su estilo personal, aunque conviene que
tampoco sea 'muy personal', si es para compartirlo. El tabular la escritura del código lo hace más
legible y fácil de mantener.
46
Los comentarios
El código fuente debe estar bien documentado, de tal forma que si se lo pasamos a otra persona
pueda entenderlo sin grandes dificultades. Quizá se piense: "mi código es mío y nunca se lo voy a
dejar a nadie, así que para que voy a comentarlo". Parece lógico, pero imagínese que se abandona
temporalmente y en el futuro se quiere retocar el programa. Es muy probable el olvido de por qué se
hizo tal o cual cosa, (pasa muy a menudo) y es preciso gastar un montón de tiempo descifrando algo
que en su día estaba entendido perfectamente.
PRINT "Introduce una cadena: " ' Imprimo el mensaje 'Introduce una
cadena'
INPUT "", cadena ' Pregunto por el valor de cadena
Estos comentarios están bien si el código forma parte de algún curso, pero no de un programa de
uso habitual. Todo el mundo (que lleva un poco de tiempo programando en BASIC) sabe que con
FOR se realiza un bucle repetitivo y que con END se finaliza el programa.
Los comentarios deben decirnos qué es lo que hace el programa, para qué sirven las variables y
explicar las partes críticas o confusas del programas. Algo mas correcto sería:
' EJEMPLO.BAS
' Programa ejemplo creado para el curso de BASIC (QBasic 1.1)
' Víctor R. González, 2/02/2002
END
47
Este programa es tan sencillo que no tiene puntos oscuros para comentar.
Es importante indicar para qué se van a usar las variables. Cuando tengamos muchas y pase el
tiempo es difícil descifrar para que era cada una.
Cuando hacemos un programa con prisas o por no pensar mucho damos a las variables cualquier
nombre. Supongamos un programa con una sección de declaración de variables como la que sigue:
¿Cómo podemos acordarnos al cabo de un tiempo de qué era cada variable?. Por eso es conveniente
que aparte de indicar para qué sirve cada variable les demos nombres descriptivos:
48