Sviluppo

Corso di programmazione in REXX - Lezione 3 - nozioni avanzate

Alessandro Cantatore
 

Precedenza degli operatori
La valutazione di un'espressione viene eseguita dall'interprete REXX da sinistra a destra, ma alcuni operatori hanno una maggior precedenza (priorità) di altri e vengono perciò elaborati prima indipendentemente dalla loro posizione.
L'ordine completo di precedenza degli operatori, iniziando da quelli con più alta priorità è:

operatori prefissi \ - +
operatore di elevazione a potenza **
operatori di moltiplicazione e divisione * / % //
operatori di somma e sottrazione + -
operatori di concatenazione " " || abuttal
oparatori di comparazione == = \== \= > < >> << >< <> >= \< >>= \<< <= \> <<= \>>
AND logico &
OR e OR esclusivo | &&
Secondo tali regole si può determinare il risultato di una sequenza di operazioni come:
Say 3 + 2 * 5         /*  mostra '13'    */
Dato che la moltiplicazione (*) ha una priorità superiore alla somma (+), viene prima calcolato il risultato di 2 * 5 e poi viene sommato a 3.
Allo stesso modo, avendo l'operazione di somma (+) una priorità superiore a quella di concatenazione, nell'esempio successivo la somma sarà eseguita prima della concatenazione:
Say 3 2 + 2 5         /* mostra '3 4 5'  */
Le parentesi possono essere usate per forzare la valutazione dell'espressione in un ordine differente da quello causato dalla precedenza degli operatori in quanto le espressioni racchiuse entro le parentesi vengono valutate per prime:
say 6 - 4 + 1        /* mostra '3'  */
say 6 -(4 + 1)       /* mostra '1'  */
say 3 + 2||2 + 3     /* mostra '55' */
say 3 +(2||2)+ 3     /* mostra '28' */

Numeri
Per l'interprete del REXX un programma non è che un insieme di stringhe da valutare. Se una stringa soddisfa le seguenti condizioni il REXX la considera un numero valido:

  • La stringa inizia con un numero, un punto decimale o un segno (+ o -).
  • Le potenze di 10 (numeri in notazione scentifica) sono indicati da E. Questi sono anche detti numeri in virgola mobile.
  • I numeri possono essere racchiusi tra virgolette semplici (') o doppie (") e sono ammessi spazi tra il numero e il segno.
L'argomento dei numeri verrà ulteriormente approfondito in uno dei prossimi capitoli.

Concatenazione
L'operazione di concatenazione può essere eseguita:

  • lasciando uno o più spazi tra i termini. L'interprete del REXX unisce i termini con un solo spazio di separazione.
  • unendo i termini senza lasciare spazi, purché il REXX sia in grado di riconoscerli come separati.
  • usando l'operatore ||.

La funzione substring()
La funzione SUBSTR permette di isolare una parte di una stringa. SUBSTR può essere invocata con 2 o 3 argomenti:

substr(string,n)
substr(string,n,length)
dove:
string è la stringa di cui si vuole isolare una porzione
n è la posizione del primo carattere della substringa che si vuole estrarre da string. I caratteri in string sono contati a partire dal numero 1.
length è opzionale e rappresenta il numero di caratteri della substringa. Se viene omesso tutta la parte di string successiva al carattere n sarà inclusa nella substringa.
Esempi:
say substr("rivelando", 1, 4)      /* mostra "rive"                     */

verbo = "rivelare"                 /* assegna "rivelare" alla variabile */

say substr(verbo, 3)               /* mostra "velare"                   */
say substr(verb, 3, 4)             /* mostra "vela"                     */

Lunghezza delle stringhe
Per calcolare la lunghezza di una stringa si usa la funzione "LENGTH:

n = length(string)
n, il risultato, rappresenta la lunghezza della stringa.
Esempio:
verbo = "rivelare"
say length(verbo)                  /* mostra "8"  */
Il seguente programma richiede all'utente di immettere il nome di un file, se la lunghezza di questo supera gli 8 caratteri ammessi nelle partizioni FAT, il programma mostra un messaggio e accorcia il nome del file:
/* CHKFNAME.CMD */
say "Scrivi il nome di un file"
pull fname"."ext          /* Pull legge il nome del file separandolo */
                          /* dall'estensione                         */
if length(fname) > 8
then
   do
      fname = substr(fname,1,8)
      say "Il nome del file introdotto è troppo lungo! ",
          "Verrà troncato in "fname
   end
L'argomento relativo alle funzioni per la manipolazione delle stringhe verrà approfondito in uno dei prossimi capitoli.

Comparazione
Ci sono due diversi metodi di comparazione di caratteri e stringhe: la comparazione normale e la comparazione esatta.

La comparazione normale ignora gli spazi precedenti e successivi alla stringa e compara carattere per carattere.
La comparazione esatta compara carattere per carattere includendo anche gli spazi.
Il valore di un carattere nella comparazione è determinato in base al suo valore in codice ASCII:

 valore minore -----------------------------------------> valore maggiore
        |
        |             carattere NULL
        |    .../     caratteri di controllo, punteggiatura e speciali
        |   0...9     numeri
        |   A...Z     caratteri maiuscoli
        |   [...`     alcuni caratteri punteggiatura e speciali
        |   a...z     caratteri minuscoli
        |   {...þ     caratteri speciali, semigrafici, lettere accentate
        |
        V
 valore maggiore
Tutti i caratteri vengono comparati secondo il valore ASCII relatiivo alla codepage corrente.

Nella comparazione normale, se entrambi i termini non sono numeri, gli spazi che li precedono o li seguono vengono ignorati, le stringhe più corte vengono riempite di spazi e poi vengono comparate da sinistra a destra un carattere per volta.
Se le stringhe non sono uguali i primi due caratteri differenti determinano il risultato.
Per esempio se compariamo " Formaggio" con "Foro":

   gli spazi precedenti vengono ignorati
     | |
     V V
    | | |F|o|r|m|a|g|g|i|o|
         | | | |
         = = = * -----------------------> "m" < "o"
         | | | |
        |F|o|r|o| | | | | | <---- alla stringa più corta vengono
                                  aggiunti degli spazi

Tramite la comparazione esatta (strict-comparison) si può eseguire una comparazione precisa, carattere per carattere, senza che gli spazi iniziali vengano sottratti o senza che vengano aggiunti spazi finali.

Per controllare che due stringhe siano esattamente uguali si usa il doppio segno di uguale (==).
Per esempio:

  • il valore di "biscotto" = " biscotto" è 1 (VERO)
  • il valore di "biscotto" \= " biscotto" è 0 (FALSO)
  • il valore di "biscotto" == " biscotto" è 0 (FALSO)
  • il valore di "biscotto" \== " biscotto" è 1 (VERO)
Dato che gli spazi hanno un valore ASCII inferiore a quello dei caratteri dell'alfabeto, con la comparazione esatta, il valore di "biscotto" è superiore e a quello di " biscotto".

Per determinare con precisione quale stringa è maggiore o minore, piuttosto che detrminare solo se le stringhe sono differenti come negli esempi precedenti si usano gli operatori >> e <<.
Per esempio:

  • il valore di "banana" >> "biscotto" è 1 (VERO)
  • il valore di "$10" >> "nove" è 0 (FALSO)
  • il valore di "pesce" << "bistecca" è 0
  • il valore di " pesce" << "pesce" è 1 dato che il valore del carattere di spazio è inferiore a quello del carattere "p".
Rappresentando graficamente la comparazione:
   gli spazi precedenti non vengono ignorati
    | |
    V V
   | | |p|e|s|c|e|c|a|n|e|
    |
    *------------------------> " " < "p" quindi "  pescecane" << "pesce"
    |
   |p|e|s|c|e| <--------------- non vegono aggiunti spazi

di solito non si applica la comparazione esatta alle stringhe numeriche perchè la ragione di tale comparazione e comparare valori piuttosto che caratteri.
Se x = "2" e y = "+2":

  • x = y è VERO
  • x \= y è FALSO
  • x == y è FALSO
  • x \== y è VERO
La comparazione esatta può essere utile nel caso si voglia controllare la presenza di zeri non significativi o della notazione esponenziale:
  • 32.000 = 32 è VERO
  • 32.000 == 32 è FALSO
  • 000000 = 0E0000 è VERO
  • 000000 == 0E0000 è FALSO

Operatori Booleani
Gli operatori logici o operatori Booleani modificano e combianano le espressioni.
Essi sono:

  • L'operatore NOT (\) quando precede un termine cambia il suo valore da VERO in FALSO o viceversa.
    Quando precede un operatore di comparazione ne inverte il risultato.
    Per esempio:
    say \ 0                     /* mostra '1'                */
    say \ 1                     /* mostra '0'                */
    say \ 2                     /* mostra messagio di errore */
    
    say \ (3 = 3)               /* mostra '0'                */
    
    frutta = "banane"
    say frutta = "banane"       /* mostra '1'                */
    say frutta = "mele"         /* mostra '0'                */
    say \(frutta = "mele")      /* mostra '1'                */
    say \(frutta = "banane")    /* mostra '0'                */
    
  • L'operatore AND (&) dà un risultato di VERO solo quando entrambi i termini sono veri:
    if pronto = "SI" & risultato = GIUSTO"
    then say "va!"
    
    La frase "va!" viene mostrata solo quando vengono soddisfatte entrambe le condizioni.
  • L'operatore OR (|) dà un risultato di FALSO solo quando sono FALSI entrambi i termini:
    if pronto = "SI" | risultato = GIUSTO"
    then say "va!"
    
    E' sufficiente che una qualsiasi o entrambe le condizioni siano VERE perché il risultato sia anch'esso VERO.
  • L'operatore di OR esclusivo (&&)dà un risultato VERO solo quando uno e solo uno dei termini è VERO.
    if pronto = "SI" & risultato = GIUSTO"
    then say "va!"
    
    La frase "va!" viene mostrata solo quando una sola delle due condizioni è VERA.

Conversione di dati
Il REXX può essere usato per tradurre dati da un set di caratteri ad uno differente o per elaborare dati in formato binario o esadecimale.

In uno dei prossimi articoli tratteremo più approfonditamente l'argomento dell'ingresso e uscita dei dati sotto forma di file e queue.

Sistemi numerali
L'OS/2 usa un set di caratteri standard, chiamato ASCII in cui ad ogni carattere corrisponde un dato codice numerico. Per esempio il carattere "?" ha il valore di 63.
I computer operano su dati in formato binario, che possono cioè assumere solo 2 differenti valori cui ci si può riferire come acceso/spento, si/no, VERO/FALSO o 1/0.
Anche i numeri vengono rappresentati in questo modo. Il numero decimale 63 in un sistema binario viene rappresentato come 00111111.
Ogni cifra indica una potenza di 2 per cui nel precedente esempio 00111111 indica 32 + 16 + 8 + 4 + 2 + 1.
E' questo il modo in cui il carattere di punto interrogativo viene rappresentato nel computer. Ogni carattere viene considerato come un byte un insieme di otto cifre binarie aventi ciascuna un valore di 0 o 1.
Essendo i numeri binari piuttosto scomodi da leggere, i programmatori usano un sistema numerico in base 16 chiamato esadecimale (spesso abbreviato in hex). Ogni cifra di un numero esadecimale rappresenta quattro cifre binarie. Perciò sono sufficienti due sole cifre esadecimali per rappresentare un byte.
I caratteri usati per rappresentare le 16 cifre esadecimali sono:

valore decimale 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
cifra esadecimale 0 1 2 3 4 5 6 7 8 9 A B C D E F
L'equivalente esadecimale di 63 è 3F, cioè 16 * 3 + 15 * 1 corrispondente al carattere "?".

Oltre ai caratteri in formato ASCCI e ai numeri il REXX è in grado di elaborare anche numeri in formato binario e esadecimale.

I numeri in formato binario sono rappresentati come una sequenza di cifre binarie racchiusa da virgolette e seguita immediatamente (senza separazione di spazi) dal carattere "B" o "b".
Sono ammessi spazi nella stringa binaria, ma solo per separare le cifre in gruppi di 4 o 8.

Per rappresentare un numero in formato esadecimale, la sequenza di cifre esadecimali che lo compone deve essere racchiusa tra virgolette ed immediatamente seguita dal carattere "X" o "x" (senza separazione di spazi).
Gli spazi nella stringa sono ammessi solo per separare le cifre in coppie.

Alcuni esempi:

say 37             /* mostra '37' (numero decimale)    */
say "%"            /* mostra '%' (codice ASCII 37)     */
say '25'x          /* equivale a '37' decimale. Mostra */
                   /* il carattere corrispondente: '%' */
say '0010 0101'b   /* equivale a '37' decimale. Mostra */
                   /* il carattere corrispondente: '%' */
Nel caso vengano usati x o b come variabili, in caso di ambiguità, il REXX dà precedenza al loro significato di indicatori di base numerica:
x = 'qui'       /* assegna la stringa "qui" alla variabile x */
say '3F'x       /* mostra il carattere '?' invece di "3Fqui" */

Funzioni di conversione dati
Le seguenti funzioni, incluse nell'interprete REXX, convertono numeri e caratteri da un formato ad un altro:

conversione di n da a binario ASCII esadecimale decimale
binario - X2C(B2X(n)) B2X(n) X2D(B2X(n))
ASCII X2B(C2X(n)) - C2X(n) C2D(n)
esadecimale X2B(n) X2C(n) - X2D(n)
decimale X2B(D2X(n)) D2C(n) D2X(n) -

Il nome delle funzioni di conversione è stato creato in base al seguente significato:

carattere significato
2 converte in
B binario
C carattere ASCII
X esadecimale
D decimale
Esempi:
say B2X(0011 1111)     /* mostra "3F "      */
say X2B(3F)            /* mostra "00111111" */
say C2X(?)             /* mostra "3F"       */
say X2C(3F)            /* mostra "?"        */
say C2D(?)             /* mostra "63"       */
say D2C(63)            /* mostra "?"        */
say D2X(63)            /* mostra "3F"       */
say X2D(3F)            /* mostra "63"       */


[Pagina precedente] [Sommario] [Pagina successiva]