Indice oltre il limiti della matrice VB2008 Express

sabato 20 febbraio 2010 - 15.39

mozempk Profilo | Newbie

Salve a tutti ragazzi, intanto complimenti vivissimi per il sito!
ma convenevoli apparte, vi espongo il mio problema:
io ho un file, chiamto contatti.txt il cui contenuto è qualcosa di simile

=========================================
Email Address: email@email.it
=========================================

ripetuto per n volte, io necessito di ritagliare gli indirizzi email ed utilizzarli come destinatari per un messaggio di posta.
ecco il mio codice di ritaglio:
Dim con(1000) 'As String Dim i As New Integer Dim k As IO.StreamReader = New IO.StreamReader("contatti.txt") Dim Strem 'contenitore email Dim lenstr Dim lenmail For i = 0 To 10 con(i) = k.ReadLine Next i = 0 For b = 0 To UBound(con) 'se il primo carattere della riga è un = salta la riga If con(i).Chars(1) = "=" Then i = i + 1 Else 'taglio la mail lenstr = con(i).Length lenmail = lenstr - 20 Strem = (con(i).Substring(20, lenmail)) Text1.Text = Text1.Text & Strem i = i + 1 End If 'se trova una riga vuota salta e va avanti If con(i).Chars(1) = "" Then i = i + 1 Next
il problema è che: appena la mia variabile i raggiunge il valore 4 il prog va in errore sostenendo che la l'indice sia oltre i limiti della matrice, ma la mia matrice ha come limite massimo 1000...
sono 2 notti che tento di trovare una soluzione, senza risultati, confido in un vostro aiuto!
Grazie in anticipo
Giancarmine
ps. spero di aver postato nella giusta sezione del foro... in caso contrario, chiedo scusa in anticipo

aiedail92 Profilo | Expert

Ciao Giancarmine

Ci sono diverse cose che non vanno nel tuo codice, provo a spiegartele:

Dim con(1000) 'As String
Qui hai commentato As String, generalmente è buona pratica tipizzare le variabili; inoltre definisci un array di 1000 elementi, senza sapere quanti effettivamente ne serviranno. In alcuni casi può essere un enorme spreco, in altri potrebbero non bastare...

Dim i As New Integer
Qui l'utilizzo dell'operatore New non serve, è solo lavoro aggiuntivo inutile per il programma

Dim k As IO.StreamReader = New IO.StreamReader("contatti.txt")
Questo di per sé non ha niente di male, ma è più comoda e leggibile la sintassi abbreviata:
Dim k As New IO.StreamReader("contatti.txt")
Inoltre, è buona pratica rilasciare esplicitamente le risorse come i file quando non sono più necessarie, chiamando la funzione Dispose oppure usandole in un costrutto Using

Dim Strem 'contenitore email Dim lenstr Dim lenmail
Vale lo stesso di prima, dichiara sempre anche il tipo di dati che conterranno, nel tuo caso String, Integer e Integer. Inoltre, cerca di utilizzare nomi descrittivi e chiarificativi per le variabili.

For i = 0 To 10 con(i) = k.ReadLine Next
Come fai a sapere in anticipo che ci saranno solo 11 righe? E perché creare un array di 1000 elementi per 11 righe e basta?

For b = 0 To UBound(con)
Dichiara sempre il tipo delle variabili (b As Integer); inoltre è sconsigliato l'utilizzo delle vecchie funzioni stile VB6. Al posto di
UBound(con) usa con.Length - 1

'se il primo carattere della riga è un = salta la riga If con(i).Chars(1) = "=" Then
Qui dici "se il primo carattere", però attenzione! Gli indici sono numerati a partire dallo 0, non da 1... Con “con(i).Chars(1)” quello che fai è verificare il secondo carattere, non il primo

i = i + 1
E già che ci sono, ti consiglio di usare la forma abbreviata “i += 1”

lenstr = con(i).Length lenmail = lenstr - 20
Qui usi ‘lenstr - 20’ per ricavare la lunghezza dell'email, ma seguendo il formato che hai indicato, la lunghezza corretta sarebbe ‘lenstr - 15’, e di conseguenza anche
Strem = (con(i).Substring(20, lenmail))
Deve diventare
Strem = con(i).Substring(15, lenmail)
(Ho anche rimosso un paio di parentesi, che erano inutili e sfavorivano la leggibilità)

TextBox1.Text = TextBox1.Text & Strem
Attento che così scriverai tutte le email una di fila all'altra, senza spazi. Inoltre, consiglio di usare la funzione AppendText al posto del concatenamento, che dovrebbe essere più efficiente:
TextBox1.AppendText(Strem & VbCrLf) ' Aggiunge una nuova riga dopo l'email ' Oppure TextBox1.AppendText(Strem & " ") ' Aggiunge uno spazio dopo l'email

i = i + 1
Come prima

'se trova una riga vuota salta e va avanti If con(i).Chars(1) = "" Then i = i + 1
Anche qui, “con(i).Chars(1)” prende il secondo carattere, non il primo. Inoltre è sbagliato usarlo, ed è qui che viene sollevata l'eccezione di cui tu parli. Se la stringa è vuota, non avrà nessun carattere al suo interno, quindi “Chars(1)” solleva l'eccezione IndexOutOfRangeException, così come farebbe “Chars(0)”. Il modo corretto di verificare se una stringa è vuota è usare la funzione String.IsNullOrEmpty, oppure confrontare la proprietà Length con 0:
If String.IsNullOrEmpty(con(i)) Then i += 1 ' Oppure If con(i).Length = 0 Then i += 1


Detto questo, io cambierei approccio, usando uno di questo genere:

' Uso il costrutto Using per rilasciare automaticamente ' la risorsa alla fine del blocco Using stream As New IO.StreamReader("C:\contatti.txt") ' Leggo fino alla fine del file Do Until stream.EndOfStream ' Leggo una riga Dim line As String = stream.ReadLine() ' Riga vuota? La salto If line.Length = 0 Then Continue Do ElseIf line(0) = "=" Then ' Riga che inizia con =, la salto Continue Do Else ' Una riga contenente un'email. Taglio l'email Dim lenmail As Integer = line.Length - 15 Dim mail As String = line.Substring(15, lenmail) TextBox1.AppendText(mail & " ") End If Loop End Using

Ovviamente funziona solo se sei sicuro che il formato del file è quello lì, e che nessuno ti fa qualche scherzetto...

Luca

alexmed Profilo | Guru

Ciao

Farei solo una piccola modifica
Più che "saltare" le righe vuote verificherei che la linea che mi interessa contenga un'indirizzo email.
In questo modo non considera anche le linee che iniziano con "="

Posto il codice:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Ciao

alexmed

mozempk Profilo | Newbie

Grandissimooooo Luca!!! :D grazie mille miliardi!!!! :D come avrai capito sono abbastanza nuovo a vb... sto ancora studiando, ti ringrazio molto, il tuo codice funziona a meraviaglia, e grazie mille per esserti dilungato nella correzione passo passo del mio codice e per i preziosi consigli ceh seguirò sicuramente
Grazie anche a gli altri che hanno risposto...
un saluto e alla prossima
Giancarmine

alexmed Profilo | Guru

Se hai risolto allora dovresti cliccare su "Accetta" al post di Luca così chiudi il Thread

Ciao

alexmed
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5