SERIE CONVERSIONES DEL SPECTRAVIDEO SVI-318 AL SPECTRUM Programa: Fichero Biblioteca Versión base / Basic / Gestión personal Publicado en la página 91 de la revista Tu Micro 3/4 de julio/agosto de 1984. El listado original: 1 REM ENRIQUE JAVIER MURUBE SOTO 2 REM Programa principal 3 PLAY"AB" 5 CLS 7 PRINT" JAVIER MURUBE's fichero" 10 PRINT"MENU",,"1-creacion",,"2-insercion",,"3-busqueda",,"4-eliminacion" ,,"5-listado",,"6-grabacion",,"7-carga" 15 PRINT:PRINT:PRINT 20 INPUT " opcion ";N 25 CLS 30 ON N GOSUB 100,200,300,400,500,600,700 90 GOTO 5 99 REM rutina de creacion del fichero 100 IF C=8 THEN GOTO 197 101 PLAY"C": PRINT "Estas seguro de querer crear... s/n " 105 INPUT N$ 110 IF N$<>"s" THEN GOTO 197 111 RESTORE 112 C=8: DIM V$(C): FOR I=1 TO C: READ V$(I): NEXT I 113 INPUT "Numero maximo de titulos a guardar ";NUMERO 115 DIM A$(NUMERO,C) 120 FOR J=1 TO NUMERO: PRINT:PRINT"PARA TERMINAR: zzz":PRINT:PRINT: FOR I=1 TO C 125 PRINT V$(I):INPUT A$(J,I) 130 IF A$(J,I)="zzz" THEN GOTO 195 135 NEXT I:CLS:NEXT J 145 INDICE=NUMERO 150 DATA titulo,autor,editorial,idioma,edicion,paginas,precio,notas 155 GOTO 196 195 INDICE=J-1 196 GOSUB 900 197 RETURN 199 REM rutina de insercion de 1 elemento 200 PLAY"D": IF INDICE=NUMERO THEN GOTO 290 205 PRINT "INSERCION" 210 FOR I=1 TO C 215 PRINT V$(I):INPUT A$(INDICE+1,I) 220 NEXT I 225 PRINT:INPUT "CORRECTO? s/n ";N$ 230 IF N$<>"s" THEN GOTO 291 235 INDICE=INDICE+1 240 GOSUB 900 250 GOTO 291 290 PRINT "FICHERO COMPLETO": INPUT J 291 RETURN 299 REM rutina de busqueda de 1 elemento 300 PLAY"E": IF INDICE=NUMERO THEN GOTO 340 301 GOSUB 900 302 PRINT "Introduce ";V$(S);" a buscar" 303 INPUT N$ 305 FOR I=1 TO INDICE 310 IF A$(I,S)=N$ THEN GOTO 375 315 IF A$(I,S)>N$ THEN GOTO 330 320 NEXT I 330 CLS:PRINT "NO ESTA ";N$: INPUT J 332 RN=0 340 RETURN 375 RN=I 380 FOR I=1 TO C: PRINT V$(I);": "A$(RN,I):NEXT I:INPUT J 385 GOTO 340 399 REM rutina de eliminacion de 1 elemento 400 PLAY"F": IF INDICE=NUMERO THEN GOTO 490 405 GOSUB 300 410 IF RN=0 THEN GOTO 490 415 INPUT "Seguro de querer borrarlo? s/n ";T$: IF T$<>"s" THEN GOTO 490 420 A$(RN,S)="zzzzzz" 425 GO SUB 1000 430 INDICE=INDICE-1 490 RETURN 499 REM rutina de impresion de todo el fichero 500 PLAY"G": FOR I=1 TO INDICE:FOR J=1 TO C 510 PRINT V$(J);": ";A$(I,J) 520 NEXT J:FOR K=1 TO 100:NEXT K:PRINT:PRINT:NEXT I 525 INPUT J 530 RETURN 599 REM RUTINA DE GRABACION 600 PLAY"D":IF INDICE=NUMERO THEN GOTO 690 601 OPEN"cas:t"FOR OUTPUT AS 1 602 PRINT#1,INDICE,C 605 FOR I=1 TO INDICE:FOR J=1 TO C 610 PRINT#1,A$(I,J) 615 NEXT J:NEXT I 620 FOR I=1 TO C:PRINT#1,V$(I):NEXT I 625 CLOSE 1 690 RETURN 699 REM rutina de carga 700 PRINT"PONGA EN MARCHA EL CASETE PARA CARGAR EL FICHERO":OPEN"cas:t"FOR INPUT AS 1 705 INPUT#1,INDICE,C:DIM A$(INDICE+10,C):DIM V$(C) 710 FOR I=1 TO INDICE:FOR J=1 TO C 715 INPUT#1,A$(I,J) 720 NEXT J:NEXT I 725 FOR I=1 TO C:INPUT#1,V$(I):NEXT I 730 CLOSE 1 790 RETURN 898 REM 899 REM rutina de ordenacion (no visible) 900 CLS:PRINT "Por que numero de campo desea la busqueda/ordenacion": FOR K=1 TO C:PRINT K;"-";V$(K):NEXT K:INPUT "numero ";S 1000 PLAY"ABC" 1005 J=0 1010 FOR I=1 TO INDICE-1 1020 IF A$(I,S)>A$(I+1,S) THEN GOSUB 1100 1030 NEXT I 1040 IF J<>0 THEN GOTO 1005 1050 RETURN 1100 J=1 1110 FOR K=1 TO C 1120 N$=A$(I,K) 1130 A$(I,K)=A$(I+1,K) 1140 A$(I+1,K)=N$ 1150 NEXT K 1160 RETURN PORTANDOLO AL SPECTRUM La estructura del listado Basic es la sigte.: 1-90 : el programa principal y menú. 99-190 : rutina de creación 199-290 : inserción de datos 299-385 : busqueda 399-490 : eliminación 499-530 : impresión de todo el fichero 599-690 : grabación del fichero 699-790 : carga 899-1160: ordención de los datos Tras estudiar el programa podemos decir que el programa es facil de portar al Spectrum, con unas cuantas modificaciones al listado en lo que respecta al modo de manejar las matrices de cadena y la forma de salvar el fichero. Ya que ON GOSUB no existe en el Spectrum debemos reemplazar la línea 30 por: 30 GO SUB 100*N En cuanto a las sentencias de sonido PLAY, estas se pueden retener en el Spectrum 128, +2 o +3 y en cambio reemplazarlas por su equivalente BEEP en un 48k. En este caso los PLAY de las líneas 3,101,200,300,400,500,600 y 1000 pueden ser eliminados con lo que dejamos el programa sin sonidos o tipeamos: 3 BEEP .5,5: BEEP .5,6 101 BEEP .5,0: ... 200 BEEP .5,1: ... 300 BEEP .5,2: ... 400 BEEP .5,3: ... 500 BEEP .5,4: ... 600 BEEP .5,1: ... 1000 BEEP .5,5: BEEP .5,6: BEEP .5,0 VARIABLES Y MATRICES EN EL SPECTRUM Las variables usadas por el progtrama son las sigtes.: A$() - almacena todos los registros del fichero C - el número de campos I,J,K - variables auxiliares para bucles FOR INDICE - indica las fichas existentes N - auxiliar NUMERO - el máximo de fichas al crear el fichero N$,T$ - auxiliares RN - define la posición den las operaciones de búsqueda S - almacena el cambio por el que se busca y ordena V$() - guarda el encabezado de los campos Tras estudiar las variables elegidas por su autor, paso a hacer lo sigte.: La línea: 112 C=8: DIM V$(C): ... en el Spectrum tengo que cambiarla por: 112 LET C=8: DIM V$(C,9): ... Pero en el caso de: 115 DIM A$(NUMERO,C) Tengo dos opciones: 1- 115 DIM A$(NUMERO,C, long.max) y... 2- 115 DIM A$(NUMERO,long.max) para la primera opción reteniendo C por razones de retener la sintaxis y no cambiar mucho el listado elegí hacer long.max= 32 mientras que en el segundo caso elegí hacer long.max= 160. En el primer caso tenemos N registros o fichas de C campos, todos los cuales son de 32 caracteres de longitud máxima. Y en el segundo caso tenemos N registros de 160 caracteres, los cuales contienen los campos que luego hay que separar mediante los sigtes. métodos: a) Creando 2 variables de matriz numérica conteniendo los puntos de inicio y fin de los campos y... b) usando una sola matriz numérica conteniendo todo lo anterior Los campos y la longitud de cada campo en mi versión es como sigue: titulo - 32 caracteres autor - 32 c. editorial - 10 c. idioma - 10 c. edicion - 4 c. paginas - 4 c. precio - omitido, volviendo C=7 notas - 67 c. más o menos Aplicando el método b, debemos añadir lo siguiente: DIM x(c+1):FOR i=1 TO c+1: READ x(i): NEXT i DATA 0,32,64,74,84,88,92,160 y reemplazar A$(J,I) por A$(J,X(I)+1 TO X(I+1)) Ahora las líneas 130,310, y 315 se deben reemplazar por: 130 IF A$(J,I, TO 3)="zzz" THEN GOTO 195 310 IF A$(I,S, TO LEN N$)=N$ THEN GOTO 375 315 IF A$(I,S, TO LEN N$)>N$ THEN GOTO 330 o segun el método b: 130 IF A$(J, TO 3)="zzz" THEN GOTO 195 310 IF A$(I,X(S)+1 TO X(S)+LEN N$)=N$ THEN GOTO 375 315 IF A$(I,X(S)+1 TO X(S)+LEN N$)>N$ THEN GOTO 330 Solamente si usamos el método b, debemos modificar las líneas 125,215,380,420,510, 1020,1120,1130 y 1140. Para salvar los datos a cinta simplemente reemplazamos las rutinas OPEN/CLOSE por: 620 SAVE "CAS:T2" DATA V$() 625 SAVE "CAS:T3" DATA A$() Añadir al comienzo del programa DIM N(2) y... 611 LET N(1)=INDICE: LET N(2)=C 615 SAVE "CAS:T1" DATA N() Para la rutina de carga en cambio: 715 LOAD "" DATA N() 720 LOAD "" DATA V$() 725 LOAD "" DATA A$() 730 LET INDICE=N(1):LET C=N(2) La sintaxis de la versión cinta, solo es compatible con el +3 y el MB-02+. En el caso de Speccydos y otros sistemas de discos debe usarse SAVE* y LOAD* o la sintaxis que tales sistemas requieran. FICHEROS SECUENCIALES El Spectrum solamente puede trabajar con ficheros secuenciales si se poseen Microdrives, Wafadrive o discos como el Opus discovery, +D o Timex FDD-3000. Versión Microdrive debemos modificar la rutina de guardar tipeandola como: 601 OPEN #4;"m";1;"cas:t" 602 PRINT #4;INDICE'C 605 FOR I=1 TO C:PRINT #4;V$(I):NEXT I 610 FOR I=1 TO INDICE:FOR J=1 TO C 615 PRINT #4;A$(I,J) 620 NEXT J:NEXT I 625 CLOSE #4 Y... 700 OPEN #4;"m";1;"cas:t" 705 INPUT #4;INDICE;C: DIM A$(INDICE+10,C):DIM V$(C) 710 FOR I=1 TO C:INPUT #4;V$(I):NEXT I 715 FOR I=1 TO INDICE:FOR J=1 TO C 720 INPUT #4;A$(I,J) 725 NEXT J:NEXT I 730 CLOSE #4 Versión Wafadrive solamente hay que reemplazar las líneas 601 y 700 por: OPEN #*4;"cast" Versión Opus y DiscIple estos sistemas tienen la sintaxis parecida: 601 OPEN #4;1;"cas:t" OUT Y... 700 OPEN #4;1;"cas:t" IN solo que el DiscIple requiere OPEN #4;d1;... comparado con el Opus. Versión BETA128 DOS =15619 para BETA128 y DOS =15363 para Betadisc 48 o Betaplus 601 RANDOMIZE USR DOS: REM: OPEN #4,"CAST",W 625 RANDOMIZE USR DOS: REM: CLOSE #4 y... 700 RANDOMIZE USR DOS: REM: OPEN #4,"CAST",R Versión Didaktik 601 OPEN #4,,"cast" Y... 700 OPEN #4,"cast" Versión Timex FDD-3000 hacer previamente DIM*"cast" para crear el fichero secuencial 601 OPEN #*1;"cast";O 602 PRINT *#1;STR$ INDICE+" "+STR$ C+" " 605 FOR I=1 TO C:PRINT *#1;V$(I)+" ":NEXT I 610 FOR I=1 TO INDICE:FOR J=1 TO C 615 PRINT *#1;CHR$ 34+A$(I,J)+CHR$ 34+" " 620 NEXT J:NEXT I 625 CLOSE #*1 Y... 700 OPEN #*1;"cast";I 705 INPUT *#1;B$:LET INDICE=VAL B$:INPUT *#1;B$:LET C=VAL B$: DIM A$(INDICE+10,C) :DIM V$(C) 710 FOR I=1 TO C:INPUT *#1;V$(I):NEXT I 715 FOR I=1 TO INDICE:FOR J=1 TO C 720 INPUT *#1;A$(I,J) 725 NEXT J:NEXT I 730 CLOSE #*1 FICHEROS DIRECTOS Aunque el programa fue pensado para manejar ficheros secuenciales, podemos hacerle una mejora adaptándolo para trabajar con ficheros directos. En este caso el Spectrum solo puede accesar a este tipo de ficheros si se tiene el Opus Discovery o el Timex FDD. Beta128 también accesa estos ficheros mientras el +D solamente con Betados o Unidos. Versión Opus 601 OPEN #4;1;"cas:t" RND c*32+9,MAX 602 POINT #4,1: PRINT #4;INDICE'C 605 POINT #4,2:LET B$="":FOR I=1 TO C:LET B$=B$+V$(I)+CHR$ 13:NEXT I:PRINT #4;B$ 610 FOR I=1 TO INDICE:POINT #4,2+I:LET B$="":FOR J=1 TO C 615 LET B$=B$+A$(I,J)+CHR$ 13 620 NEXT J:PRINT #4;B$:NEXT I 625 CLOSE #4 Y... 700 OPEN #4;1;"cas:t" RND c*32+9 705 POINT #4,1:INPUT #4;INDICE;C;NUMERO: DIM A$(INDICE+10,C,32):DIM V$(C,9) 710 POINT #4,2:FOR I=1 TO C:INPUT #4;V$(I):NEXT I 715 FOR I=1 TO INDICE:POINT #4,2+I:FOR J=1 TO C 720 INPUT #4;A$(I,J) 725 NEXT J:NEXT I 730 CLOSE #4 O... 601 OPEN #4;1;"cas:t" RND 161,MAX 610 FOR I=1 TO INDICE:POINT #4,2+I 615 PRINT #4;A$(I) 620 NEXT i Y... 700 OPEN #4;1;"cas:t" RND 161 715 FOR I=1 TO INDICE:POINT #4,2+I 720 INPUT #4;A$(I) Versión +D con Betados reemplazamos las líneas 601 y 700 por: OPEN #4;d1;"cas:t" RND añadimos DIM z$(5) 602 POINT #4,0: LET Z$=STR$ INDICE: PRINT #4;Z$ 610 FOR I=1 TO INDICE*160 STEP 160:POINT #4,4+I Versión DiscIple y +D con Unidos 601 OPEN #4;d1;"cas:t" RND MAX*160+2,0 Y... 700 OPEN #4;d1;"cas:t" RND Versión BETA128 601 RANDOMIZE USR DOS: REM: OPEN #4,"CAST",RND,160 602 PRINT #4;1;STR$ INDICE 705 INPUT #4;(1);B$:LET INDICE=VAL B$(TO 4) Versión Timex FDD-3000 601 OPEN #*1;"cast";R;160 602 PRINT *#1;STR$ INDICE+" "+STR$ C; AT 1 605 FOR I=1 TO C:PRINT *#1;V$(I)+" ":NEXT I 610 FOR I=1 TO INDICE 615 PRINT *#1;A$(I); AT I 620 NEXT I 625 CLOSE #*1 Y... 700 OPEN #*1;"cast";R;160 705 INPUT *#1;B$; AT 1:LET INDICE=VAL B$(TO 4):LET C=VAL B$(5 TO) 707 DIM A$(INDICE+10):DIM V$(C) 710 FOR I=1 TO C:INPUT *#1;V$(I):NEXT I 715 FOR I=1 TO INDICE 720 INPUT *#1;A$(I); AT I 725 NEXT I 730 CLOSE #*1 Nota: MAX, en los DOS que los rquieran es el númwero máximo de registros que el fichero contendrá, una vez alcanzado ese valor ya no podrán añadirsele más datos pues habrá llegado a su límite. RESPECTO AL PROGRAMA NUMERO es comparado en las lineas 200,300,400 y 600, pero no es salvada como parte del fichero, así que al cargar los datos, NUMERO ya no figura. En el Basic estandar se pone a cero, pero no en el Basic Sinclair. Su mera inexistencia da error en el Spectrum y su puesta a cero hace que las comparaciones nunca se cumplan. Eso se corrige salvando también esta variable, para su posterior compración ahí donde se requiera. Al cargar, el valor de INDICE es incrementado en 10, redimensionando así la matriz DIM, pero a la larga, superará el espacio libre disponible para los datos con lo que el programa se detendrá con un error de debordamiento. Esto se corrige creando una variable MAX a la cual se le igualará en caso necesario: IF indice > max THEN LET indice = max. La variable C es iniciada en cero, y obtiene su valor solo cuando se ejecuta crear o cargar el fichero. Solo se la compara en la línea 100, para evitar entrar en crear, si el fichero ya existe. INPUT J es usado en las líneas 290,330,380 y 525. En Spectravideo eso hace que el usuario pulse ENTER para continuar, pero en el Spectrum hay que reemplazarla ya sea por INPUT J$ o INPUT LINE J$. MEJORAS AL PROGRAMA Añadir una opción "0- salir del programa" y "IF n=0 THEN GOTO 10000" En el caso de discos se puede añadir una opción 8 para ver el CATálogo. En el caso de los Microdrives y Wafadrive se podría añadir una opción ERASE para borrar ficheros ya que no permite sobreescribir. El OPUS no necesita eso, pues sobreescribe todo. Timex FDD ofrece la opción de lectura y escritura / sovreescritura de ficheros. Igual Disciple. Beta128 sí necesitaría esa opción, pues en vez de sobre escribir, añade al final del fichero. Otra mejora es modificarlo para que puedan crearse ficheros de cualquier tipo, ya no solo libros, sino otro tipo de datos como agenda telefonica o lista de empleados y cientes por ejemplo. La línea 150 con los datos y las líneas 111 y 112 que leen los datos se remplazaría por: INPUT "Numero de campos ";C DIM V$(C,10) FOR n=1 TO C INPUT "Ingrese nombre del campo #";(n)'V$(n) NEXT n A partir de aquí podemos dejar la matriz A$ que contiene los registros como: DIM A$(numero, C, len) donde len=32 para no complicarnos más, o añadir una nueva matriz V que contenga la longitud maxima de cada campo obligqando a: DIM A$(numero, len) donde len= la suma de todas las longitudes de cada campo Otro cvambio es usr solamente acceso directo al fichero y en este caso se cambian todas las líneas de lectura escritura siendo A$ solamente: DIM A$(len) para este ejemplo len=160 ya que no contendría nada más que los datos del registro siendo la versión OPUS: POINT #4;indice: PRINT #4;A$ es decir se trabajaría directamente en el fichero sin usar DIM como intermedio. Y con esto cierro todas mis notas de conversión de este interesante programa. Francisco León. (C)2021. zx_if1@hotmail.com