Index was outside the bounds of the array ??

0

Witam

Jestem poczatkujacym programista i mam problem z takim kodem

public static string[] czytaj_polozenie()
		{
		odczyt = port_res.ReadExisting();
		Res.res = Res.odczyt.Split(',');
		res[0]=res[0].Replace('.',',');
		res[1]=res[1].Replace('.',',');
		res[2]=res[2].Replace('.',',');
		return res;
		}

Chodzi o to ze czytam dane z RS232 w postaci xx.xxxx,xx.xxxxx,xx.xxxxx gdzie x to cyfry
i ta funcja ... wiadomo co robi .. potem dane te wswietlam na formie w textboxach

void Timer1Tick(object sender, System.EventArgs e)
		{
			
			Res.res=Res.czytaj_polozenie();
			tb_res1.Text=Res.res[0];
			tb_res2.Text=Res.res[1];
			tb_res3.Text=Res.res[2];
						
		}

jak na razie wszystko ok Problem pojawia sie gdy chce zrobic to samo w innym miejscu programu

public static void start(int ilosc_projekcji,int odstep_czasu)
		{
			do
			{
			jakas_funkcja()
			
			Res.res=Res.czytaj_polozenie();
						
			}
			while (Convert.ToDouble(Res.res[0]) > 2.0 );
		}

przy uruchomieniiu tej f-cji wywala blad
"Wyjątek System.IndexOutOfRangeException został wywołany w debugowanym:
Index was outside the bounds of the array." :/

Przeciez nie wychodze poza index tabeli ???

bardzo prosze o pomoc

0

to znaczy ze linijka Res.res = Res.odczyt.Split(','); nie zwrocila Ci tablicy 3elementowej, a to oznacza ze linijka odczyt = port_res.ReadExisting(); nie doczytala prawidlowo danych - moze <ort>w ogóle</ort> odczytala pustego stringa i potem split zwrocil Ci tablice jednoelementowa - pustego stringa

0

dzięki quetzalcoatl !! a czy mógłbyś mi podpowiedzieć ja zmienić kod tak żeby się ten problem nie pojawiał?? Chodzi o to ze kontroler wysyła co jakieś 0,25 s taki ciąg znaków jak wspomniałem. Jak uniknąć pustych stringów ??? Czym zastąpić ReadExisting() lub co zmienić??

0

jesli nie jestes w stanie podpiac sie pod kontroler zdarzeniowo, tak zeby za kazda transmisja byla twoja metoda jakas wywolywana (to by bylo najlepsze.. ale pewnie sie nie da zrobic albo jest trudne..), to musisz caly czas skanowac port czy aby cos nie przyszlo - pewnie juz to w tej chwili robisz i jest ok. musisz natomiast bezwzglednie poprawic obsluge odczytanych danych.. najprosciej uzywajac trywialnego IF:

public static string[] czytaj_polozenie()
{
odczyt = port_res.ReadExisting();
res = odczyt.Split(',');
if(res.Length != 3) // <- tu
return null; // <- taj
res[0]=res[0].Replace('.',',');
res[1]=res[1].Replace('.',',');
res[2]=res[2].Replace('.',',');
return res;
}

i oczywiscie potem sprawdzac czy udalo sie odczytac
<code class="c#">void Timer1Tick(object sender, System.EventArgs e)
{
    res=czytaj_polozenie();
    if(res != null)                // <- tu
        return;                     // <- taj
    tb_res1.Text=Res.res[0];
    tb_res2.Text=Res.res[1];
    tb_res3.Text=Res.res[2];
}

nie krepuj sie zorganizowac owa kontrole w inny sposob, to jest tylko przyklad. pamietaj zeby sprawdzac czy odczyt sie udal wszedzie gdzie uzywasz funkcji czytaj_polozenie()

0

witam ponownie

Zmienilem kod wg. wskazowek i znów pojawia sie problem

"Object reference not set to an instance of an object"

void Timer1Tick(object sender, System.EventArgs e)
{

		Res.res=Res.czytaj_polozenie();
		if(Res.res != null)               
        return;    
		tb_res1.Text=Res.res[0];   <---- tu debuger" wywala" błąd
		tb_res2.Text=Res.res[1];
		tb_res3.Text=Res.res[2];
	}

:(

0

zrobilem jeszcze inaczej :

public static string[] czytaj_polozenie()
{
odczyt = port_res.ReadExisting();
Res.res = Res.odczyt.Split(',');

	if(res.Length != 3) czytaj_polozenie();
	
	res[0]=res[0].Replace('.',',');
	res[1]=res[1].Replace('.',',');
	res[2]=res[2].Replace('.',',');
	
	return res;
	}

teraz jest prawie ok tylko nie wiem dlaczego wywala co chwlie

Wyjątek System.StackOverflowException został wywołany w debugowanym:
<null reference="reference">

ReadExisting()
czytaj_polozenie() - c:\Documents and Settings\Moje Dokumenty\SharpDevelop Projects\attocube\Res.cs:44,3
(...)

0

#1:

"Object reference not set to an instance of an object" oznacza ze probowales wykonac operacje na obiekcie ktorego nie ma -- zmienna ma wartosc null.
moze to sie pojawic w linii tb_res1.Text=Res.res[0]; tylko wtedy gdy tb_res1 jest rowne null. Res, ani Res.res na pewno nie jest rowne null poniewaz jesli Res bylby null to wysypalaby sie linijka wyzej, a jesli Res.res bylby null -- to by linijka wyzej wykonala return

#2:
masz blad logiczny - nieskonczona rekursje - co powoduje wywolywanie funkcji w fukncji w funkcji w fukcji i tak pareset/paretysiecy razy i w koncu konczy sie stos = stack overflow

.. aha.. i wez uzywaj oznakowania CODE wokol kodu..

public static string[] czytaj_polozenie()
{
    odczyt = port_res.ReadExisting();
    Res.res = Res.odczyt.Split(',');
                
    if(res.Length != 3) czytaj_polozenie();  // <- tutaj wolasz "siebie"
                                            // zakladajac ze paczki caly czas nie ma na porcie
                                            // to ten nowy "ja" wywola jeszcze jednego "mnie"
                                            // zakladajac ze ciagle paczki caly czas nie bedzie
                                            // to ten trzeci "ja" wywola czwartego "mnie"
                                            // i tak dalej
    res[0]=res[0].Replace('.',',');
    res[1]=res[1].Replace('.',',');
    res[2]=res[2].Replace('.',',');

    return res;
}
0

Racja !! taka rekurencja się nie kończy !! to nie byl dobry pomysl. Wlsciwie rozwiazalem juz problem, ale pojawil sie nastepny. Chodzi o to ze czasem w Res.res[0], Res.res[1] Res.res[2] pojawiaja sie smieci (tzn

  • albo ciagi typu .xxxx ,albo liczy ktore nie powinny sie pojawic ,albo puste ciagi albo co najdziwniejsze jakies kwadraciki zamiast cyfr) Podejrzewam ze problem pojawia sie juz przy odczycie danych z kontrolera. To jest tak ze kontroler nadaje ciagi takie jak opisalem w okreslonych odstepach czasu, to kiedy uzytkownik wlaczy aplikacje i odczyta co jest na porcie to kwestia losowa.Moze wtedy pojawiaja sie bledy ?? Mozna napisac funkcje filtrujaca glupoty ale nie jest to dobre rozwiaznie. Poniewaz dane na porcie sa pogrupowane w linie moze lepiej uzyc ReadLine() ... ( zamiast ReadExisting) ale przy uzyciu tej funkcji aplikacja sie wiesza. Jak porzadnie odczytac te dane. Dla przypominienia format ich wyglada tak:

xx.xxxx,xxx.xxxx,x.xxxxx
xxx.xxx,xx.xxxxx,x.xxxx

gdzie x to dowolne cyfry

Musze odczytac je bez smieci i skonwertowac string-> double. Gdy smieci sie pojawiaja konwersja wywala sie. Dzieki i prosze o pomoc

0

Moze uzyj regex'a? Sprawdzisz w ten sposob czy w ogole to co dostales pasuje do wzorca i jezeli tak, to otrzymasz gotowe, wyciagniete z niego liczby.

0

Johny Nie jestem wprawionym programistą C#. Co prawda poczytałem po Twoim poście trochę na temat wyrażeń regularnych, ale wciąż brakuje mi wiedzy jak zrobić funkcję sprawdzającą taki format danych. Czy mogłbyś dać jakiś zarys. Z góry dzięki ! pozdrawiam

0

Np. cos takiego:

using System.Text.RegularExpressions; ...
Regex vRegex = new Regex(@"^\s*(?:([\d]{2})\.([\d]{4}),([\d]{3})\.([\d]{4}),([\d])\.([\d]{5})|([\d]{3})\.([\d]{3}),([\d]{2})\.([\d]{5}),([\d])\.([\d]{4}))\s*$", RegexOptions.IgnoreCase);
String TestString = "122.235,35.14567,7.5789";
Match vMatch = vRegex.Match(TestString);
if (!vMatch.Success)
	throw new FormatException(String.Format("Tried to parse: {0}\nString does not match required format", TestString));
int []vNumbers = new int[6];
int vStart = 1;
if(vMatch.Groups[8].Value != "")
	vStart = 7;
for(int i = 0; i < vNumbers.Length; i++)
{
	try
	{
		vNumbers[i] = Int32.Parse(vMatch.Groups[i + vStart].Value);
	}catch(FormatException vException)
	{
		vNumbers[i] = -1;
	} 
}

Jak potrzebujesz komentarza to daj znac, chwilowo nie chce mi sie komentowac :)

Jak pisac wyrazenia regularne jest swietnie wyjasnione w msdn.
0

Poniewaz dane na porcie sa pogrupowane w linie moze lepiej uzyc ReadLine() ... ( zamiast ReadExisting) ale przy uzyciu tej funkcji aplikacja sie wiesza.

sprawdz w jaki sposob sa te konce linii wysylane. readline moze sie spodziewac np. "\r\n" a wysylane sa tylko "\n" i readline odczytuje i odczytuje i odczytuje.. smieci natomiast moga powstac z zaklocen transmisji, z zasmieconego bufora portu, podczas proby odczytania transmisjii w polowie jej trania itp itd. Dlatego tez ponawiam propozycje zeby zobaczyc czy nie da sie jakos podpiac zdarzeniowo swojego handlera trasmisji przychodzacej zamiast pollingowac stan portu. To by rozwiazywalo sporo problemow, wiec jest calkiem prawdopodobne ze taka mozliwosc istnieje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1