Argument out of range exception - c#

Can anyone tell me why I am getting this exception? Well I know "why" I am getting it is cause it says that the element in the list I am trying to access does not exist, but stepping through the code I can see that it actually does exist?
In Game1 I call a helper class' calculation method. Then when the calculation is done, I add the result to a List<> in the CalculationHelper class.
The code for this looks like:
In Game1 class where I have instanciated CalculationHelper calcHelper class and then call one of the class methods.
Fisrt, in Game1 I call calcHelper.ForceVanishingPointIntersections(...) method in a for() loop which can be seen below. This works just fine and the calcHelper.ForceVanishingPointIntersections(...) method adds the value to the IntersectionPointList<> in the CalculationHelper class (see method below).
for (int i = 0; i < LineList.Count; i++)
{
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite(VanishingPointIntersectionList, calcHelper.GetIntersectionPointListElementAt(i), greenCirlce);
i++;
}
To do some calculations and add a value to the IntersectionPointlist in CalculationHelper class I do:
List<Vector2> IntersectionPointList = new List<Vector2>();
public void ForceVanishingPointIntersections(Line line1, Line line2)
{
Vector2 intersectionPoint;
// Do some calculations
IntersectionPointList.Add(intersectionPoint);
}
Finally in Game1 class, the second method in the for() loop I call AddSprite to create a Sprite. I want to pass in the values stored in CalculationHelper class IntersectionPointList as coordinates for the Sprite.
To this end I call calcHelper.GetIntersectionPointListElementAt(i) which calls a method in CalculationHelper class like so (which should return the value at the specified point (i) from the IntersectionPointList<>)
public Vector2 GetIntersectionPointListElementAt(int index)
{
Vector2 result = this.IntersectionPointList[index];
return result;
}
The first time the for() loop executes, this works fine. I do the calculations, the value is stored in the list and I am able to get this value from the list and pass it to AddSprite(..). However, the second time round the for() loop, when I call GetIntersectionPointListElementAt from the AddSprite() method, I get an exception in my
public Vector2 GetIntersectionPointListElementAt(int index)
{
Vector2 result = this.IntersectionPointList[index]; // Exception thrown here
return result;
}
saying the index was out of range? But stepping through the code, my IntersectionPointList is updated and it shows that the list now contains 2 values. And I'm trying to access the second value.
Does anyone have an idea why this could be?
For the life of me I cant figure out where I am going wrong.
If more code is needed I can post some more, just let me know

Because you access LineList[] with an index i + 1 you must diminish the last index by one in the for-condition. (Note the -1)
for (int i = 0; i < LineList.Count - 1; i++) {
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite( ... );
}
This will call ForceVanishingPointIntersections with the indexes
(0, 1), (1, 2), (2, 3), ... (Count-2, Count-1)
Note that the index range of LineList is 0 ... Count-1.
If non-overlapping indexes are required instead, like
(0, 1), (2, 3), (4, 5), ... (Count-2, Count-1)
then change the loop to
for (int i = 0; i < LineList.Count - 1; i += 2) {
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite(
VanishingPointIntersectionList,
calcHelper.GetIntersectionPointListElementAt(i / 2),
greenCirlce);
}
EDIT According the Chris Gessler's comments this second approach is the right one.
Remove the i++ inside the loop, it's quite uncommon and confusing. Instead, replace it by i += 2 in loop header.
Also note that (again according to Chris Gessler) IntersectionPointList has half as much items as LineList. Therefore call GetIntersectionPointListElementAt with i / 2. Since i is {0, 2, 4, ... }, i / 2 is {0, 1, 2, ...}.
The for-loop allows you to have a comma-separated list of statements in the first and third section. You could use it to maintain two indexes
for (int i = 0, k = 0; i < LineList.Count - 1; i += 2, k++) {
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite(
VanishingPointIntersectionList,
calcHelper.GetIntersectionPointListElementAt(k),
greenCirlce);
}

for (int i = 0; i < LineList.Count; i++)
{
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
...
i++;
}
Instead of doing that, you should do:
for (int i = 0; i < LineList.Count; i += 2)
{
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
...
}
And if LineList.Count isn't even, for example: 3.
It will start at 0, you use 0 and 1.
Then it jumps to 2, you use 2 and 3.
But oops! there isn't 3!
Only count 3! 0 to 2!
Thats when you'll get argument out of range exception.
To avoid that, you can either check if Count % 2 == 0, or you can go until LineList.Count - 1, if you don't mind skipping extra's if there are.

It looks like you're adding two lines per one Sprite. The indexes won't line up. When LineList has 10 items, you will only have 5 IntersectionPointList items, so passing in an index of 9 will fail.
You should change your LineList collection to List<Tuple<string,string>> so that you have two lines per item which will line up with each Sprite. This will create a one-to-one relationship between Lines and Sprites.
I suppose you could always pass in an index (i / 2), which should be the correct Sprite for every two lines.

Related

A for loop somehow overrides an entire array, even though I can see no reason for that

So, been looking at this code for a good while now, and I am lost.
The point is to run a for loop that adds classes to an array, and then for each class runs through an array of points inside of that class, and add variations to it.
This then shows as a bunch of dots on a form, which are supposed to move independently of each other, but now follows each other completely.
It does not matter how much variation there is or anything, it's just 99 dots with the exact same acceleration, velocity, and location, and path.
The code is here, the method isn't touched by any other code, and the problem arises before it returns.
//Point of the method is to put variations of Baby into an array, and return that array
Dot.Class[] MutateAndListBaby(Dot.Class Baby)
{
//Making the empty array
Dot.Class[] BabyList = new Dot.Class[dots.Length];
//For loop that goes through through the whole array
for (int i = 1; i < BabyList.Length; i++)
{
//For each itteration the for loop adds the class reference to the index, then puts the standard directions into that reference, and then sets a value preventing it from being changed in another code
BabyList[i] = new Dot.Class();
BabyList[i].Directions = Baby.Directions;
BabyList[i].StartupComplete = true;
//The zero index variation when made like this, allows it to not be overriden, which would lead one to believe that how the directions are copied is he problem
//But it shouldn't be, BabyList[i].Directions = Baby.Directions; should be fire and forget, it should just add the Directions to the array and then leave it
BabyList[0] = new Dot.Class();
BabyList[0].Directions = new PointF[100];
for (int b = 0; b < BabyList[0].Directions.Length; b++)
{
BabyList[0].Directions[b] = new Point (5, 10);
}
BabyList[0].StartupComplete = true;
//The for loop that shuld add variation, but it seems like it somehow overrides it self, somehow
for (int b = 0; b < BabyList[i].Directions.Length; b++)
{
if (rand.Next(0, 101) >= 100)
{
int rando = rand.Next(-50, 51);
float mod = (float)rando / 50;
float x = BabyList[i].Directions[b].X;
x = x + mod;
BabyList[i].Directions[b].X = rand.Next(-5, 6);
}
if (rand.Next(0, 101) >= 100)
{
int rando = rand.Next(-50, 51);
float mod = (float)rando / 50;
float y = BabyList[i].Directions[b].Y;
y = y * mod;
BabyList[i].Directions[b].Y = rand.Next(-5, 6);
}
}
//Now one would assume this would create a unique dot that would move 100% independently right? Since it's at the end of the for loop, so nothin should change it
// Nope, somehow it makes every other dot copy its directions...
if (i == 5)
{
for (int b = 0; b < BabyList[5].Directions.Length; b++)
{
BabyList[5].Directions[b] = new PointF(-5f, -5f);
}
}
}
return BabyList;
}
}
}
With the code there, what I get is the 0 index dot going its own way, while the other 99 dots for some reason follow the 5th index's Directions, even though they should get their own variations later on in the code.
Any help would be much appreciated, it probarbly something obvious, but trust me, been looking at this thing for quite a while, can't see anything.
If I understand you correctly, this might be the issue:
BabyList[i].Directions = Baby.Directions;
Directions is of type array of PointF - a reference. The line above does not copy the array. Is that what you assume? If I'm not misreading the code you're presenting, you're creating one Dot.Class with its own array of PointF at index 0 and fill the rest of your Dot.Class array with instances that share one single array.
Directions is array, which is a reference type. When you're making assigment of a variable of this type
BabyList[i].Directions = Baby.Directions;
no new instance is created and reference us just being copied into new variable which still references original instance. Essentially in your loop only very first item gets a new instance of Directions as it's explicitly constructed. The rest share the instance which comes as a member of parameter passed to the method.
You probably want to change your if conditions:
(rand.Next(0, 101) >= 100
to
(rand.Next(0, 100) < 99
This will run an average of 99 times out of 100, whereas your current condition runs 1 out of 101 times (on average)
Oh, and Benjamin Podszun's answer about assigning the same array (not a copy of the same array) to Directions apply as well!
(Assuming that Directions isn't a getter that you created to return a copy of an array instead of a reference!)

How to classify an undefined vector list item?

I understand that an undefined vector3 = default(vector3), but what about a vector list item that does not exist? For example:
List<Vector3> stuff = new List<Vector3>();
for(int i=1; i<10; i++){
stuff.add(new Vector3(0 + i, 0, 0));
}
In this case what would stuff[15] be considered? I know it is undefined, but lets say that you did not know if it's defined or not. How would you find out if it was? Like, if stuff[15] is undefined print("stuff[15] is undefined") and break.
Assuming you are asking if your code will be able to access stuff[15], no.
The reason for this is because you only add 10 elements to it, each of type vector.
List<Vector3> stuff = new List<Vector3>();
for (int i = 0; i < 10; i++) {
stuff.add(new Vector3(0 + i, 0, 0));
}
This code will add a new Vector 10 times with the positions given, where the first parameter is 0 + i. Since there are only 10 elements, stuff[15] will not be accessed, and will throw an ArrayOutOfBoundsException.
To safely check if an array can contain a 15th element, use an if statement
if (stuff.Length > 15) {
stuff[15]; // will only be called if an element exists
}
I figured out the answer partly thanks to Frontear's answer.
List<Vector3> stuff = new List<Vector3>();
for(int i=1; i<10; i++){
stuff.add(new Vector3(0 + i, 0, 0));
}
if(15 > stuff.Count ){
print("stuff[15] is undefined")
break;
}
So, all undefined list items are obviously out of the range of the number of defined list items and, therefore, to find out if a list item is undefined just compare it's number to the number of defined list items.
I suppose it was a very simple answer, I just thought there was a word that you could set the defined/undefined list item equal to to get a boolean value representing if it was defined or not; like stuff[15]==undefined. Apparently not...

Checking the values in an array around a specific index

I have a 2 dimensional array and what I want to do is search for a specific value around that index(so I want to check array[x-1,y], array[x,y-1] and so on).
My problem is when it will check index which is out of range. Is there someway to check them (I don't want to a lot of IF's checking if x-1 or y-1 is in range of course). I haven't used try/catch a lot yet, and I'm not sure how that works either, but can I ignore the out of range Exception with that? Or is there a better solution for this problem?
If you can't have if you can pre-compute lists of indexes for each cell and iterate over them. I.e. have separate array of the same dimensions that contains lists of index pairs for iteration. Inner elements would have 8 pairs each, corner and border elements would have less (3 and 5 correspondingly).
Alternatively you can use ? : instead of if condition in case restriction is only on syntax and not on condition itself.
I suggest using an extension method for hiding the logic in it (weather with if's or with Math.Max and Math.Min):
public static partial class Array2DExtensions {
public static IEnumerable<T> Vicinity<T>(this T[,] data, int line, int col) {
if (null == data)
throw new ArgumentNullException("data");
//TODO: you may want to add range check here
for (int i = Math.Max(data.GetLowerBound(0), line - 1);
i <= Math.Min(data.GetUpperBound(0), line + 1);
++i)
for (int j = Math.Max(data.GetLowerBound(1), col - 1);
j <= Math.Min(data.GetUpperBound(1), col + 1);
++j)
yield return data[i, j];
}
}
And so you can put something like this:
int[,] sample = ...
...
// Are there any value less than 100 in vicinity of 5, 7 item?
bool found = sample
.Vicinity(5, 7)
.Any(item => item < 100);
You can calculate the safe lower and upper limits for both dimensions and then iterate over the matrix:
// Calculate x range to check
var xl = Math.Max(x-1, 0);
var xu = Math.Min(x+1, array.GetUpperBound(1));
// Calculate y range to check
var yl = Math.Max(y-1, 0);
var yu = Math.Min(y+1, array.GetUpperBound(0));
// Iterate using ranges
for (var j=yl; j <= yu; j++)
for (var i=xl; i <= xu; i++)
// Do the checking
// array[j, i]
I think you'll have to check for each index if it around the array edges.
with the necessary "if's"
if you want to use try and catch it will work,
but you'll have to surround each array access with it's own Try And Catch
(if all will be in same try, once exception was caught the following commands will be skipped)
like this:
try
{
array[x-1,y]
}
catch (ArgumentOutOfRangeException ex)
{
}
try
{
array[x,y-1]
}
catch (ArgumentOutOfRangeException ex)
{
}
etc..

C# Out of Range in For Loop

I'm running this code, but every time, I get the error "An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred" on the first line of the for loop. Its basically code for a multiple choice quiz question, with questions & answers stored in a 2d array.
Unfortunately, I can't seem to spot the problem. It's probably a simple error, but I'm a beginner so I'm struggling to spot it.
I've read through similar questions, but I don't understand why this line is causing problems. I've got 4 elements in my list, one is removed before the loop, so there should be 3 left. I'm only looping through 3 times, so I don't understand what the problem is.
Hopefully someone will be able to help, Thanks!
Random rndq = new Random();
Random rnda = new Random();
List<int> answers = new List<int> { 1, 2, 3, 4 };
int questionchoice = rndq.Next(0, questions.GetLength(0) - 1);
int labelchoice = rnda.Next(0, answers.Count-1);
lblQuestion.Text = questions[questionchoice, 0];
var answer = (Label)Controls["lblAns" + answers[labelchoice]];
answer.Text = questions[questionchoice, 1];
answers.Remove(labelchoice);
int j = 2;
for (int i = 0; i < 3; i++)
{
var wronganswers = (Label)Controls["lblAns" + answers[i]];
wronganswers.Text = questions[questionchoice, j];
answers.RemoveAt(i);
j++;
}
Each pass through the loop you're removing an item from the list. After the first pass your list has 3 items in it [2, 3, 4]. Next pass there are two items left [2, 4]. Then you try to get the third item from the list of two and get an exception.
Either you need to leave the list alone while looping or make sure that your loop condition actually references the length of the list. Assuming that you want to actually process all 4 items I would suggest that you remove the RemoveAt call completely.
Or if you actually want to remove the items, reverse the direction of your loop:
for (int i = answers.Count - 1; i >= 0; i--)
{
// ....
answers.RemoveAt(i);
}
This will still process all of the items in the list and leave you with nothing in the list at the end.

How to display all members of a given subsequence on the console?

I'm trying to understand why I can't print only the members of a subsequence of an array, that is equal to an integer from the input. The array is also read from the console. When i run the program only the first of these members does come up, but with him also a seemingly random number of zeros, while the rest of the subsequence is omitted. If there's a better way than to use a second array, I'll be grateful if you share it. Okay, to specify- I want to know how to print all the members of the aforementioned subsequence, can you please give me a useful advice or sample? Here's the input, output and code:
4 4 56 57 58
8
4 0 0 0 0
instead of 4 4
int v = int.Parse(Console.ReadLine());
int[] valueHolder = new int[arr1.Length];
int currentSum = 0;
for (int endIndex = 0; endIndex <= arr1.Length -1; endIndex++)
{
currentSum = 0;
for (int currentSumIndex = endIndex; currentSumIndex >= 0; currentSumIndex--)
{
currentSum += arr1[currentSumIndex];
if (currentSum == v)
{
valueHolder[currentSumIndex] = arr1[currentSumIndex];
}
if (currentSum == v)
{
for (int i = 0; i <= valueHolder.Length - 1; i++)
{
Console.Write(valueHolder[i] + " ");
}
}
}
I think you would be best served by putting a break point on the line of the first for loop then stepping through your code. If you take a pad of paper and write each of the variables states as you go through it then it will be pretty obvious what's going on.
However, just to help you out.
In the first pass of the outer loop (endIndex = 0), the inner loop does NOT execute. currentSumIndex = endIndex which equals zero, which does not pass the currentSumIndex >= 0 test. Therefore the first 4 is skipped.
In the second pass, the number 4 is emitted because currentSum equals 4. However, the values of 0 are also emitted because you are walking the entire valueHolder array and spitting all of the empty values out.
From the third pass forward, currentSum will never equal the number you typed in:
The first pass of the inner loop sets currentSum to 56, which does not equal v. The second pass of the inner loops sets it to 56+4 ( currentSum += arr1[currentSumIndex] ) which is 60. Therefore, nothing will ever be emitted again as currentSum will always be the sum of all numbers from the current array position going backward to the beginning array position and therefore will always be greater than v
You don't need a second array. You just need to pay attention to what your code is doing. Side note: I have absolutely no idea why you have that inner loop or even what the 8 is supposed to represent in your example entry above.
If I was writing this, I'd change it to (assuming you can't use LINQ):
int v = int.Parse(Console.ReadLine());
for (int i= 0; i <= arr1.Length -1; i++)
{
if (arr1[i] == v) {
Console.Write(arr1[i].ToString() + " ");
}
}
Console.WriteLine();

Categories

Resources