View Full Version : [c#] Indice oltre i limiti della matrice.
Andrea993
29-08-2010, 20:49
Sto programmando un applicazione e mi sono imbattuto in questo strano errore
Indice oltre i limiti della matrice.
Il progetto viene compilato ma quando arriva a questa linea dove devo tagliare una stringa si blocca dando l'errore sopra citato.
string pippo= files_trovati[i].Remove(0, files_trovati[i].Length - 3);
La cosa strana che se metto un breakpoint su questa riga e la eseguo manualmente non da l'errore.
Avete qualche idea? Grazie in anticipo
le possibilità sono molto poche. Quella riga di codice è critica in due casi. la i che può andare fuori dalla dimensione massima del tuo indice e il comando remove dove al secondo membro dai per scontato che la string asia più lunga di 3.
Dovrei vedere più cosice per dirti dov'è l'errore. Ad ogni modo mi sembra di capire che hai un array di file e vuoi ottenere solo le estesioni giusto?
nel qual caso perchè non usare il tipo fileinfo e un pò di Linq?
Dai uno sgardo quà
static void Main(string[] args)
{
string[] files = {"pippo.txt", "pluto.jpg", "paperino.pdf", "topolino.csv"};
files = files.Select(i => new FileInfo(i).Extension).ToArray();
foreach (var estensione in files)
{
Console.WriteLine(estensione);
}
Console.ReadLine();
}
risultato a video:
.txt
.jpg
.pdf
.csv
Andrea993
29-08-2010, 21:23
Non è nessuna delle due cose.
La i è uguale a 0
La stringa ha almeno 30 caratteri.
Ma il fatto è che funziona se si va con il debug!
Ah sì altra cosa strana è che anche se ha dato l'errore il valore di pippo è giusto!
Qui c'è un problema simile ma non ho capito la soluzoine se chi è più esperto ci da un occhiata...
http://www.dotnethell.it/forum/messages.aspx?ThreadID=29954
l'errore segnalato nell'altra pagina è un errore generato dai thread e non credo che tu stia facendo uso di thread.
forse non ci siamo capiti prima.
se vuoi che possiamo capire dove sta l'errore devi farci vedere il codice. quella riga da sola vuol dire tutto e niente.
Ciao non ho ancora avuto tempo di analizzare bene il tuo codice.
In tanto ti posso dire che già nel primo for utilizzi una variabile int b = 0 che poi non incrementi mai....
sei sicuro di non esserti dimenticato qualcosa?
cmq appena ho tempo lo guardo bene
Allora ho guardato con più calma... ci sono tanti errori e tanti punti inutili o mal progettati.
Per tua comodità ti riposto il tuo codice commentato da me e successivamente un esempio di come sistemarlo un pò, tieni conto che non capisco bene quello che vuoi fare e molto probabilmente anche il mio codice si potrebbe ulteriormente migliorare... e di molto sapendo quello che deve fare. Per il momento mi sono limitato a togliere errori e ridondanze strane
questo è il tuo codice commentato:
class Program
{
static string[] dir_trovate;
static string[] files_trovati;
static int indice;
static string strtemp;
static void Main(string[] args)
{
string[] arg = new string [10];
arg[0] = @"C:\";
files_trovati = Directory.GetFiles(arg[0], "*.*", SearchOption.AllDirectories);
dir_trovate = Directory.GetDirectories(arg[0], "*", SearchOption.AllDirectories);
for (var i = 0; i < files_trovati.Length; i++)
{
//Questa variabile b che utilizzi non viene mai incrementata da nessuna parte... che senzo ha?
//a questo punto converrebbe la forma for (; i < 355;i++ ) N.B. ricorda che in un for tutti i parametri sono opzionali,
//quindi se non ti servono è inutile crearli
//Inoltre non capisco perchè utilizzi di nuovo i in questo for.... per forza che hai problemi sugli indici.... stai già utilizzando i nel for precedente....
for (var b = 0; i < 350; i++)
{
//Quì non capisco che controllo fai, la variabile b sarà sempre uguale a 0 perchè l'hai dichiarata così e non la
//incrementi mai, quindi cosa vuol dire questo if?
if (b != 1 | b != 5)
{
//Uguale a prima.... vedi sopra
if (b < 10)
{
//string pippo= files_trovati[i].Remove(0, files_trovati[i].Length - 3);
//la linea sopra voglio integrarla dentro l'if come ho fatto sotto...era solo x prova
//Ricerdati che puoi usare il string.format per formattare un intero in modo che torni una stringa lunga 2 e quindi conun eventuale 0 davanti
//Vedi il mio esempio sotto per chiarimenti
if (files_trovati[i].Remove(0, files_trovati[i].Length - 3) == "r" + "0" + Convert.ToString(b))
{
string pippo = files_trovati[i].Remove(0, files_trovati[i].Length - 3);
File.Delete(files_trovati[i]);
}
if (files_trovati[i].Remove(0, files_trovati[i].Length - 2) == "0" + Convert.ToString(b))
{
File.Delete(files_trovati[i]);
}
if (files_trovati[i].Remove(0, files_trovati[i].Length - 2) == "h" + "0" + Convert.ToString(b))
{
File.Delete(files_trovati[i]);
}
}
//if else inutile per quello spiegato sopra.... vedi esempio sotto
else
{
if (files_trovati[i].Remove(0, files_trovati[i].Length - 3) == "r" + Convert.ToString(b) | files_trovati[i].Remove(0, files_trovati[i].Length - 4) == "r" + Convert.ToString(b))
{
File.Delete(files_trovati[i]);
}
if (files_trovati[i].Remove(0, files_trovati[i].Length - 2) == Convert.ToString(b) | files_trovati[i].Remove(0, files_trovati[i].Length - 3) == Convert.ToString(b))
{
File.Delete(files_trovati[i]);
}
if (files_trovati[i].Remove(0, files_trovati[i].Length - 2) == "h" + Convert.ToString(b) | files_trovati[i].Remove(0, files_trovati[i].Length - 3) == "h" + Convert.ToString(b))
{
File.Delete(files_trovati[i]);
}
}
}
//Che controllo è? esiste per forza il file, te l'ha tornato la funzione getFiles...... non può non esistere
if (File.Exists(files_trovati[i]))
{
//variabili superflue, puoi alleggerire vedi esempio sotto
indice = files_trovati[i].LastIndexOf("\\");
strtemp = (files_trovati[i].Remove(0, indice + 1));
try
{
//più velocee comodo un substring perchè non calcoli tutte le volte il lenght della stringa.... vedi sotto
if (strtemp.Remove(9, strtemp.Length) == "PtiQwerty")
{
//Anche quì la o è inutile in qualndo darebbe false all'if solo se strtemp == "PtiQwertyItalian.rsc" && strtemp == "PtiQwertyEnglish.rsc" cosa impossibile
//Penso tu volessi mettere una E.... guarda esempio sotto
if (strtemp != "PtiQwertyItalian.rsc" | strtemp != "PtiQwertyEnglish.rsc")
{
File.Delete(files_trovati[i]);
}
}
}
//i catch vuoti sono abbastanza inutili, trampi le eccezioni senza neanche tracciarle...
catch { }
try
{
//Stesso discorso... meglio un substring
if (strtemp.Remove(3, strtemp.Length) == "Pti")
{
//Stesso discorso volevi mettere la E
if (strtemp != "PtiItalian.rsc" | strtemp != "PtiEnglish.rsc" | strtemp != "ptidecumacore.dll")
{
File.Delete(files_trovati[i]);
}
}
}
catch { }
strtemp = null;
}
}
}
for (int i = 0; i < dir_trovate.Length; i++)
{
//Come sopra utilizzi b e poi incrementi i che per altro già la utilizzi nel for precedente.... proprio non ha senso e fa casino con gli indici perchè
//come sopra questo ciclo ti porta i a 350 poi invece che andare alla directory successiva il prossimo giro andrà alla dir_trovate[351].....
//ma che senso ha?
for (int b = 0; i < 350; i++)
{
try
{
//b non potrà mai essere < 0, tutto inutile, vedi esempio sotto
//se invece volevi scrivere < 10 e hai sbagliato a digitare ti riporto all'altro if sopra.... è un controllo inutile, usa lo string format
//per aggiungere uno 0 davanti all'intero se < 10 e non un if
if (b < 0)
{
if (dir_trovate[i].Remove(0, dir_trovate[i].LastIndexOf("\\") + 1) == "0" + Convert.ToString(b))
{
Directory.Delete(dir_trovate[i], true);
}
}
}
catch { }
try
{
//b è sempre > 0, if inutile, vedi esempio sotto
if (b > 0)
{
if (dir_trovate[i].Remove(0, dir_trovate[i].LastIndexOf("\\") + 1) == Convert.ToString(b))
{
Directory.Delete(dir_trovate[i], true);
}
}
}
catch { }
}
}
}
}
Questo è l'esempio mio con un pò di accorgimenti:
static string[] _dirTrovate;
static string[] _filesTrovati;
static int _indice;
static string _strtemp;
static void Main(string[] args)
{
var arg = new[]{@"C:\"};
_filesTrovati = Directory.GetFiles(arg[0], "*.*", SearchOption.AllDirectories);
_dirTrovate = Directory.GetDirectories(arg[0], "*", SearchOption.AllDirectories);
foreach (var file in _filesTrovati)
{
for (var b = 0; b < 350; b++)
{
if (b != 1 && b != 5)
{
if (file.Remove(0, file.Length - 3) == string.Format("r{0:00}", b))
{
string pippo = file.Remove(0, file.Length - 3);
File.Delete(file);
}
if (file.Remove(0, file.Length - 2) == string.Format("{0:00}", b))
{
File.Delete(file);
}
if (file.Remove(0, file.Length - 2) == string.Format("h{0:00}", b))
{
File.Delete(file);
}
}
if (!File.Exists(file)) continue;
_strtemp = (file.Substring(0, file.LastIndexOf("\\")+ 1));
try
{
if (_strtemp.Substring(0,9) == "PtiQwerty")
{
if (_strtemp != "PtiQwertyItalian.rsc" && _strtemp != "PtiQwertyEnglish.rsc")
{
File.Delete(file);
}
}
}
catch (Exception e)
{
throw;
}
try
{
if (_strtemp.Substring(0,3) == "Pti")
{
if (_strtemp != "PtiItalian.rsc" && _strtemp != "PtiEnglish.rsc" && _strtemp != "Ptidecumacore.dll")
{
File.Delete(file);
}
}
}
catch (Exception e)
{
throw;
}
_strtemp = null;
}
}
foreach (var t in _dirTrovate)
{
for (var b = 0; b < 350; b++)
{
try
{
if (t.Remove(0, t.LastIndexOf("\\") + 1) == b.ToString())
{
Directory.Delete(t, true);
}
}
catch { }
}
}
}
Andrea993
30-08-2010, 23:19
Grazie mille mi hai veramente fatto un enorme piacere, ci sono poche persone disponibili come te.
Ho fatto molti errori di svista ad esempio quello che begli if scrivo int b e poi uso b.
Poi non so a cosa serve questo: ("{0:00}", b))
Non l'avevo mai visto, altra cosa iop usavo la distinzione di numeri minori di 10 e numeri maggiori di 10 a casua del fatto che le cartelle o i file da cancellare quando sono minori di 10 invece di chiamrsi 1,2,3 si chiamano 01,02,03.
E non mi sembra di aver visto tale distinzione nel tuo codice, o mi sbaglio???
Perchè non vorrei sbagliarmi.
Comunque grazie mille, davvreo gentilissimo
A sì e poi un altra cosa a cosa serve "Exception e" che metti in catch??
EDIT: Ho rivisto applicato il tuo codice è devo dire che è una meraviglia ho trovato solo un paio di banali errori di svista, ma non sapendo neanche quello che deve fare il codice averlo intuito con così tanta facilità mi sembra da geni.
Magari essere io come te.
Posto il codice finale
static string[] _dirTrovate;
static string[] _filesTrovati;
static int _indice;
static string _strtemp;
static void Main(string[] args)
{
var arg = new[] { @"C:\Users\Andrea\Desktop\pippo" };
_filesTrovati = Directory.GetFiles(arg[0], "*.*", SearchOption.AllDirectories);
_dirTrovate = Directory.GetDirectories(arg[0], "*", SearchOption.AllDirectories);
foreach (var file in _filesTrovati)
{
for (var b = 0; b < 350; b++)
{
if (b != 1 && b != 5)
{
if (file.Remove(0, file.Length - 3) == string.Format("r{0:00}", b))
{
string pippo = file.Remove(0, file.Length - 3);
File.Delete(file);
}
if (file.Remove(0, file.Length - 2) == string.Format("{0:00}", b))
{
File.Delete(file);
}
if (file.Remove(0, file.Length - 2) == string.Format("h{0:00}", b))
{
File.Delete(file);
}
}
if (!File.Exists(file)) continue;
_strtemp = (file.Remove (0, file.LastIndexOf("\\") + 1));
try
{
if (_strtemp.Substring(0, 3) == "Pti")
{
if (_strtemp != "PtiItalian.rsc" && _strtemp != "PtiEnglish.rsc" && _strtemp != "Ptidecumacore.dll" && _strtemp != "PtiQwertyItalian.rsc" && _strtemp != "PtiQwertyEnglish.rsc")
{
File.Delete(file);
}
}
}
catch (Exception e)
{
throw;
}
_strtemp = null;
}
}
foreach (var t in _dirTrovate)
{
for (var b = 0; b < 350; b++)
{
try
{
if (t.Remove(0, t.LastIndexOf("\\") + 1) == string.Format("{0:00}",b)&& b!=1 && b!=5)
{
Directory.Delete(t, true);
}
}
catch { }
}
}
}
Poi non so a cosa serve questo: ("{0:00}", b))
il string.format serve proprio a formattare una stringa dando volendo anche dei pattern... quel "{0:00}",b vuol dire proprio metti la variabile b in posizione 0 e formattala secondo il pattern 00, cosa vuol dire? vuol dire che se b=3 allora la stringa risultante sarà 03, se vale 8 sarà 08 e se vale 11 sarà 11....
Ecco perchè non serve più l'if di controllo quando b<10 o >10, lo 0 in più lo mette già se necessario....
Per le Exception....
quando fai un try catch nel catch puoi intercettare la eventuale eccezione che si scatena, per intercettarla devi appunto dichirarla nel catch.
try
{
...
}
catch(Exception e)
{
Messagebox.Show(e.message);
}
Questo blocco di codice intercetta una qualsiasi eccezione generata dal blocco try e la stampa su una message box.
Ovviamente puoi intercettare specifiche tipologie di eccezzione, ogni metodo può scatenerare tipologie ben definite di eccezione, Exception e invece le intercetta tutte in quanto generico... Però puoi modificare il codice precedente in
try
{
//....
}
catch (ArgumentNullException argomentoNullo)
{
Console.WriteLine("eccezione di tipo Argomento nullo: " + argomentoNullo.Message);
}
catch (Exception eccezzioneGenerica)
{
Console.WriteLine("Eccezzione generica: " + eccezzioneGenerica);
}
finally
{
Console.WriteLine("istruzioni da eseguire sempre");
}
In questo modo finirai nel primo catch solo se scateni una eccezzione di tipo argomento nullo, invece entrerai nel secondo catch se scatenerai una qualsiasi eccezzione che non rientra nel primo caso, il finally invece serve per eseguire una porzione di codice sempre anche se è stata scatenata una eccezzione (ad esempio quando lavori coi file le varie operazioni le inserisci in un try, il catch lo usi per gestire eventuali errori di IO, e in finally magari ci metti la chiusura di eventuali stream)
Ad ogni modo guardati qualche articolo sulle eccezzioni che quì non posso trattare l'argomento per esteso se no non finiamo più. Per il resto il codice è ancora scarso di controlli, e probabilmente sapendo cosa deve fare si potrebbero evitare parecchi if e qualche ciclo, prova a chiudere visual studio e ad analizzare bene la cosa sulla carta, vedrai che quando riapri visual studio lo riscrivi mooooolto meglio. eheheheh
ciao
Andrea993
31-08-2010, 09:33
Grazie mille sei un ottimo maestro ;) Ho risistemato il codice devo dire che è venuto una meraviglia con la gestione degli errori e relativo codice d'uscita, ho risparmiato altri if...
Grazie ancora
di nulla....
ciao a presto
Andrea993
07-09-2010, 14:00
Ciao, ho notato un problema nel codice, con la formattazioe della stringa "{0:00}",b cìè il problema che trova anche i file che hanno 2 zeri prima del numero, ad esempio 004 e questo non deve succedere.
Grazie in anticipo
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.