System out of range in for loop - c#

System is giving me out of range exception when p = 255. My understanding is that with "OR" operator, later part of if statement should come into affect. However, it is not. Please advise on how to fix it.
for (int p = 0; p < 256; p++)
{
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
{
//Code
}
}

In the first iteration p = 0;
With p = 0; the right side of the conditional expression is trying to access buffer[-1], which throws the Exception.
You should start the iteration with index 1 and end it one item before the last item in the buffer. Try something like this:
for (int p = 1; p < buffer.Length - 1; p++)
{
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
{
//Code
}
}

You have out of range error. It means that index p is out of buffer range,
which is
// buffer has Length items, starting from 0
[0 .. buffer.Length - 1]
Now, let's have a look at index usage: you have
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1])
and you address
buffer[p] where p can be in 0..buffer.Length - 1 range
buffer[p + 1] where p can be in -1..buffer.Length - 2 range
buffer[p - 1] where p can be in 1..buffer.Length range
combining all 3 ranges for index p together we get p in 1..buffer.Length - 2 range or
for (int p = 1; p < buffer.Length - 1; p++)
if (buffer[p] == buffer[p + 1] || buffer[p] == buffer[p - 1]) {
...
}
Note edge cases (first and last buffer items):
when p == 1 we have
(buffer[1] == buffer[2] || buffer[1] == buffer[0])
^
first item
when p == buffer.Length - 2
(buffer[buffer.Length - 2] == buffer[buffer.Length - 1] || buffer[buffer.Length - 2] == buffer[buffer.Length - 3])
^
last item
that's why no item is lost

You're comparing an item x to either the item before it or the item after it. Then you move along one, and you potentially make the same compare you just did, so you're wasting a lot of CPU:
var a= new []{1,2,3,4}
if(2 == 1 or 2 == 3)
...
if(3 == 2 or 3 == 4). //3==2 was already done above like 2==3
Just compare current with next, moving along by 1 each time, stopping 1 short of the end of the loop
If you want to duplicate messaging, print twice
for(int x=0; x<array.Length-1; x++){
if(array[x] == array[x+1]){
Console.WriteLine($"index {x} is same as {x+1}");
Console.WriteLine($"index {x+1} is same as {x}");
}
}
My understanding is that with "OR" operator, later part of if statement should come into affect.
Later part of statement comes into effect if first part of statement returns false. First part of statement is always done. your first part of statement is guaranteed to crash if the array is length 256
C# isn't some sort of AI that thinks "ooh, if I do the left part of the OR then I'll get a crash, so I'll just do the right part", it just does as you told it according to its "do left, then if false, do right" rules, which might mean you try access an array index that doesn't exist
Worth pointing out that if the first two bytes in your buffer are not the same (left part of OR returns false) then you'll get another crash, this time because C# is trying to evaluate the right side of the OR, and you make it do buffer[-1]

Related

Move an element from an array

How can I move an element from an index, for example to the front. Let's say this example : moving the second index to the front, and the rest of the elements remain the same. As I am working with algorithms I can't implement things like lists that I found most efficient I guess.
Example : 1 2 3 4
Output : 3 1 2 4
I assigned the value from the index to a temporary variable so far. But I do not know how to shift the elements, I'm guessing implementing somehow a for loop.
You have to change how you iterate based on whether your desired index is before or after the elements original index and handle those cases individually.
public static void MoveToIndex(int[] array, int from, int to)
{
if (array.Length < 2) return;
if (from == to) return;
if (from < 0 || array.Length <= from) throw new ArgumentException(nameof(from));
if (to < 0 || array.Length <= to) throw new ArgumentException(nameof(to));
var startIndex = Math.Min(from, to);
var endIndex = Math.Max(from, to);
var swappedValue = array[startIndex];
if (to < from)
{
array[startIndex] = array[endIndex];
}
for (var i = startIndex + 1; i <= endIndex; i++)
{
var current = array[i];
if (to < from)
{
array[i] = swappedValue;
swappedValue = current;
}
else
{
array[i - 1] = i == endIndex ? swappedValue : current;
}
}
}

Variable values update before I give that instruction

I apologize in advance for this way to long post.
I'm working on a C# function to unify a mesh's triangles'orientation for a Unity3D project. I use Vector3 type, which is a struct composed by a float array [3].
In order to do so I take a first triangle and check if it points outwark or inward. After that I check for an adiacent one and check the order of the indices of the triangle. If I find couple of indices in order, I flip them.
here an example:
base triangle' indices: 1 2 3
second triangle' indices:
1 2 4 (1 2 are in the same order as the base triangle, need to flip to 2 1 4)
4 2 1 (2 1 are not in the same order, then do nothing)
The check returns me the next triangle to check if it finds; otherwise it returns a null vector.
if "next" isn't null I make the "next" triangle to "current", I store the fixed triangle in a variable, in order to avoid the program to keep checking the same indices and re-iterate the check.
The problem is that some variable seem to update their values before the instruction messing up my conditions.
As you can see in the code below I have a really complex If statement that tries to find if two triangles'indices are present in the same order (not necessary the same position) like:
1 2 3 (base)
all the following possible result need to be flipped to
1 2 4 -> 2 1 4
4 1 2 -> 1 4 2
2 4 1 -> 4 2 1
that minus before mesh.Index[] is needed because it seems to use IndexList values, instead of mesh.Index ones and I don't know why.
I'm using this custom struct to test the program outside Unity
public struct SimplifiedMesh
{
//this stores the order of the vertices needed to
//create all the triangles of the mesh.
public int[] Index;
it list all the vertices of the mesh
public Vector3[] Vertex;
};
IndexList is used to store the checked triangles. At first all values are positive, but when it check one, it turns its indices negative.
int[] IndexList = new int[Unimesh.Index.Length]; IndexList = Unimesh.Index;
First I check with a different method in order to determine if the face is pointing outward or inward
FirstCheck(Unimesh, CentreofMesh, currentIndices);
//this will tell the program this triad is already checked
IndexList[currentIndices[0]] *= -1;
IndexList[currentIndices[0] + 1] *= -1;
IndexList[currentIndices[0] + 2] *= -1;
The following now is the tough part. Here a legend of variables:
currentIndices is an Array[3] storing the position of thr three indices of the last checked triangle in the mesh.Index array. It's used to find an adiacent one;
next is the return variable that return the next vector to be considered for the check or null if he has found no adiacent triangles.
mesh.Index[currentIndices[0-1-2] are the current indices
FlipNormals get the mesh indices, go to the three indices pointed by "Flipvector" and swap the first two, inverting their order
and here the code
static int[] AdiacentFace(SimplifiedMesh mesh, int[] IndexList, int[] currentIndices)
{
int[] next = new int[3];
for (int i = 0; i < IndexList.Length; i += 3)
{
if (IndexList[i] > 0 || IndexList[i + 1] > 0)
{
if
// e restituisce la nuova terna modificata
((IndexList[i] == -mesh.Index[currentIndices[0]] && (IndexList[i + 1] == -mesh.Index[currentIndices[1]] || IndexList[i + 2] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 1] == -mesh.Index[currentIndices[0]] && (IndexList[i + 2] == -mesh.Index[currentIndices[1]] || IndexList[i] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 2] == -mesh.Index[currentIndices[0]] && (IndexList[i] == -mesh.Index[currentIndices[1]] || IndexList[i + 1] == -mesh.Index[currentIndices[2]])))
{
int[] Flipvector = new int[3];
Flipvector[0] = mesh.Index[i];
Flipvector[1] = mesh.Index[i+1];
Flipvector[2] = mesh.Index[i + 2];
FlipNormals(mesh, Flipvector);
// Elimina la terna per i successivi controlli
IndexList[i] *= -1;
IndexList[i + 1] *= -1;
IndexList[i + 2] *= -1;
// Ritorna gli indici del nuovo vettore
next[0] = i;
next[1] = i + 1;
next[2] = i + 2;
return next;
}
else if
((IndexList[i] == -mesh.Index[currentIndices[0]] && (IndexList[i + 2] == -mesh.Index[currentIndices[1]] || IndexList[i + 1] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 1] == -mesh.Index[currentIndices[0]] && (IndexList[i] == -mesh.Index[currentIndices[1]] || IndexList[i + 2] == -mesh.Index[currentIndices[2]])) ||
(IndexList[i + 2] == -mesh.Index[currentIndices[0]] && (IndexList[i + 1] == -mesh.Index[currentIndices[1]] || IndexList[i] == -mesh.Index[currentIndices[2]])))
{
// Elimina la terna per i successivi controlli
IndexList[i] *= -1;
IndexList[i + 1] *= -1;
IndexList[i + 2] *= -1;
// Ritorna gli indici del nuovo vettore
next[0] = i;
next[1] = i + 1;
next[2] = i + 2;
return next;
}
}
}
next = null;
return next;
}
I found the solution.
I'm a beginner with C#, and I didn't know the operation "IndexList = Unimesh.Index" between arrays pass the reference, instead of the single values.
I managed to solve the problem in this way.
From:
int[] IndexList = new int[Unimesh.Index.Length]; Indexlist = Unimesh.Index;
to:
int[] IndexList = new int[Unimesh.Index.Length];
For (int i = 0; i < Unimesh.Index.Length; i++)
{
IndexList[i] = Unimesh.Index[i];
}
This way I copy just the values and not the reference to the array.

Out of range index in if condition [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 3 years ago.
I have a sentence, and I want to check for duplication letters in order to add a 'x' as a separator between them, however I debugged and kept getting an exception in here:
for (int i = 0; i < res.Length; i++)
{
t += res[i];
if (res[i] == res[i + 1]) //Index out of range exception here
{
t += 'x';
}
}
what goes wrong in here?
The cause of misbehavior is in the if:
if (res[i] == res[i + 1])
when i == res.Length - 1 (for loop last iteration) you have
if (res[res.Length - 1] == res[res.Length])
and res[res.Length] throws OutOfRangeException since valid range is [0..res.Length - 1] (please, note - 1).
Your code corrected:
for (int i = 0; i < res.Length; i++)
{
Nplaintext += res[i];
// we don't want to check (and insert 'x') for the last symbol
if (i < res.Length - 1 && res[i] == res[i + 1])
{
Nplaintext += 'x';
}
}
Often we work with string with a help of regular expressions (let .Net loop over the string for you):
using System.Text.RegularExpressions;
...
string source = "ABBBACCADBCAADA";
// Any symbol followed by itself should be replaced with the symbol and 'x'
string result = Regex.Replace(source, #"(.)(?=\1)", "$1x");
Console.Write(result);
Outcome:
ABxBxBACxCADBCAxADA
i+1 us causing this.
in the last iteration, i+1 refers to a location which is not inside that array.
Better change the condition in for loop as below:
for (int i = 0; i < res.Length - 1; i++)
{
t += res[i];
if (res[i] == res[i + 1]) //Index out of range exception here
{
t += 'x';
}
}
t += res[res.Length -1 ];
Hope this helps.
Sure you get this exception. In the case i=res.Length -1 (what is exactly the last position) you ask for res[Length] with the i +1 but because of starting with 0 the element you are asking for does not exist.
try something like
if(i+i < res.Length)
before you ask for that element
or even better start counting with i=1 and use
if (res[i] == res[i - 1])
{
Nplaintext += 'q';
}

how to transfer between arrays in c#?

I have a project in Automata theory, and I want to convert an algorithm into programming language( no matter what programming language used to solve this question)
Well, I have these orders
we enter a string and then we convert it to char so we can compare,
for example we entered this input
01001
to make it clear, I will add more inputs to know what I mean,
01000001
{valid input}
101101
{Wrong input}
0
{Wrong input}
we will check if the first digit is 0 if yes, we copy this string to another array 1, and then convert it to with 1 if it's same we copy it to array 2, then here we will need to enter a loop using for or foreach, we want to check if the next values are 0 ( without last char) so I used a.length-1 to make sure it's won't use last one, and when we see new value which is 1, we move to the last array and must be 1.
we will message using Console.WriteLine(""); that the program follows the order
I made something similar which is this (in C#):
string s= Console.ReadLine();
var a = s.ToCharArray();
Console.WriteLine("Original String: {0}",s);
//for (int k = 4; k < a.Length; k++) {
if (a[0] == '0' && a[1] == '1' && a[a.Length-1] == '1') {
for (int r = 2; r < a.Length-1; r++) {
if (a[r] == '0')
{
Console.WriteLine("The Language is Right.");
}
}
}
how do I make new arrays and copy and use it to check out
The straightforward way of implementing a finite automaton is to loop over the input and store the state in a variable:
string s= Console.ReadLine();
int state = 0;
foreach (char c in s.ToCharArray())
{
if (state == 0 && c == '0')
state = 1;
else if (state == 0 && c == '1')
state = -1;
else if (state == 1 && c == '1')
state = 2;
else if (state == 1 && c == '0')
state = -1;
else if (state == 2 && c == '1')
state = 3;
else if (state == 3)
state = -1;
}
bool accepted = state == 3;
Console.WriteLine(accepted);

Index was outside of the bounds of the array [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 7 years ago.
Unhandled Exception: System.IndexOutOfRangeException: Index was outside of the bounds of the array (at the first if statements)
static int arrayRows = 20;
static int arrayCols = 20;
public void printBoard()
{
int neighbours;
for (y = 0; y < arrayCols; y++)
for (x = 0; x < arrayRows; x++)
{
neighbours = 0;
// Count number of neighbours surrounding live cell
if (parentGen[x-1, y-1] == 1) // top left
neighbours++;
if (parentGen[x-1, y] == 1) // left
neighbours++;
if (parentGen[x-1, y+1] == 1) // bottom left
neighbours++;
if (parentGen[x, y-1] == 1) // middle top
neighbours++;
if (parentGen[x, y+1] == 1) // middle bottom
neighbours++;
if (parentGen[x+1, y-1] == 1) // top right
neighbours++;
if (parentGen[x+1, y] == 1) // right
neighbours++;
if (parentGen[x+1, y+1] == 1) // bottom right
neighbours++;
}
}
The only thing I can think of is that my program is checking coordinates of < 0? How do I go about fixing this?
Your first coordinates are parentGen[-1, -1], this will always throw the exception.
You need to check if the cell you're on has any neighbors to the left, right, top, or bottom. For example, x = 0 has no neighbors to the left and y = 20 has no neighbors to the bottom. You may wish to break this out to other functions, such as HasNeighborsLeft(int x), etc.
edit: sample code
if(x > 0 && y > 0 && parentGen[x - 1, y - 1] == 1)
{
neighbors++;
}
You can factor this out to it's own functions though, and you can wrap this kind of logic around all of the checks that involve x - 1 for example.
You need boundary condition checks on both x and y at top and bottom of their range. You cannot legally index the entire array using +1 and -1 offsets. Break up your check into boundary condition cases where x == 0, x == arrayRows-1 (by not checking the invalid relative offsets here), and then check cases where x+1 and x-1 are always valid in an else. Similarly with y.
You're array goes from 0->21. As well, you're testing values at [-1, -1] and [22, 22]You can fix it by chainging your for statement(s) to
for (int x = 1; x <= arrayCols - 1; x++)
for (int y = 1; y <= arrayRows - 1; y++)
In addition, problems with loops are almost always caused by a small number of cases that you can always check for:
Your for statement a) starts at a lower bound than the array, or b) finishes at a higher one
a) for (int x = -1;
b) for (int x = 0; x <= array.Length
Your code in the loop accesses values outside of your indexer range
for (int x = 0...
array[x-1, ...
Your collection isn't initialized
In this case, your problem 2.
The problem is that you are looking at the previous and next values (-1 and +1) which will obviously go outside the array bounds at either ends of the array.
There are a few options solving this:
Create a bigger array with a dummy 'border' around the edge which you don't use for your board but allows you to use code very similar to that which you have now (with your -1 and +1 previous and next cell logic). (Imagine a chess board that is 10x10 where you are not allowed to play in the outermost squares).
Scatter loads of 'if' statements to check if you're at the first or last item in the array and thus avoid making any array accesses that are invalid.
Create a function to retrieve an item at a particular cell and put conditional logic in this function for dealing with the array bounds.
Personally I would go with the last option, build yourself a function which gets the state of the specified cell, checks that the indices are valid and returns a default value if they are not. For example:
private const int EMPTY_CELL = 0;
private const int INVALID_CELL = EMPTY_CELL; // for now the same, but gives scope to handle separately
private int GetCellState(int row, int column)
{
if (row < 0) return INVALID_CELL;
if (column < 0) return INVALID_CELL;
if (row >= arrayRows) return INVALID_CELL;
if (column >= arrayColumns) return INVALID_CELL;
return parentGen[row, column];
}
It is then simply a matter of swapping your direct accesses to parentGen with calls to the function.
you could start by creating a sequence of only the valid indices and then iterate the combinations of those:
static int arrayRows = 20;
static int arrayCols = 20;
public void printBoard()
{
var sequences = from row in Enumerable.Range(0, arrayRows)
from column in Enumerable.Range(0, arrayCols)
select new
{
Rows = (from xs in new[] { row - 1, row, row + 1 }
where xs >= 0 && xs < 20
select xs),
Columns = (from ys in new[] { column - 1, column, column + 1 }
where ys >= 0 && ys < 20
select ys)
};
//now that we have a sequence with all the needed (valid) indices
//iterate through the combinations of those
var neighbours = (from seq in sequences
from row in seq.Rows
from column in seq.Columns
where row != column && parentGen[row, column] == 1
select 1).Count();
}

Categories

Resources