Gambas-it

Gambas3 => Programmazione => Topic aperto da: vuott - 24 Marzo 2018, 19:44:13

Titolo: Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 24 Marzo 2018, 19:44:13
Quale codice suggerireste per estrapolare da una stringa la sua parte iniziale formata da caratteri numerici ?

In pratica, avendo ad esempio questa stringa (compresa fra i doppi apici e colorata):
 "123.45        testo qualsiasi"
dovete estrarre soltanto l'intera parte numerica (ossia dal carattere 1 al carattere 5 compreso il punto fra i caratteri "3" e "4", escludendo la parte che va dal primo spazio fino al carattere " i ") e convertirlo nel coerente tipo di valore (in tale caso un tipo Single o un tipo Float ).
Va da sé che quello che mi interessa vedere è soprattutto l'estrazione dei caratteri numerici.

E' ammessa qualsiasi soluzione e qualsiasi risorsa, ma - come sempre - sono preferite quelle più brevi ed eleganti.
Potete indicare più soluzioni.


Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: naderit - 24 Marzo 2018, 20:26:51
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:
Codice: [Seleziona]
 
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:
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 24 Marzo 2018, 20:42:30
Mi viene in mente qualcosa del genere:
Codice: [Seleziona]
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  :-\
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 24 Marzo 2018, 20:43:01
Naderit, perché hai usato l'Oggetto GridView e tutto quel codice ?

(http://snaroenvel.no/wp-content/uploads/2013/05/Overrasket.gif)

Non potresti farne un codice essenziale ?
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 24 Marzo 2018, 20:44:40
Ma occorrerebbe sapere se è sempre una sola stringa con un solo numero e composta come da esempuio  :-\

 :violent:
Pure tu ti ci metti ?

Ragionate sulla stringa dell'esempio. Punto.
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 24 Marzo 2018, 21:08:19

Va da sé che quello che mi interessa vedere è soprattutto l'estrazione dei caratteri numerici.


Il codice da me postato estrae i caratteri numerici
 :ciao:
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: naderit - 24 Marzo 2018, 22:26:06
 ;D ecco,
Codice: [Seleziona]
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:
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 24 Marzo 2018, 23:21:51
La più breve che mi viene in mente:
Codice: [Seleziona]
Public Sub Main()
 
  Dim s As String = "123.45        testo qualsasi"
 
  Print Scan(s, "*" & Chr(32) & "*")[0]
 
End

 :ciao:
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 03:02:03
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():
Codice: [Seleziona]
Public Sub Main()
 
  Dim s As String = "123.45        testo qualsiasi"
 
  Print Split(s, Chr(32))[0]
 
End
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 03:09:40
Codice: [Seleziona]
r = CFloat(Trim$(Left$(s, 10))) ' i primi dieci caratteri della stringa'


Come principio sarebbe accettabile; rischia, però, di non essere universale.
Ad esempio con una stringa di questo genere: "1234567890.1234        testo qualsasi"
o con quest'altra: "8        testo qualsasi" (ove i dieci caratteri vanno a comprendere anche la "t")
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 04:07:16
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...
Codice: [Seleziona]
' 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:
Codice: [Seleziona]
' 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:
Codice: [Seleziona]
' 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( ):
Codice: [Seleziona]
' 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
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 25 Marzo 2018, 09:36:52

In queste ore dicevo fra me e me: " Possibile mai che non gli venga in mente Scan() e Split() ? ".


Veramente stavo guardando un paio di telefilm con mia moglie e poi sono scappato a nanna per via dell'ora legale.  :-[
Comunque tutte le soluzioni "rapide", in un algoritmo "vero" vanno verificate almeno con un Try e se ti restituiscono errore poi la verifica più sicura non può che essere quella carattere per carattere magari includendo anche la virgola oltre ai numeri e al punto, non trovi?

 :ciao: :ciao:
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 14:54:30
.... verificate almeno con un Try....

Ho repulsione di Try anche ben più di Shell.



la verifica più sicura non può che essere quella carattere per carattere
Sì, ritengo sia la base essenziale.
...e infatti le funzioni esterne, da me sopra presentate, compiono anche quella verifica.
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 25 Marzo 2018, 15:15:56
Sì, ritengo sia la base essenziale.
...e infatti le funzioni esterne, da me sopra presentate, compiono anche quella verifica.
Beh allora non capisco il perché tu abbia snobbato i miei primi due codici...
Citazione
Ho repulsione di Try anche ben più di Shell.
:D esagerato.
Try è utile, occorre sempre tener conto dell'imprevisto tipo la classica breve momentanea mancanza di corrente, la sola trappola finale (Catch) non sempre è sufficiente.
Try a volte potrebbe essere addirittura indispensabile o comunque semplificare molto il codice (e la vita del programmatore).
Lo so meglio prevenire che curare ma la prevenzione 100% non è di noi mortali.
 :ciao: :ciao:
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 16:34:38
Beh allora non capisco il perché tu abbia snobbato i miei primi due codici...
Non esagerare. Mi sono solo meravigliato che non avessi anhe proposto Scan( ) e Split( ), poiché solitamente ne fai ampio uso.
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 16:55:45
la verifica più sicura non può che essere quella carattere per carattere
Ci metto qualcosa anch'io al riguardo:

Codice: [Seleziona]
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:
Codice: [Seleziona]
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
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 25 Marzo 2018, 17:34:46
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
Codice: [Seleziona]
  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:

Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 17:38:54
...una riga nella quale, per i più svariati motivi, gli spazi sono andati persi...

E quali sarebbero 'sti motivi ?   ???
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: Gianluigi - 25 Marzo 2018, 17:45:53
...una riga nella quale, per i più svariati motivi, gli spazi sono andati persi...

E quali sarebbero 'sti motivi ?   ???

Di solito si tratta di un errore di battitura di chi ha immesso i dati che dobbiamo leggere
Titolo: Re:Estrarre da una stringa una rappresentazione numerica
Inserito da: vuott - 25 Marzo 2018, 17:52:14
...manca l'adduzione aliena degli spazi.   :D