Newsgroup: it.comp.lang.visual-basic
Titolo: Stringa e numeri

ciao, e buon anno nuovo.
Ho un problemino per voi forse banale.
Importo in un database di Access 97 un file Articoli.txt
Purtroppo sul db il campo del codice è stato definito numerico,ma capita che 
ci siano delle volte in cui per sbaglio
vengono inseriti dei codici alfaN sul file txt.
Il problema è che io leggo il file ed estraggo con un Mid la stringa e poi 
la assegna al campo.
Ovvio che se è AlfaN mi va in errore.
come faccio a capire prima di assegnare il campo che è AlfaN o solo 
Numerico?
Grazie. 

 Numerico?
aa$=mid(x,x,x)
IsNumeric(aa) => True/False
Mi pare ci fosse qualche eccezione, ma dovrebbe andare.
-- 
DBMS Firebird
VB6 + Ado

 assegna al campo.
Il giro corretto è:
- Ricavi la stringa
- Verifichi se è valida
- Ne interpreti il valore e lo memorizzi in una variabile numerica
- Inserisci quest'ultima nel campo, o attraverso assegnazione al .Value 
o attraverso la composizione di una stringa SQL.
Per semplicità, sarebbe bene che queste operazioni avvenissero mediante 
step distinti anzichè annidando funzioni.
Innanzitutto, cosa fare se il pezzo di stringa non è numerico?
Se vuoi scartare il record, allora basta un IF.
Se vuoi inserire Zero, allora puoi usare Val.
Secondo:
Il campo contiene decimali o è un intero?
Se è un intero, Val va benissimo comunque.
Se contiene decimali, com'è il separatore: fisso o locale di chi genera 
il txt?
Se fisso, puoi sostituirlo col punto (se non lo è già), poi usi Val.
Se locale, dovrai in qualche modo farti un parser che analizza la 
stringa e 'capisce' come interpretare.
Per vedere se il campo è numerico o meno, c'è IsNumeric che però espone 
il fianco alle notazioni scientifiche ed esadecimali. Quindi caratteri 
a caso capiterà che vengano interpretati e convertiti in numeri a caso.
Personalmente utilizzo un poccolo parser che controlla che TUTTI i 
caratteri siano nel range 0-9 o uno dei separatori ammessi (".", ",", 
locale).
Ciao
Alberto
-- 
Max Beerbohm: Tutto ciò che è degno di essere fatto è stato fatto 
ripetutamente. Dalle cose mai fatte bisognerebbe tenersi, sospetto, 
molto alla larga.

 Nel primo caso sistemi l'importazione, nel secondo sistemi il DB.
Io andrei ancora più a monte: come mai ci sono valori sballati nel file?
Questo file è sotto il nostro controllo?
Ciao 

 Ciao
Grazie e tutti.
Dnque il file non è sotto controllo, come non lo è il Db di access 97.
Io ho solo il compito di importare il file di testo prodotto da A e 
modificare le voci presenti o inserirle se nuove sul db B
Il problema sono i dati dentro al file non coerenti con la tipologia dei 
campi sul DB.
Per adesso ho parzialmente risolto mettendo un Isnumeric come suggerito.
Volevo porò approfondire la soluzione che avete abbozzato del "Parser". Cosa 
significa? 

 locale).
Ecco qual era il problema.
E' capitato con alcuni clienti che ricercavano un articolo immettendo l'id
o il codice (char).
Facevo la distinzione con l'isnumeric (mi pare) e codici tipo "0004D5"
venivano interpretati come numeri.
Poi ho fatto una funzione tipo quella che hai indicato.


 significa?
Se non erro si intedeva una funzione che analizza carattere carattere la
stringa
Function IsNum2(num as string) as boolean
dim lLun as long
dim i as long
  isnum2=true
 
  lLun=len(num)
  for i=1 to llun
    select case mid$(num,i,1)
      case "0","1".... "." , "," ecc
      case else
        isnum2=false
        exit For
    End Select
  next i
end function
Una cosa del genere insomma...


 Una cosa del genere insomma...
Capito! Una funzione che analizza carattere per caratter la stringa e  ne 
determina i tipo ed il contenuto!
La parola Parser mi sviava. 

 Una cosa del genere insomma...
Curioso...immagino tu l'abbia scritta al volo, ma a parte disquisire
sull'uso del Select Case (che credo sia la soluzione peggiore, ad
occhio), la cosa che mi incuriosisce e' un'altra.
Io nelle mie procedure faccio l'esatto contrario: segnalo a false le
eventuali variabili di risultato, e poi le metto a true quando e' il
caso.
Cioe'...tu nella procedura sopra entri e prima di qualsiasi cosa, ti
segni che il valore che ti hanno passato e' un numerico. Se poi la
procedura scopre che non lo e', allora corregge quanto deciso prima ed
esce.
Pura curiosita' accademica, ma non e' la soluzione peggiore?
Cioe'...metti che per qualsiasi motivo la procedura sbagli ad uscire,
oppure per sbaglio finisce in un blocco di on error resume next...non
e' meglio segnarsi subito che NON e' un numero?

 e' meglio segnarsi subito che NON e' un numero?
Come faresti per segnalare che non č un numero?
Cioč uno potrebbe mettere false all'inizio, mettere true nel case "0"...
E nel case Else lasciare com'č.
All'On error basterebbe settare a false.
Al posto della Select cosa sarebbe meglio utilizzare? Anche se forse meno
performante la preferisco di gran lunga a IF annidati, soprattuto per la
rilettura.
Si potrebbe fare cosě:
Const VAL_AMMESSI="0123456789.,"
if instr(VAL_AMMESSI,mid$(num,i,1)>0 then
  IsNum2=True
else
  IsNum2=False
  Exit For
endif
Non so se sia piů performante del select case, a quel punto si potrebbe
sostituire il For con un While/Do perchč piů adatto (anche se meno
leggibile imho).


 leggibile imho).
Il codice ASCII, mio caro, il codice ASCII :-)
Otterresti un miglioramento di prestazioni "statistico", ma pur sempre
un miglioramento :-)

 un miglioramento :-)
Cioè tipo
iCar=asc(mid$(num,i,1))
select case iCar
    case 48 to 57,44,46
    case else
end select
Ciao


 end select
Esatto. Anche se io (tanto per rispondere ad un'altra domanda
precedente) con i Select Case non ci sono mai andato a nozze ed avrei
usato un If, ma il concetto e' quello.
Usando il codice ascii, se fai due conti, piu' che enormi vantaggi in
termini di velocita' hai una standardizzazione delle prestazioni. Per
semplificare, fai conto si analizzino solo i numeri (lasciando perdere
virgole e punti).
Usando il codice ascii, riconosci se un carattere e' un numero sempre
con due operazioni di confronto.
Per contro, usando un case con i 10 caratteri numerici, con "1" ci
vuole un confronto, con "2" ce ne vogliono due, con "3" e cosi' via,
fino allo "0" che riconosci dopo 10 confronti.
In un ipotetica stringa "1234567890", con il mio metodo impieghi 18
confronti, con il case segnalato all'inizio ne usi 55, tre volte tanto.
Senza contare i caratteri che non numerici, che finiscono sempre nel
caso peggiore (10 controlli prima di decidere che non sono numeri) .
Altre due cosette:
1) Comunque l'intero parser non funziona se non si usano anche due
variabili booleane per controllare il numero e le posizioni di punti e
virgole (non possono esserci punti dopo la virgola ne' piu' di una
virgola. Senza contare il fatto che i punti devono essere a tre
caratteri l'uno dall'altro)
2) Questa piu' per Albe che altro: il case Y To X genera lo stesso
codice di
if (<=X) AND (>=Y) 
???
Ciao!

 fino allo "0" che riconosci dopo 10 confronti.
???
Select case Asc(Mid(num, i, 1))
Case 48 To 57, 44, 46
Case Else
End select
Select case Mid(num, i, 1)
Case "0" To "9", ".", ","
Case Else
End Select
C'è qualche differenza computazionale che mi sfugge?
Ciao
Raf


Si, il contesto del thread ;-D
Questo era il codice proposto all'inizio:
select case mid$(num,i,1)
      case "0","1".... "." , "," ecc
      case else
        isnum2=false
        exit For
End Select
Il punto non era sul ASCII o meno, ho usato quella terminologia per
distinguere dal caso con To al caso senza To. In effetti mi sono
espresso da cane, pardon ^^;;;

>> sempre con due operazioni di confronto.
volesse dire tutt'altro.
Ciao
;-)
Raf

 ;-)
:-)
Beh, parliamone...io non ho mai scritto in vita mia una roba tipo "A"
to "Z" o roba del genere, ma proprio non mi sarebbe nemmeno mai venuto
in mente ^^;;;

 Pura curiosita' accademica, ma non e' la soluzione peggiore?
Nel contesto di quel tipo di soluzione è più efficiente, visto che il
ciclo for si interrompe prima, altrimenti dovresti analizzare sempre 
e comunque TUTTA la stringa. Nel caso in esame si analizza la stringa
solo fino ad incontrare un carattere non numerico.
-- 
BREAKFAST.COM
 halted... cereal port not responding!
News 2002 [v 2.07] / StopDialer / PopDuster - 
http://www.socket2000.com
Akapulce portal: 
http://www.akapulce.net