Todo sobre: PRINT USING o sus equivalentes en el Basic Sinclair Continuando con el Basic Sinclair, esta es una nueva recolección de notas sueltas ahora dedicadas exclusivamente a PRINT USING. Veamos su definición primero: USING usada exclusivamente con PRINT, permite imprimir números o cadenas con un formato variable específico. También permite expresiones con formato determinado. Sintaxis: PRINT USING "formato"; expresiones Ejemplo: 10 A=125: B=13456 20 PRINT USING "######";A 30 PRINT USING "######";B IMAGE y USING existente en algunas versiones de Basic, son las instrucciones mas potentes para el formateo de salida de datos. Siempre se deben usar juntas. La instruccion IMAGE aparece en los listados bajo la forma de dos puntos ":" y USING siempre asociada a PRINT pero con numero de linea IMAGE por unico parametro. Ejemplo: 120 :Nombre Horas Cant.Ganada 130 :########### ### $#####.## 140 :Suma de cantidades $#####.## 150 PRINT USING 120 No es muy diferente a como Pascal o Fortran formatean sus resultados impresos. Claro esta la sintaxis USING "formato"; expresiones fue la que termino imponiendose en la mayoria de BASICs que lo usan. Con impresoras Sintaxis: LPRINT USING string exp; list of expressions[;] en el GWbasic se asume que la impresora es de 80 columnas. USING# PRINT# tambien puede usarse con USING para controlar el formato en los ficheros de disquete. Por ejemplo: PRINT#1,USING"$$###.##.";J;K;L Los sigtes. caracteres especiales pueden ser usados para formatear campos numericos: # se usa para representar cada digito. Las posiciones siempre se llenan. Si el numero a imprimir tiene menos digitos, el resultado se justifica a la derecha precedido de espacios. Se puede insertar un punto decimal en cualquier parte del campo. + al inicio o al final hace que el signo de mas o menos se imprima. - al final del campo hace que los numeros negativos tengan signo menos. ** al inicio hace que el resultado sea llenado con asteriscos. $$ al inicio del campo hace que se imprima un signo dolar a la derecha **$ combina los efectos de los dos simbolos ya mencionados. , a la izquierda del punto decimal hace que una coma se imprima. ^^^^ sirven para especificar un formato exponencial. Da espacio o signo a E+xx. _ hace que un signo salga como un caracter literal. % se imprime delante del resultado si el numero es mayor al campo. USING, inexistente en el Basic Sinclair, tampoco la tienen los BASICs de APPLE, Atari, C=64 y VIC-20. Existe en cambio, en las versiones Basic de Microsoft como el GW-Basic, MSX, C=128 y PLUS/4. Curiosamente las versiones de Basic estructurado como el BBC y el Superbasic del QL carecen de esta instrucción. Betabasic posee dos versiones de esta instrucción: USING, que solo puede ser usada con PRINT y LPRINT, y su variante USING$, una función de cadena que hace lo mismo, pero que puede ser usada dentro de variables y otras sentencias aparte de PRINT como puede ser PRINT# o incluso INPUT. El SAM usa USING pero como parte de la sintaxis de FILL para rellenar graficos en vez de con PRINT. Posee en cambio USING$ pero solamente con Master Basic. Ahora si no se tiene Betabasic, hay que definirla como sigue: En el caso de Apple: Publicado en Basug Hardcore vol.1 #3 MAY 1981 P.32: 10 TEXT: HOME: RESTORE: GOSUB 190: GOSUB 300: HOME: FOR I= 1 TO NF: PRINT R$(I): NEXT: END 190 READ NF: FOR I= 1 TO NF: READ NF$,LE(I),VT(I): HTAB 15-LEN(NF$): VTAB VT(1): PRINT NF$: NEXT 191 DATA 10,NAME,18,10,ADDRESS,18,11,ADDRESS,18,12,ADD RESS,18,13,ADDRESS,18,14,POST CODE,10,15,TELEPHONE #,15 ,16,RENEW DATE,8,18,PAID DATE,8,19,MEMBER #,8,21 195 RETURN 300 I=0 310 I=I+1: RD$="" 320 IF I>NF THEN 470 330 IF I<1 THEN RETURN 310 VTAB VT(I): HTAB 16: R$=R$(I) 360 GET Y$: IF Y$=CHR$(13) AND LEN(RD$) THEN 460 370 IF Y$=CHR$(13) THEN 310 380 IF Y$=CHR$(8) AND LEN(RD$)<2 THEN VTAB VT(I): HTAB 16: CALL -868: RD$="": GOTO 360 390 IF Y$=CHR$(8) THEN RD$=LEFT$(RD$, LEN(RD$)-1): VTAB VT(I): HTAB 16: PRINT RD$: CALL -868: GOTO 360 400 IF Y$=CHR$(27) AND LEN(RD$) THEN RD$="": VTAB VT(I): HTAB 16: CALL -868: GOTO 360 410 IF Y$=CHR$(27) THEN I=I-1: R$="": GOTO 330 415 IF Y$=CHR$(21) AND (R$="" OR LEN(RD$)=LEN (R$)) THEN 360 417 IF Y$=CHR$(21) THEN RD$=RD$+MID$(R$,LEN(RD$)+1,1): PRINT MID$(R$,LEN(RD$),1);: GOTO 360 420 IF ASC(Y$)<32 THEN CALL -1052: GOTO 360 430 IF LEN(RD$)+1 > LE(I) THEN CALL -1052: GOTO 360 440 PRINT Y$; 450 RD$=RD$+Y$: R$=RD$: GOTO 360 460 R$(I)=RD$: R$="": GOTO 310 470 RETURN La solución para Atari: Publicada en la revista norteamericana COMPUTE! #10 de marzo del 81, pag.84. 1 REM ** FORMATTED OUTPUT EXAMPLE ** 2 REM JOE WROBEL, ROCHESTER, NY 3 REM SUBROUTINE VARIABLES - I,LC,N,NC,ND,NZ,RC,LlNE$,N$ 10 NC=37: DIM LINE$(NC), N$(NC) 20 GOSUB 2010 100 N$="X":RC=7:GOSUB 1060 110 N$="X/32":RC=17:GOSUB 1060 120 N$="SIN(PI*X/8)":RC=33:GOSUB 1060 130 GOSUB 2000 140 FOR X=0 TO 15 150 N=X:ND=0:RC=7:GOSUB 1000 160 N=X/32:ND=3:RC=17:GOSUB 1000 170 N=SIN(4*ATN(1)*X/8):ND=7:RC=32:GOSUB 1000 180 GOSUB 2000:NEXT X 190 STOP 1000 I=INT(10^ND+0.5) 1010 N=INT(I*N+0.5)/I 1020 N$=STR$(N):IF ND=0 THEN 1060 1030 IF N=INT(N) THEN N$(LEN(N$)+1)="." 1040 NZ=ND+1+LEN(STR$(INT(N)))-LEN(N$) 1050 IF NZ>0 THEN FOR I=1 TO NZ:N$(LEN(N$)+1)="0":NEXT I 1060 LC=RC+1-LEN(N$):IF LC<=RC AND RC<=NC AND LC>=1 THEN LINE$(LC,RC)=N$ 1070 RETURN 2000 PRINT LINE$ 2010 FOR I=1 TO NC:LINE$(I,I)=" ":NEXT I:RETURN La respuesta de Commodore: Publicado como un ejemplo del uso de STR$ en la pag.157 del libro "C=64, VIC-20 Basic Handbook". 5 PRINT CHR$(147) 10 PRINT "TEST PROGRAM FOR" 15 PRINT "DOLLAR AND CENT FORMAT" 20 PRINT "INPUT VALUES:" 25 PRINT 30 INPUT N 40 60SUB 200 45 PRINT 50 PRINT " ==> ";P$ 60 PRINT 70 GOTO 30 140 REM * DOLLAR AND 150 REM * CENT FORMAT 160 REM * ROUTINE. 170 REM * RECEIVES 175 REM * VALUE IN N; 180 REM * RETURNS 190 REM * PRINT STRING 195 REM * IN PS. 200 LET N=INT(N*100+.5)/100 210 LET N$=STR$(N) 215 LET N$=MID$(N$,2,LEN(N$)-1) 220 LET P=0:LET C$="":LET d$="" 230 FOR 1=1 TO LEN(N$) 240 IF MID$(N$,I,1)="." THEN LET P=I 250 NEXT I 260 IF P=0 THEN LET P=LEN(N$)+1:LET N$=N$+".0" 270 LET N$=N$+"0" 280 LET C$=MID$(N$,P,3) 290 IF P=1 THEN LET D$="0":GOTO 430 300 LET N$=MID$(N$,1,P-1) 310 IF LEN(N$)<=3 THEN LET D$=N$:GOTO 430 320 LET T=INT(LEN(N$)/3)-1 330 LET L=LEN(N$)-(T+1)*3 340 IF L=0 THEN GOTO 360 350 LET D$=LEFT$(N$,L)+"," 360 LET L=L+1 370 IF T=0 THEN GOTO 420 380 FOR I=1 TO T 390 LET D$=D$+MID$(N$,L,3)+"," 400 LET L=L+3 410 NEXT I 420 LET D$=D$+MID$(N$,L,3) 430 LET P$="$"+D$+C$ 440 RETURN La alternativa del ZX-81: Originalmente publicado en "les aides aux ZX" de la revista francesa ORDINATEUR INDIVIDUEL #39, p-188. Fue corregido despues en el #44, p-199 y vuelto a corregir en el #58, p-237, siendo esta su forma final que es la que expongo aqui: 1 INPUT X: REM LET D=...: LET I=... 2 LET X$=STR$ INT((ABS X-INT ABS X)*10**D+.5) 3 IF LEN X$<=D THEN GOTO 10 4 LET X=X+SGN X 5 LET X$="0" 10 LET X$=("-" AND SGN X=-1+STR$ INT ABS X+"."+("0000")(LEN X$ TO D-1)+X$ 20 PRINT (" "+X$)((LEN X$+8-I TO) 30 GOTO 1 Donde: X= el valor numerico a formatear en pantalla D= el numero de decimales - un valor de 1 a 5 I= el numero total de columnas del formato a imprimir, siendo el resultado mostrado en la forma como por ejemplo: I - siempre un valor de 3 a 10, equivalente a LEN "xxxxx.ddd" En el ZX Spectrum: Podemos usar y tipear tal cual la rutina para ZX81 con el unico cambio en la linea 2 que pasaria a ser: 2 LET X$=STR$ INT((ABS X-INT ABS X)*10*^D+.5) En mi caso, se me ocurrieron otras alternativas a USING que ofrezco a continuacion. Version 1: DEF FN U$(n,l)= "{15 espacios}"(TO l - LEN STR$ n) + STR$ n donde: n= el numero a formatear y l= la cantidad de digitos a imprimir Version 2: DEF FN U$(l$,n)= "{15 espacios}"(TO LEN l$ - LEN STR$ n) + STR$ n donde: n= el numero a formatear y l$= una cadena con la cantidad de digitos a usar Version 3: DEF FN u$(x,n)=(STR$ x)(TO LEN STR$ INT x)+((STR$ x)(1+LEN STR$ INT x TO))(TO n+1) donde: x= el numero a formatear y n= la cantidad de decimales a usar Version 4: DEF FN w$(x)=(STR$ x)(1+ LEN STR$ INT x TO) DEF FN u$(x,n)=(STR$ x)(TO LEN STR$ INT x)+ FN w$(x)(TO n+1) donde: x= el numero a formatear y n= la cantidad de decimales a usar En el QL: Podemos definir la rutina del ZX81 ya sea como un procedimiento o ya como funcion. Si como procedimiento: DEfine PROCedure USING(x,d,l) en este caso se invocaria directamente por su nombre como USING solo e imprimira directamente an pantalla el valor deseado. Si como funcion: DEfine FUNction USING(x,d,i) en este caso se invocaria ya sea mediante LET o PRINT USING u otra instruccion que lo requiera. En el caso del SAM: Debido a que sin Master Basic, el SAM carece de PRINT USING, podemos definir la version del ZX81 solamente como un procedimiento bajo la forma: DEFPROC PRINTUSING x,d,i asi sin espacios, siendo invocada directamente bajo ese nombre. Y para cerrar: Publicado en la revista Microhobby Espa~a #27, p-7, seccion trucos y vuelto a publicar en su Especial #1, p-14: 10 REM *** SIMULACION DE *** 20 REM *** PRINT USING *** 30: 40 REM *** INICIALIZACION *** 45: 50 LET SPACE=32: LET E$="" 60 LET CONGCAMPO=15 62 LET ERROR=0 63 LET COMPROBAR=1000 65: 70 FOR_I=1 TO LONGCAMPO 80 LET E$=E$+CHR$(SPACE) 90 NEXT I 95: 100 DEF FN U$(N,L)=E$( TO L-LEN STR% N)+ STR N 110: 120 REM *** ENTRADA DATOS *** 125: 130 INPUT "NUMERO ";NUM 140 INPUT "CAMPO ";LCAMPO 145 GO SUB COMPROBAR 147 IF ERROR THEN LET ERROR= NOT ERROR: GO TO 130 148: 150 PRINT INVERSE 1; FN U$(NUM,LCAMPO) 155: 160 GOTO (130 AND NUM) + (2000 AND NOT NUM) 170: 1000 REM *** COMPROBAR *** 1010 REM *** ERRORES *** 1020 LET ERROR=NOT LCAMPO OR (LEN STR$ NUM>LCAMPO) 1030 RETURN Esta rutina tambien puede ser definida en el SAM como procedimiento y en el QL ya sea como procedimiento o funcion. Si bien estas subrutinas no nos ofrecen todos los formatos de USING, al menos son una buena alternativa para Spectrum o SAM sin expandir. (c)2023 zx_if1@hotmail.com