Ottenere i "reali" valori numerici da una lettura di tipo Stringa di un flusso di dati

Da Gambas-it.org - Wikipedia.

Per varie ragioni a volte può essere necessario effettuare una lettura di taluni dati come tipo Stringa, pur non necessariamente appartenendo ad un file di testo. Ciò può risultare utile in modo particolare quando si devono leggere da un file o altro flusso due o più dati che rappresentano per noi significativi, reali valori numerici. In tal caso, quindi, la stringa, ottenuta dalla lettura del flusso di dati, contiene due più valori numerici di qualsiasi tipo (Short, Integer, etc.), che ovviamente dovranno essere riconvertiti dall'attuale rappresentazione di tipo stringa alla rappresentazione di tipo numerale per ottenenre i loro originari e reali valori.


Soluzione se i valori sono di tipo Byte

Se i valori numerali possono essere espressi dal tipo Byte, allora per trasformare ogni carattere della stringa, ottenuta dalla precedente lettura del flusso, nel corrispondente reale valore numerico di tipo Byte si potrà utilizzare molto agevolmente il metodo .FromString() appartenente alla Classe Byte[]:

Byte[].FromString(stringa) As Byte[]

che riempirà, quindi, gli elementi di una variabile vettoriale di tipo Byte[] dei valori numerici ottenuti dalla conversione di ogni carattere della stringa.

Si procederà alla lettura del valore, contenuto da ciascun elemento del vettore di tipo Byte[], nelle modalità consuete preferite.


Soluzione se i valori sono di tipo avente dimensione superiore al Byte

Nei restanti casi si potrà agire con due modalità.


1a modalità

In questa modalità si terrà conto della posizione di ciascun byte all'interno della sua rappresentazione esadecimale.
Facciamo un esempio, ipotizzando che il file sia costituito dai seguenti 10 byte:

56 34 12 00 44 33 22 11 99 00

che rappresentano in successione due Interi ed uno Short:

Public Sub Main()

 Dim s As String
 Dim i1, i2 As Integer
 Dim sh As Short
 
 s = File.Load("/percorso/del/file/da/leggere")

' Tenendo conto che il valore è rappresentato in "Little-Endian": [nota 1]
 i1 = Asc(s, 1)
 i1 += Asc(s, 2) * 256        ' &0100
 i1 += Asc(s, 3) * 65536      ' &010000
 i1 += Asc(s, 4) * 16777216   ' &01000000 

 i2 = Asc(s, 5)
 i2 += Asc(s, 6) * 256
 i2 += Asc(s, 7) * 65536
 i2 += Asc(s, 8) * 16777216

 sh = Asc(s, 9)
 sh += Asc(s, 10) * 256

 Print i1
 Print i2
 Print sh

End


Uso di una variabile di tipo Puntatore

Questa modalità prevede la crazione di una variabile di tipo Puntatore con la funzione VarPtr(), che avrà come parametro la variabile stringa contenente i dati ottenuti dalla precedente lettura del flusso.

Successivamente si provvederà a dereferenziare la variabile Puntatore mediante le specifiche funzioni fornite da Gambas (Short@(), int@(), etc.), per poter ottenere i reali valori numerici.


Facciamo un esempio, ipotizzando che il file sia costituito dai seguenti 18 byte:

44 44 44 00 33 33 33 00 22 00 11 11 11 11 11 11 11 00

che rappresentano in successione due Interi, uno Short ed un Long.

Per ricavare i numeri dei predetti tipi rappresentati da quei byte, possiamo procedere come segue:

Private s As String


Public Sub Main()

 Dim p As Pointer
 Dim i1, i2 As Integer
 Dim sh As Short
 Dim l As Long
 
' Leggiamo il file come testo e salviamo i dati nella variabile di tipo stringa "s":
 s = File.Load("/percorso/del/file/da/leggere")

' Dalla variabile stringa "s" generiamo una variabile di tipo "Puntatore" mediante la funzione "VarPtr()":
 p = VarPtr(s)

' Infine, vediamo in console i "reali" valori numerici, dereferenziando il Puntatore tenendo conto dei byte di memoria occupati da ciascun tipo di valore:
 Print Int@(p)
 Print Int@(p + 4)
 Print Short@(p + 8)
 Print Long@(p + 10)
      
End


Note

[1] Se fosse rappresentato, invece, in "Big-Endian", la conversione sarebbe:

i = Asc(s, 1) * 16777216   ' &01000000 
i += Asc(s, 2) * 65536     ' &010000
i += Asc(s, 3) * 256       ' &0100
i += Asc(s, 4)