IndexOutOfRangeException when trying to access array element - c#

I can't figure out why I'm getting the out of range exception on the following piece of code. The values for _maxRowIndex and _maxColIndex are 5, and 0 respectively. The exception is being thrown on the first time through when row and col are both equal to 0. I don't understand why 0, 0 would be out of bounds on the array.
_cells = new ToolBarButton[_maxRowIndex, _maxColIndex];
.
.
.
for (int col = 0; col <= _maxColIndex; col++) {
for (int row = 0; row <= _maxRowIndex; row++)
{
if (_cells[row, col] == null)
{
PopulateCell(toolBarbutton, row, col);
}
}
}

Array indices start from 0 and are upto [upperbound-1]. Since your loop starts at 0, it must end at < the limit value rather than <= limit value. So, change the "<=" to "<" in the loop. Eg:
col <= _maxColIndex
should be changed to
col < _maxColIndex

If you want the max index to be 5, that means the array needs to be of length 6 as the first element is at index 0.
So, change:
_cells = new ToolBarButton[_maxRowIndex, _maxColIndex];
to:
_cells = new ToolBarButton[_maxRowIndex+1, _maxColIndex+1];

You have <= in your for statement...
So your loop evaluates for col =0, 1, 2, 3, 4 and 5... 5 is out of bounds

I guess you should declare _cells as below
_cells = new ToolBarButton[5,1];
instead of
_cells = new ToolBarButton[5,0];

Related

How to reverse 2d arrays in c#

array :
int[,] nums = new int[3,4]{
{6,7,9,8},
{4,2,1,3},
{9,7,0,4}
};
I need to print out the rows in reverse but keep the columns in same order.
Iooked all over the internet I don't even know where to start my code, all I have is a for loop that prints in reverse but when I run my code nothing shows up.
for (row = 3; row >= 0; row--)
{
for (column = 0; column < 4; column++)
{
Console.Write("{0} ",nums[row,column]);
}
}
I'm definitely missing something and the only error I get is the index out of bounds.
Please, do not use magic numbers like 3, 4, but actual array lengths, GetLength(...):
int[,] nums = new int[3, 4] {
{ 6, 7, 9, 8 },
{ 4, 2, 1, 3 },
{ 9, 7, 0, 4 },
};
for (int row = nums.GetLength(0) - 1; row >= 0; --row) {
for (int column = 0; column < nums.GetLength(1); ++column)
Console.Write($"{nums[row, column]} ");
if (row > 0)
Console.WriteLine();
}
Fiddle
As you know indexes in an array go from 0 to upper bound so when cycling through you should consider that for an array with 3 elements you will have indexes 0, 1 and 2, you are trying to access index 3 which does not exist.
High level languages have safeguards to avoid this, here an out of range type exception is thrown to let you know you are accessing memory that does not belong to the array.
You should avoid direct indexing because it's very easy to get these off-by-one errors, you should always try to use range based loops, if that's not possible get the length of the array by code, don't use hard coded dimensions unless you have to. Here you can use member methods to figure out the bounds of the array:
int[,] nums = {
{6,7,9,8},
{4,2,1,3},
{9,7,0,4}
};
for (var row = nums.GetUpperBound(0); row >= 0; row--)
{
for (var column = 0; column < nums.GetLength(1); column++)
{
Console.Write("{0} ",nums[row,column]);
}
Console.WriteLine(); // line break for tiddy print
}
This should work
for (row = 2; row >= 0; row--)
{
for (column = 0; column < 4; column++)
{
Console.Write("{0} ",nums[row,column]);
}
}
for (row = 3; row >= 0; row--)
The program is throwing OutOfRangeEception, because when you have an array[3,4], the last index of row is 2. Your program was trying to find an element with too large index number(3).
Here you have working code
int[,] nums = new int[3, 4] { { 6, 7, 9, 8 }, { 4, 2, 1, 3 }, { 9, 7, 0, 4 } };
for (int **row = 2**; row >= 0; row--)
{
for (int column = 0; column < 4; column++)
{
Console.Write("{0} ", nums[row,column]);
}
Console.WriteLine();
}
As you can see, changing value in for loop from 3 to 2 fixed the problem.
And one important note from me - try to declare counter variables inside for - do not make it "global" if you don't need to. In bigger project it could use more memory than necessary. When it's inside for, garbage collector will destroy the variable after all loops

moving every int in the array one place backwards

I'm trying to move every int in array one "cell" (position) backwards (and take the first int to the last position) in a for loop. (example: if i have array of 5,6,9 the result will be 6,9,5).
Here is my code:
int[] arr = { 1, 2, 3, 4, 5, 6 };
int temp=arr[0];
for (int i=1; i < arr.Length-1; i++)
{
arr[i - 1] = arr[i];
}
arr[arr.Length - 1] = temp;
for (int i = 0; i < arr.Length - 1; i++)
{
Console.WriteLine(arr[i]);
}
Instead of getting
2,3,4,5,6,1
I'm getting
2,3,4,5,5.
Why is my code not working? What is the right way to do such process?
This code does what you need. Sort the array.
int[] arr = { 1, 2, 3, 4, 5, 6 };
//int[] arr = { 5, 6, 9 };
//string[] arr = { "A", "B", "C" };
var result = Enumerable.Range(1, arr.Length).Select(i => arr[i % arr.Length]).ToArray();
foreach (var item in result)
{
Console.WriteLine(item);
}
Input data and Results:
//Input: { 1, 2, 3, 4, 5, 6 };
//Result: 2,3,4,5,6,1
//Input: { 5, 6, 9 };
//Result: 6,9,5
//Input: { "A", "B", "C" };
//Result: B,C,A
Remove the -1 :
for (int i=1; i < arr.Length-1; i++)
in both loops and let the loops run until the end. The condition should be i < arr.Length You never reach the last position.
Although you use arr[arr.Length - 1] to Index the last element, it is different with the loop. If you take a closer look at the finishing condition it says: < that means that i will never get the value of Length - 1 the loop will end one iteration before that. Another way to fix your code would be to change the condition and let i run until it gets this value. You can achieve it by: i <= arr.Length - 1. The little difference should also do the trick. This time the loop will end exactly after I has reached the value of the index of the last element
All you need to do is remove the - 1 from your for loop condition, as it is not iterating over all the elements in your array.
If iterating over an array of 6 elements, the indices are from 0 -> 5. So, for your example, you want your loop to go from index 1 to 5 (what you had been doing is iterating over indices 1-4 (since you were subtracting by 1).
int[] arr = { 1, 2, 3, 4, 5, 6 };
int temp=arr[0];
for (int i=1; i < arr.Length; i++)
{
arr[i - 1] = arr[i];
}
arr[arr.Length - 1] = temp;
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
}

Create 2D array from datatable

I am trying to create a 2D array from a DataTable, however Instead of getting the end result defined below. One row is not added, if that row is added, it will overwrite the column values.
Here is the end result I am looking to get:
[
//columns
['TaskID','TaskName','StartDate','EndDate','Duration','PercentComplete','Dependecies'],
//rows
['Cite','Create bibliography',null,1420649776903,1,20,'Research'], //missing row
['Complete','Hand in paper',null,1420908976903,1,0,'Cite,Write'],
['Outline','Outline paper',null,1420563376903,1,100,'Research'],
['Research','Find sources',1420390576903,1420476976903,null,100,null],
['Write','Write paper',null,1420822576903,3,25,'Research,Outline']
];
However, I get this.
[
["TaskID","TaskName","StartDate","EndDate","Duration","PercentComplete","Dependecies"],
["Complete","Hand in paper",null,1420908976903.0,1,0,"Cite,Write"],
["Outline","Outline paper",null,1420563376903.0,1,100,"Research"],
["Research","Find sources",1420390576903.0,1420476976903.0,null,100,null],
["Write","Write paper",null,1420822576903.0,3,25,"Research,Outline"]
]
I have tried:
// define the array size based on the datatable
object[,] multiDimensionalArry = new Object[breDataTable.Rows.Count, breDataTable.Columns.Count];
const int columnsArryIndex = 0;
// populate array with column names
if (breDataTable.Columns.Count > 0 && breDataTable.Rows.Count > 0)
{
// loop around columns
for (int i = 0; i <= breDataTable.Columns.Count - 1; i++)
{
// add all the column names
multiDimensionalArry[columnsArryIndex, i] = breDataTable.Columns[i].ColumnName;
}
}
// outer loop - loop backwards from the bottom to the top
// we want to exit the loop, when index == 0 as that is reserved for column names
for (int j = breDataTable.Rows.Count - 1; j >= 0; j--)
{
// get current row items array to loop through
var rowItem = breDataTable.Rows[j].ItemArray;
// inner loop - loop through current row items, and add to resulting multi dimensional array
for (int k = 0; k <= rowItem.Length - 1; k++)
{
multiDimensionalArry[j, k] = rowItem[k];
}
}
You're missing one row when creating your array since the columns name row dosent count as a row
object[,] multiDimensionalArry = new Object[breDataTable.Rows.Count + 1, breDataTable.Columns.Count];
And you need to change your for loop to take into count the extra row
// outer loop - loop backwards from the bottom to the top
// we want to exit the loop, when index == 0 as that is reserved for column names
for (int j = breDataTable.Rows.Count - 1; j >= 0; j--)
{
// get current row items array to loop through
var rowItem = breDataTable.Rows[j].ItemArray;
// inner loop - loop through current row items, and add to resulting multi dimensional array
for (int k = 0; k <= rowItem.Length - 1; k++)
{
multiDimensionalArry[j + 1, k] = rowItem[k];
}
}

Why I get 0 as a value in my array elements?

I'm encountering a problem with the code :
for (int i = 0; i < nr; i++)
{
intarray = new int[nr];
intarray[i] = generateRandom(4);
Console.WriteLine(intarray[i]+"Test1 "+i);
}
for (int i = 0; i < intarray.Length; i++)
{
Console.WriteLine(intarray[i]+"Test2 "+i);
}
//nr = 3
Some outputs : http://prntscr.com/5d8msx http://prntscr.com/5d8nkm ... .My problem that first 2 (intarray[0] and intarray[1]) are always 0, why are they always 0 because they aren't supposed to. intarray is initialiazed outside the function. Btw the generateRandom is this
Random r = new Random();
static int generateRandom(int max)
{
int randnum = r.Next(0, max);
return randnum;
}
You are creating a new array in the for-loop each time:
intarray = new int[nr];
This part should be outside the loop.
Since int is a value-type, all values of the array are initialized with its default value (0)
Initialize you array outside loop.
var intarray = new int[nr];
for (int i = 0; i < nr; i++)
{
intarray[i] = generateRandom(4);
Console.WriteLine(intarray[i]+"Test1 "+i);
}
for (int i = 0; i < intarray.Length; i++)
{
Console.WriteLine(intarray[i]+"Test2 "+i);
}
What you are doing now is create new array every time. and int init by 0.
I think your logic is wrong.
Every iteration in your first for loop, you are creating a new array reference. Since your array type is int, all elements of your array fills with 0 by default.
Since in Random.Next(int, int) overload, minimum values is inclusive, it might generate 0 as a result.
For example;
In your first iteration i is 0 and you create an array referance called intarray with new int[3] and you assing intarray[0] some random number (which is from 0 to 3) but the other elements in your array (intarray[1] and intarray[2]) are filled with 0 which is default value for an int.
At last iteration; your nr value is 3 and your i is 2. That means you fill your intarray[2] with a random number from 0 to 3, but since you didn't assing any value your intarray[0] and intarray[1] elements, they still keep 0 value by default.
As a solution, you should initialize your array outside of your for loop, like;
intarray = new int[nr];
for (int i = 0; i < nr; i++)
{
intarray[i] = generateRandom(4);
Console.WriteLine(intarray[i] + "Test1 " + i);
}
for (int i = 0; i < intarray.Length; i++)
{
Console.WriteLine(intarray[i] + "Test2 " + i);
}

find diagonal in 2 dimensional array

I have a 2-dimensional array with user-entered values. I need to find sum of the even elements in the diagonal of the array.
I know how to declare the array and get it filled by the user, but I'm not sure what even elements in the main diagonal really means.
I know I can find out if a number is even by saying:
if n / 2 == 0
Once I've reported the sum of the even elements in the diagonal, I would like to replace all 0 values in the array with ones.
Diagonal means all places where x and y cordinates are the same
Do if your array contains:
1 3 8 5
3 3 9 7
4 4 5 7
5 1 7 4
Then the diagonal are in bold.
Assuming the array is a square:
int sum = 0;
for(int i = 0; i < numOfArrayRows; i++)
{
//Use the mod operator to find if the value is even.
if(array[i][i] % 2 == 0)
sum += array[i][i];
//Change 0's to ones
for(int j = 0; j < numOfArrayCols; j++)
if(array[i][j] == 0)
array[i][j] = 1;
}
Also, next time add the "Homework" tag if you have a homework question :P
With a two-dimensional array it's really easy, since you don't need any index magic:
int a[N][N] = ...;
int sum = 0;
for(int i=0; i<N; ++i)
if(a[i][i] % 2 == 0) //or a[i] & 1, if you like, just check if it's dividable by 2
sum += a[i][i];
This C++ code shouldn't be that different in C or C#, but you should get the point. Likewise the second question would be as simple as:
int a[M][N] = ...;
for(i=0; i<M; ++i)
for(j=0; j<N; ++j)
if(a[i][j] == 0)
a[i][j] = 1;
And I suspec that the main diagonal is the one that begins with coordinates 0,0.
To replace 0 elements with 1 you would do something like:
if (array[i,j] == 0) array[i,j] == 1;
This sounds like homework - however I will help out :)
So if you have an 2D array, and in order to find the sum of the diagonal values, you will know that the indices of both of the values would match in order to provide you with each of the diagonal values.
To iterate through these you could use a simple loop that would sum up every diagonal value, as shown:
//Your Sum
int sum = 0;
//This will iterate and grab all of the diagonals
//You don't need to iterate through every element as you only need
//the diagonals.
for(int i = 0; i < sizeOfArray; i++)
{
//This will add the value of the first, second, ... diagonal value to your sum
sum += array[i,i];
}
To set each of the values that is 0 to 1, you could iterate through each element of the array and check if the value is 0, then set that value to 1, for example:
for(int i = 0; i < sizeOfArray; i++)
{
for(int j = 0; j < sizeOfArray; j++)
{
//Check if this value is 0;
//If it is 0, set it to 1, otherwise continue
}
}
int[,] array = new int[,] {{1,2,3},
{4,5,6},
{7,8,9}};
//Suppose you want to find 2,5,8
for(int row = 0; row < 3; row++)
{
for(int column = 0; column < 3; column++)
{
if((row == 0 && column == 1) || (row == 1 && column == 1) || (row == 2 && column == 1))
{
Console.WriteLine("Row: {0} Column: {1} Value: {2}",row + 1, column + 1, array[row, column]);
}
}
}
Here is the code you need, not much explain:
//Read the size of the array, you can get it from .Count() if you wish
int n = Convert.ToInt32(Console.ReadLine());
int[][] a = new int[n][];
//Reading all the values and preparing the array (a)
for (int a_i = 0; a_i < n; a_i++)
{
string[] a_temp = Console.ReadLine().Split(' ');
a[a_i] = Array.ConvertAll(a_temp, Int32.Parse);
}
//performing the operation (google what diagonal matrix means)
int PrimarySum = 0, SecondarySum = 0;
for (int i = 0; i < n; i++)
{
//The If condition is to skip the odd numbers
if (a[i][i] % 2 == 0) { PrimarySum += a[i][i]; }
//For the reverse order
int lastelement = a[i].Count() - 1 - i;
if (a[i][lastelement] % 2 == 0) { SecondarySum += a[i][lastelement]; }
}
//Get the absolute value
Console.WriteLine(Math.Abs(PrimarySum - SecondarySum).ToString());
Console.ReadKey();

Categories