Ciao un po' di tempo fa mi sono trovato ad estrarre dei dati da un file di testo :
1.0 1.1 4.970 136.48 -29.83 [1]
1.0 1.1 4.969 136.48 -29.81 [1]
1.0 1.1 4.978 136.49 -29.73 [1]
ho usato questo metodo:
Dim sPath As String
Dim intfile As File
Dim ntesto As String
Dim vtesto As String
Dim xtesto As String
Dim nrighe As Integer = 0
Dim i As Integer = 0
Dim j As Integer = 0
Dialog.Title = "Apri File" ' apro finestra di dialogo
Dialog.Filter = ["*.txt", ("Text files")] ' seleziono tipo file
GridView1.mode = Select.Multiple
GridView1.Columns.Count = 5
If Dialog.OpenFile() Then Return
intfile = Open Dialog.Path For Input
Label2.Text = File.BaseName(Dialog.Path)
While Not Eof(intfile)
Line Input #intfile, ntesto ' ogni riga del file è una stringa che lavoro in seguito'
If nrighe > 4 Then
GridView1.rows.Count = 1 + i
GridView1[i, 0].Text = Trim$(Left$(ntesto, 17)) ' ricavo dalla stringa i dati che mi sono utili'
GridView1[i, 1].Text = Trim$(Mid$(ntesto, 18, 8))
GridView1[i, 2].text = CFloat(Trim$(Mid$(ntesto, 27, 8)))
GridView1[i, 3].Text = CFloat(Trim$(Mid$(ntesto, 35, 8)))
GridView1[i, 4].Text = CFloat(Trim$(Mid$(ntesto, 43, 8)))
Inc i
Endif
Inc nrighe
vtesto = Mid$(ntesto, 18, 8)
Wend
Close #intfile
questo è valido se i campi sono di lunghezza fissa.
ciao :ciao:
Mi viene in mente qualcosa del genere:
Public Sub Main()
Primo
Secondo
End
Private Sub Primo()
Dim s As String = "123.45 testo qualsasi"
Dim c As String, i As Integer
For i = 1 To Len(s)
c = Mid(s, i, 1)
If Asc(c) > 47 And Asc(c) < 58 Or Asc(c) = 46 Then
Print c;
Endif
Next
Print "\n"
End
Private Sub Secondo()
Dim s As String = "123.45 testo qualsasi"
Dim c As String, i As Integer
For i = 1 To Len(s)
c = Mid(s, i, 1)
If Asc(c) = 32 Then Break
Print c;
Next
End
Ma occorrerebbe sapere se è sempre una sola stringa con un solo numero e composta come da esempuio :-\
;D ecco,
Dim s As String = "123.45 testo qualsasi"
Dim r As Float
r = CFloat(Trim$(Left$(s, 10))) ' i primi dieci caratteri della stringa'
Print r
quello postato in precedenza era riferito ad un file di testo che veniva visualizzato all'interno di una griglia :ciao:
La più breve che mi viene in mente:
Public Sub Main()
Dim s As String = "123.45 testo qualsasi"
Print Scan(s, "*" & Chr(32) & "*")[0]
End
:ciao:
Bravo, Gianluigi.
Eri partito un po' svogliato, al termine della serata hai tirato fuori un'ottima soluzione.
In queste ore dicevo fra me e me: " Possibile mai che non gli venga in mente Scan() e Split() ? ".
Per Split():
Public Sub Main()
Dim s As String = "123.45 testo qualsiasi"
Print Split(s, Chr(32))[0]
End
Aggiungo altre due soluzioni.
Uso della funzione esterna " sscanf( ) ".
Se la stringa prevede il simbolo locale della virgola, anziché il punto, per dividere la parte intera dalla parte frazionaria, oppure se non v'è distizione fra le predette due parti, allora potremo agevolmente...
' int sscanf (const char *__restrict __s, const char *__restrict __format, ...)
' Read formatted input from S.
Private Extern sscanf(__s As String, __format As String, dest As Pointer) As Integer In "libc:6"
Public Sub Main()
Dim s As String = "123,45 testo qualsiasi"
Dim f As Float
sscanf(s, "%lf", VarPtr(f))
Print f
End
Se c'è comunque il punto, allora il codice sarà un po' più complesso:
' int sscanf (const char *__restrict __s, const char *__restrict __format, ...)
' Read formatted input from S.
Private Extern sscanf(__s As String, __format As String, dest As Pointer) As Integer In "libc:6"
Public Sub Main()
Dim s As String = "123.45 testo qualsiasi"
Dim p As Pointer
p = Alloc(SizeOf(gb.Pointer))
sscanf(s, "%s", p)
Print CFloat(String@(p))
Free(p)
End
Volendo usare la funzione esterna "strtod( )", dovremo prevedere il simbolo locale della virgola:
' double strtod (const char *__restrict __nptr, char **__restrict __endptr)
' Convert a string to a floating-point number.
Private Extern strtod(__nptr As String, __endptr As Pointer) As Float In "libc:6"
Public Sub Main()
Dim s As String = "123,45 testo qualsiasi"
Dim f As Float
f = strtod(s, 0)
Print f
End
Possiamo usare anche la funzione esterna memccpy( ):
' void *memccpy (void *__restrict __dest, const void *__restrict __src, int __c, size_t __n)
' Copy no more than N bytes of SRC to DEST, stopping when C is found.
Private Extern memccpy(__dest As Pointer, __src As String, __c As Integer, __n As Long) In "libc:6"
Public Sub Main()
Dim s As String = "123.45 testo qualsasi"
Dim p As Pointer
p = Alloc(SizeOf(gb.Pointer), 1)
memccpy(p, s, 32, CLong(Len(s))) ' 32 è il numero ASCII del carattere dello "spazio"'
Print CFloat(Trim(String@(p)))
Free(p)
End
la verifica più sicura non può che essere quella carattere per carattere
Ci metto qualcosa anch'io al riguardo:
Public Sub Main()
Dim s As String = "123.45 testo qualsasi"
Dim bb As Byte[]
Dim i As Integer
bb = Byte[].FromString(s)
While Not IsSpace(Chr(bb[i]))
Inc i
Wend
bb.Remove(i, Len(s) - i)
Print bb.ToString(0, bb.Count)
End
o se si preferiscono esclusivamente le funzioni stringa:
Public Sub Main()
Dim s As String = "123.45 testo qualsasi"
Dim i As Integer = 1
While Not IsSpace(Mid(s, i, 1))
Inc i
Wend
Print Left(s, i - 1)
End
Ci metto qualcosa anch'io al riguardo:
Ma questo bel codice, comunque non ti salva da possibili errori.
Naturalmente io parlo non dello specifico quesito, ma di codice "vero" tu mi insegni che potresti benissimo incontrare una riga nella quale, per i più svariati motivi, gli spazi sono andati persi...
Non esagerare. Mi sono solo meravigliato che non avessi anche proposto Scan( ) e Split( ), poiché solitamente ne fai ampio uso.
Si devo ammettere che faccio uso di entrambi, visto che un certo vuott me e ce li ha ben spiegati :D
Devo anche dire che Scan lo abbino spesso e volentieri con Try quando non so a cosa posso andare incontro, ad esempio: ;D
If IsNull(sName) Then sName = Scan(s, "*<a id=\"*\">*</a>*<*")[2]
If IsNull(sName) Then Try sName = Scan(s, "*<a id=\"*\">*</a>*<*>*<*")[5]
If IsNull(sName) Then Try sName = Scan(s, "*<a id=\"*\">*</a>*<*>*<*>*<*")[7]
:ciao: :ciao: