DIM: TODO SOBRE MATRICES Este texto reune todas mis notas sobre la sentencia DIM y las instrucciones relacionadas con la misma, ya sea existentes en otros BASICs o en el Basic Sinclair, asi como sus equivalentes y diferencias en el ZX SPECTRUM. I - MATRICES NUMERICAS Para empezar: Un arreglo es una estructura de datos o coleccion de elementos del mismo tipo. Su dimensión o tamaño es el número de casillas donde se almacenan sus diversos elementos. 1) Listas y tablas Una lista es un arreglo unidimensional representado mediante una variable numérica o de cadena. Una tabla es un arreglo numérico o alfanumérico de varias dimensiones, siendo las más usadas las de 2 y 3 dims. Los elementos de una lista o tabla se denominan variables con subindice. Sentencias BASIC asociadas a matrices: DIM, ERASE, OPTION BASE. DIM es la sentencia que el BASIC usa para crear ya sea listas o tablas, estableciendo el número maximo de elementos que la conformaran. En practicamente todas las versiones de Basic se acepta la sintaxis: DIM var[$](dim1,dim2,...), var2[$](...,...), var3...., etc Pero el Basic sinclair solo acepta una variable por cada sentencia DIM, lo que obliga a que si se encuentra en un listado lo sigte: DIM c(100),z(20,2),a(25) uno debe tipear para su conversión en el Spectrum: DIM c(100): DIM z(20,2): DIM a(25) La mayoria de Basics como el GW-Basic permiten que se omita DIM, si el arreglo es de 0 a 10, y requerido obligatoriamente si el subindice es de 11 en adelante. Esto es imposible en el Spectrum, debiendo añadirsele al listado su DIM correspondiente siempre, de lo contrario genera error. OPTION BASE Inexistente en el Basic Sinclair. esta sentencia le indica a la máquina que empiece los subindices de las matrices ya sea con 0 o 1. Si no aparece en el listado, la opción base es 0 por defecto. sintaxis: OPTION BASE n donde: n solo puede ser un valor 0 ó 1. En los Basics que carecen de esta instruccion, el subindice inicial es siempre 0. De modo que DIM (10) da en realidad 11 elementos y no 10 como en el Basic Sinclair. Debido a que el Spectrum empieza exclusivamente con subindice 1, hay que ignorar esta sentencia de encontrarse en un listado a convertir, y en cambio modificar todas las variables que controlen los subindices para evitar que se de el subindice 0, ya que eso causaria que el programa se detenga dando un mensaje de error "3 suscript wrong". ERASE Inexistente en el Basic Sinclair. A diferencia de CLEAR, que borra todas las variables en uso del programa, esta sentencia borra solo las matrices DIM, con el fin de eliminar su contenido para liberar el espacio de memoria reservado para dicha matriz. La razón es que el BASIC no permite redimensionar una matriz. En caso de intentarlo, se genera un error. Y si ya no se la va a usar más, lo mejor es eliminarla para usar la memoria liberada para otras tareas. sintaxis: ERASE matriz d1, matriz d2, ... Ejemplo: ERASE nombre$(50),calificaciones(50,4) En el caso del Spectrum, una matriz es creada, redimensionada y eliminada solamente por la misma sentencia DIM. Es decir reemplaza a la sentencia ERASE de los otros BASICs. Ejemplo: 10 DIM a(15) 20 FOR i=1 TO 15 30 INPUT a(i) 40 NEXT i 50 DIM a(20) Esto generaría error en otros Basics, pero no en el Spectrum. En este caso DIM elimina todo lo almacenado en a() y lo reinicia, redimensionándolo de 15 a 20 para ser reutilizada nuevamente. Applesoft Basic acepta hasta 88 dimensiones. Una vez creada la matriz, ya no puede ser redimensionada. Intentar hacerlo genera error. El C=64 admite cualquier numero de dimensiones, hasta un maximo de 255 sub indices. Al igual que Apple, tambien da error al intentar redimensionar. 2) Vectores y matrices El termino matematico "vector" alude a listas, mientras "matriz" refiere a tablas en algebra lineal. Aquí se trabaja solo con valores numericos. Las sigtes. instrucciones son inexistentes en Basic Sinclair: Sentencias especiales de manipúlación de matrices (MAT) Las grandes computadoras con terminales como el sistema HP 9845 de la Hewlett Packard y similares, tenían una versión de BASIC, que admitía sentencias muy especiales para la manipulación de matrices, que simplificaban considerablemente los calculos de vectores y tablas de datos numéricos. Sentencias: MAT READ, MAT INPUT, MAT PRINT, NUM MAT READ llena una matriz leyendo de una lista de datos del tipo READ-DATA-RESTORE. Ejemplo: 10 DIM a(5,3) 40 MAT READ a 200 DATA 1,3,5,5,9,11,13,15,17,19,21,23,25,27,29 En el Spectrum: 40 FOR i=1 TO 5: FOR j=1 TO 3 42 READ a(i,j) 44 NEXT j: NEXT i MAT READ permite redimensionar la matriz, siempre que los valores sean menores a los del DIM original. Ejemplo: 10 DIM p(35),q(50,50) 50 INPUT m,n 80 MAT READ p(m), q(n,n) El Spectrum no tiene tales restricciones y su equivalencia seria: 80 DIM p(m):DIM q(n,n) 82 FOR i=1 TO m: READ p(i): NEXT i 84 FOR j=1 TO n: FOR h=1 TO n: READ q(j,h): NEXT h: NEXT j MAT INPUT recibe los datos directamente del teclado y los pasa a un vector dado. Ejemplo: 10 DIM a(100) 50 MAT INPUT a version Spectrum: 50 FOR i=1 TO 100: INPUT a(i): NEXT i Para saber cuantos elementos se introdujeron desde un terminal, se usa la funcion NUM. Ejemplo: 60 A(0)=NUM 90 PRINT "la lista es de ";a(0);" elementos" En el Spectrum se la reemplaza por la variable FOR menos 1: 60 LET NUM = i - 1 90 PRINT "la lista es de ";NUM;" elementos" En caso de no querer ingresar todos los valores y salir en un punto dado: 50 FOR i=1 TO x 60 INPUT LINE a$ 70 IF a$="*" THEN NUM=i: LET i=x: GOTO 90 80 LET a(i)= VAL a$ 90 NEXT i 100 IF i= x+1 THEN LET NUM = i-1 Version sin GO TO. Modificar: 70 IF a$="*" THEN NUM=i: LET i=x 80 IF a$<>"*" THEN LET a(i)= VAL a$ MAT INPUT tambien permite el redimensionado de matrices: 10 DIM a(5,5) 20 MAT INPUT a(2,2) MAT PRINT imprime los valores de un vector o matriz. Ejemplo: 20 DIM a(5) 30 FOR h=1 TO 5 40 LET a(h)=h 50 NEXT 60 MAT PRINT a En el Spectrum habria que eliminar la linea 60 y añadir en cambio: 45 PRINT a(h) Operaciones y cálculos con matrices: Sentencias: =, +, -, *, TRN, INV, CON, ZER, IDN, DET MAT = hace que una matriz x sea igual a otra sintaxis: MAT c = a En el Spectrum su equivalente seria: 20 DIM a(5): DIM c(5) ... 130 FOR h=1 TO 5 140 LET c(h)=a(h) 150 NEXT h MAT = + hace que una matriz x sea igual a la suma de otras dos sintaxis: MAT c = a + b En el Spectrum: 20 DIM a(5): DIM b(5): DIM c(5) ... 130 FOR h=1 TO 5 140 LET c(h)=a(h)+b(h) 150 NEXT h MAT = - hace que una matriz x sea igual a la resta de otras dos sintaxis: MAT c = a - b En el Spectrum: como en el ejemplo anterior pero restando en vez de sumar. MAT = * sintaxis1: MAT c = a * b hace que una matriz x sea igual a la multiplicación de otras dos En el Spectrum: 20 DIM a(5): DIM b(5): DIM c(5) ... 130 FOR h=1 TO 5 140 LET c(h)=a(h)*b(h) 150 NEXT h sintaxis2: MAT c = (valor) * a se llama multiplicacion escalar cuando una matriz x es igualada a otra multiplicada por un valor siempre entre parentesis. En el Spectrum: 20 DIM a(5): DIM c(5): LET valor = 3.5 ... 130 FOR h=1 TO 5 140 LET c(h)=a(h)*valor 150 NEXT h MAT ZER llena de ceros una matriz dada. Permite redimensionar una matriz. sintaxis: MAT a = ZER En el Spectrum DIM siempre inicia a cero las matrices. MAT CON inicializa a 1 todos los elementos de una matriz. Permite redimensionar. sintaxis: MAT a = CON Ejemplo versión Spectrum: 20 DIM a(5) ... 130 FOR h=1 TO 5 140 LET a(h)=1 150 NEXT h MAT TRN transpone o intercambia las filas y columnas de una matriz dada sintaxis: MAT b = TRN(a) El único modo de hacer esto en el Spectrum es: DIM a(x,y): DIM b(y,x) FOR m=1 TO x: FOR n=1 TO y LET b(m,n) =a(n,m) NEXT n: NEXT m MAT IDN genera una matriz identidad, poniendo todo valor a cero, excepto en su diagonal principal donde todos sus valores son 1. Siempre y cuando la matriz dada sea cuadrada. Permite tambien redimensionar. sintaxis: MAT a = IDN Su equivalente en Basic Sinclair es: 10 DIM a(z,z) 20 FOR x=1 TO z: FOR y=1 TO z 30 LET a(x,y)=0: IF x-y = 0 THEN LET a(x,y) = 1 40 NEXT y: NEXT x La rutina anterior cumple la misma función que MAT IDN. Pero si se quisiera generar en cambio, una matriz con valor 1 en su diagonal derecha: 10 DIM a(z,z) 20 FOR x=1 TO z STEP 1: FOR y=1 TO z STEP 1 30 LET a(x,y)=0: IF x+y = z+1 THEN LET a(x,y) = 1 40 NEXT y: NEXT x MAT INV genera la inversa de una matriz cuadrada sintaxis: MAT b = INV(a) Su funcion asociada es DET, que verifica si la matriz tiene o no inversa. Programa ejemplo. Para invertir una matriz 2x2 en el Spectrum: 20 REM inversa de matriz = 1/det(A).*[d -b;-c a] 30 DIM A(2,2): DIM b(2,2) 40 FOR i =1 TO 2: FOR j =1 TO 2 50 INPUT A(i,j) 60 NEXT j: NEXT i 70 LET det= A(1,1)*A(2,2) - A(1,2)*A(2,1) 80 IF NOT det THEN PRINT "matriz no invertible": STOP 90 LET b(1,1) = det ^ -1 * A(2,2) 92 LET b(1,2) = det ^ -1 * -A(1,2) 94 LET b(2,1) = det ^ -1 * -A(2,1) 96 LET b(2,2) = det ^ -1 * A(1,1) 100 FOR i =1 TO 2: FOR j =1 TO 2 110 PRINT b(i,j), 120 NEXT j: NEXT i Nota: Un "bug" hace que el Spectrum genere mensaje de error si DET es negativo. Para evitarlo habría que añadir lo sigte: 75 LET md =ABS (det)^-1: IF det<0 THEN LET md =-md y luego modificar las lineas de la 90 a la 96 como sigue: 90 LET b(1,1) = md * A(2,2) y así. II - MATRICES ALFANUMERICAS Muy bien, ya vimos todas las sentencias BASIC de otros sistemas asociadas a matrices y vectores y su empleo en lo que se refiere al manejo de los números y las matemáticas. Ahora pasamos a ver el uso de DIM con cadenas. Cadenas tipo Apple-1 / Atari Tanto el Basic Entero de Apple como el de Atari, requieren que las cadenas sean inicializadas mediante la sentencia DIM para poderlas usar, de lo contrario se genera un error. En la mayoria de BASICs como el Microsoft, eso es innecesario, mientras que en el Basic Sinclair, es opcional. Matrices y tablas de cadena Debido al modo como Atari y Apple-1 o Basic entero de Apple, manejan las cadenas mediante DIM, es imposible crear o manejar tablas y matrices de cadenas, como sí hacen los BASICs tipo Microsoft y Sinclair. Las diferencias sintácticas entre estos BASICs es la sigte: DIM a$(10) opcional o innecesario en Basic Microsoft y similares, crea una lista ó tabla de cadena con sub-indice del 0 al 10. En Basic Sinclair, crea una cadena sóla de longitud fija de 10 caracteres como límite. En el Basic Atari inicializa la variable a$ para poderla usar en un programa. DIM a$(15,5) en Basic Microsoft crea una matriz de cadena bidimensional de 15x5 (16x6 si se considera el sub-índice 0), mientras en el Spectrum esto genera una lista de cadena de 15 elementos y 5 caracteres de largo. Genera error en Atari y Apple-1 ya que no admite matrices. En Basic Sinclair, el único modo de que sea una matriz en vez de una lista, es: DIM a$(15,5,longitud máxima). Esto es debido a que Microsoft trata las cadenas tanto variables y matrices dandoles una longitud libre, mientras Sinclair hace lo mismo solo con las variables de cadena pero no con las matrices, las cuales deben tener una longitud fija como límite. Sub-cadenas Todas las versiones de BASIC pueden manejar cadenas y sub-cadenas, ya sea sumandolas o extrayendolas. El modo de hacerlo es donde difiere: Atari usa el mismo metodo del Apple-1, el cual es muy parecido al de Sinclair, mientras que Microsoft y similares usan funciones exclusivas para ello. En estas notas solo voy a mencionar las funciones exclusivas para el manejo de subcadenas. A continuación una tabla comparativa de los BASICs mencionados: operación Atari/Apple-1 Sinclair Micosoft ------------------------------------------------------------------------- extrae a la izq. x$(x) x$(x TO) LEFT$ (x$,x) estrae a la der. x$(1,x) x$(TO x) RIGHT$ (x$,x) estrae del medio x$(x,y) x$(x TO y) MID$ (x$,x,n) un sólo caracter x$(x,x) x$(x) MID$ (x$,x,1) Algunas versiones de Basic poseen otras funciones de manejo de subcadenas como TL$, una función exclusiva del ZX-80, o SEG$ que reemplaza a MID$. III - MATRICES Y DATOS Aunque pueden ser usadas independientemente, las instrucciones que veremos a continuación operan mejor cuando se les asocia con DIM para el manejo de datos. Sentencias asociadas: READ, DATA, RESTORE DATA Esta sentencia Basic es usada para guardar datos dentro del cuerpo de un programa. Se utiliza en conjunto con READ y RESTORE para accesar a los datos numéricos o de cadena que el programa requiere. sintaxis: DATA lista de constantes numéricas o alfanuméricas Algunas versiones de Basic permiten tipear los datos del modo sigte.: 100 DATA ENE,FEB,"10-1-88",12,2000 En Basic Sinclair tal línea es imposible de leer correctamente, ya que tomará las primeras dos constantes, no como cadenas, sino como a variables numéricas, produciendo error. En el Spectrum se debe de tipear así: 100 DATA "ENE","FEB","10-1-88",12,2000 READ Carga cada elemento de DATA en una variable ya sea numérica o de cadena. Cuando se lelga al final de los datos y se intenta seguir cargando con READ se obtiene un mensdaje de error que detiene el programa indicando que se ha llegado más allá de los datos. Es decir que no pueden haber más variables que constantes DATA. sintaxis: READ v, v1, v2, ... donde: v = una variable numérica o alfanumérica De este modo para leer el ejemplo anterior de DATA, se requiere algo como: 10 READ a$,b$,c$,x,y RESTORE permite leer más de una vez el contenido de las sentencias DATA. sintaxis: RESTORE {n} donde: n = numero de línea opcional para marcar el puntero DATA a leer. En conjunto con DIM Para insertar datos a una matriz DIM, tenemos cuatro formas: desde el teclado con INPUT, de una lista de DATAs en el programa mismo con READ, mediante una sentencia de asignación LET y por último de un fichero tipo OPEN/CLOSE mediante INPUT#. El caso del ZX-81 El BASIC del ZX-81 posee la sentencia DIM, pero carece de READ, DATA y RESTORE. En lugar de estas tres sentencias, el manual original recomienda usar LET e INPUT. 5 REM ESTE PROGRAMA NO TRABAJA EN EL ZX81 10 DIM M$(12,3) 20 FOR N=1 TO 12 30 READ M$(N) 40 NEXT N 50 DATA "ENE","FEB","MAR","ABR" 60 DATA "MAY","JUN","JUL","AGO" 70 DATA "SEP","OCT","NOV","DIC" En su lugar habría que tipear: 10 DIM M$(12*3) 20 LET M$ ="ENEFEBMARABRMAYJUNJULAGOSEPOCTNOVDIC" 30 FOR N=1 TO 12*3 STEP 3 40 PRINT M$(N TO N+2) 50 NEXT N Otro modo de hacerlo sería: 10 DIM M$(12,3) 20 LET N$ ="ENEFEBMARABRMAYJUNJULAGOSEPOCTNOVDIC" 25 LET M =1 30 FOR N=1 TO 12*3 STEP 3 40 LET M$(M)=N$(N TO N+2) 42 LET M =M+1 40 NEXT N Con los números, se leerían del mismo modo y convirtiendolos con VAL. 10 DIM N(5) 20 LET N$ ="111222333444555" 25 LET M =1 30 FOR N=1 TO 5*3 STEP 3 40 LET N(M)=VAL N$(N TO N+2) 42 LET M =M+1 40 NEXT N Solamente así se puede trabajar sin READ ni DATA. Es decir, la cadena reemplaza a DATA, LET a READ y en cuanto a RESTORE n, se reemplaza por (n TO n +xx). Y así con casi todo en el ZX-81. El caso del LOGO El lenguaje de programación LOGO originalmente carece de instrucciones para trabajar con matrices. Pero estas pueden ser simuladas o reemplazadas usando listas o variables numeradas. Todos los demás lenguajes de programación como Pascal, Algol, Fortran, C, por mencionar unos cuantos, tienen sus instrucciones equivalentes a DIM para el manejo de matrices y listas. IV - MATRICES Y FICHEROS En este apartado vamos a ver todo lo relacionado a DIM, DATA y demás instrucciones asociadas con ficheros en el Basic Sinclair, comparándolos con los otros BASICs. Ficheros secuenciales Son ficheros secuenciales aquellos donde los datos se escriben y leen del mismo modo que la música salvada en una cinta de casete. Sabiendo esto, empezamos con un ejemplo de fichero en Basic Microsoft, Sentencias asociadas: OPEN, CLOSE, PRINT#, INPUT# 100 REM creacion de fichero numérico 110 DIM N(30) Omitiremos el ingreso de datos pues puede usarse LET, INPUT o READ/DATA para ello, así que pasamos a ver como se salvan los datos mediante... 130 OPEN "A:NUMEROS" FOR OUTPUT AS #1 190 FOR I=1 TO 30 200 PRINT #1,N(I) 300 NEXT I 310 CLOSE #1 Cerca de 5 líneas y varias instrucciones. En cambio en Basic Sinclair: 130 SAVE "NUMEROS" DATA N() ¡Una sóla línea de comando lo hizo todo! Con el consabido ahorro de tipeo y espacio en memoria. Ahora para leer el fichero antes creado: 110 DIM N(30) 130 OPEN "A:NUMEROS" FOR INPUT AS #1 190 FOR I=1 TO 30 200 INPUT #1,N(I) 300 NEXT I 310 CLOSE #1 Y en Basic Sinclair: 130 LOAD "NUMEROS" DATA N() Nuevamente solo una línea basta para cargar todo el fichero. Nota: en Basic Sinclair, una vez salvada la matriz, retiene la dimensión que le diera DIM. Cuando es cargada otra vez, vemos que ya no se la puede volver a redimensionar o expandir. Es más, reemplaza cualquier otra matriz con la misma letra. Solo se puede modificar el contenido para volverlo a salvar. Fichero secuencial alfanumérico Como ya se mencionó en la sección de "matrices y cadenas", el Spectrum maneja las cadenas de texto de un modo muy distinto a la mayoría de BASICs. Veamos dos ejemplos: Ejemplo 1: DIM A$(50) - lista de 50 elementos de longitud libre Para salvar el contenidom del mismo modo que la lista numerica anterior: 130 OPEN "A:NOMBRES" FOR OUTPUT AS #1 190 FOR I=1 TO 50 200 PRINT #1,A$(I) 300 NEXT I 310 CLOSE #1 Para leer la lista basta con reemplazar OPEN OUTPUT por... 130 OPEN "A:NOMBRES" FOR INPUT AS #1 y PRINT# por... 200 INPUT #1,A$(I) Ejemplo 2: DIM A$(xx,x) - tabla de xx elem. con x campos de long. libre Creamos una base de datos tipo agenda telefónica de xx= 50 elementos y x= 3 campos, donde campo 1= nombre, 2= num. de telf. y 3= dirección. Una vez llenados los datos pasamos a salvarlo todo con: 100 REM otra sintaxis de OPEN 130 OPEN "O",1,"A:AGENDA" 190 FOR I=1 TO 50: FOR J=1 TO 3 200 PRINT #1,A$(I,J) 300 NEXT J,I 310 CLOSE #1 Para leer los datos hacemos los sigtes cambios: 130 OPEN "I",1,"A:AGENDA" 200 INPUT #1,A$(I,J) La conversión de dichos ejemplos al Basic Sinclair nos da: Ejemplo 1: DIM a$(50, x) - donde x= el numero máx. de car. por elemento Ejemplo 2: hay dos modos de tipearlo todo en este caso... opcion 1.- DIM A$(50,3,x) - presuponiendo que los 3 campos son de la misma longitud x opcion 2.- DIM A$(50,x) - como el ejemplo 1, pero dividiendo el texto para conformar los tres campos segun su longitud requerida. De este modo, tenemos nombre con max. 20 caracteres, telefono 11 caracteres, y dirección 30 car., eso nos da x = 61 y se leería: DIM a$(50,61), campo 1= a$(TO 20), 2= a$(21 TO 31) y 3= a$(32 TO) En ambos casos, basta con SAVE "nombre" DATA a$() y LOAD ... DATA ... para salvar y cargar la matriz. Nota: lo que SAVE DATA salva es el contenido de la matriz, por lo que LOAD DATA las puede cargar asignándole una letra de variable distinta a la que tenía antes. Eso hace posible cargar varias copias de la misma matriz dependiendo siempre del espacio en memoria, incluso puede hacerse un SWAP (intercambio) entre matrices. Ficheros de acceso directo Son aquellos cuyos datos pueden ser leidos directamente mediante un sub-índice. En este caso no se usa PRINT# ni INPUT#, sino otra serie de instrucciones y funciones. Aquí se opera solamente con cadenas de texto, incluso los números deben ser convertidos a cadenas. Ejemplo de creación y escritura de fichero de acceso directo: 10 OPEN "R", #1, "INFOFILE", 32 20 FIELD#1, 20 AS N$, 4 AS A$, 8 AS P$ 30 INPUT "INDICE DE 2 DIGITOS"; CODE% 40 INPUT "NOMBRE"; X$ 50 INPUT "MONTO"; AMT 60 INPUT "TELEFONO"; TEL$: PRINT 70 LSET N$=X$ 80 LSET A$=MKS$(AMT) 90 LSET P$=TEL$ 100 PUT #1, CODE% 110 GOTO 30 OPEN "R" le dice al fichero cuantos caracteres aceptará como máximo. FIELD designa cuantos campos tendrá el fichero y de cuantos caracteres cada campo. LSET almacena los valores ingresados a su campo correspondiente. PUT los guarda en su indice correspondiente. Para leer la información en cambio: 10 OPEN "R",#1,"INFOFILE",32 20 FIELD #1, 20 AS N$, 4 AS A$, 8 AS P$ 30 INPUT "INDICE DE 2 DIGITOS";CODE% 40 GET #1, CODE% 50 PRINT N$ 60 PRINT USING "$$###.##";CVS(A$) 70 PRINT P$:PRINT 80 GOTO 30 Como se ve, se usa GET en vez de PUT y las variables de los campos se leen directamente ahora sin más intermediarios. Su conversión al Spectrum: 10 INPUT "maximo num. de fichas? ";n 20 DIM A$(n,32): DIM x$(20): DIM m$(4): DIM t$(8) 30 INPUT "INDICE DE 2 DIGITOS"; c 35 IF c=0 OR c>n THEN GOTO 120 40 INPUT "NOMBRE"; X$ 50 INPUT "CODIGO POSTAL"; M$ 60 INPUT "TELEFONO"; T$ 70 LET A$(c, TO 20)=X$ 80 LET A$(c,21 TO 24)=M$ 90 LET A$(c,25 TO)=T$ 110 GOTO 30 120 SAVE "infofile" DATA a$() Y para leer posteriormente los datos: 10 LOAD "infofile" DATA b$() 30 INPUT "INDICE DE 2 DIGITOS";c 35 IF c=0 OR c>n THEN STOP 50 PRINT b$(c, TO 20) 60 PRINT b$(c,21 TO 24) 70 PRINT b$(c,25 TO): PRINT 80 GOTO 30 En la conversión vemos que DIM ha reemplazado a FIELD y LET a LSET, así como OPEN "R", GET y PUT han sido reemplazados por SAVE/LOAD DATA. El otro detalle a resaltar es el modo como los ficheros directos en BASIC MICROSOFT requieren de una longitud de texto fija de un modo muy parecido a como el Spectrum maneja las cadenas de texto. La diferencia estriba en que un fichero directo depende de la capacidad máxima del disco en que se guarda, mientras la matriz DIM depende de la cantidad de memoria libre disponible en RAM. Y de este modo cierro esta colección de apuntes sobre el DIM del Spectrum, demostrando lo poderoso y versatil que es. Por otro lado el Basic Sinclair sin expansión no nos deja otra opción que la de SAVE/LOAD DATA. Es de hecho la única alternativa para los usuarios del +3 y el MB-02+. (c)2020 zx_if1@hotmail.com