The below IndexOutOfRangeException is not letting my code run (it compiles). While I understand this kind of exception (array indexes etc) the issue is, what I am trying to do is simply update the String subsection2 with the value in cell B[excelrow]. For some reason, there is an index out of bounds exception which to me does not make sense. Neither subsection2 or excelrow is part of an array. The only array I can think of is the excel array, but excelrow is an integer with value of 3, it should updated to row B3, and so on. (I've even tried updating with B3 directly and I get the same error).
To help you out further with context, this method called createsource takes as input the excel spreadsheet and the total rows in that sheet. It does the below code to output a 2D array containing in the first dimension the excel index of each new order (each different customer), and the 2nd dimension is the number of items ordered per customer.
The method for the code is below:
private int[,] createsource(Microsoft.Office.Interop.Excel.Worksheet xlWorksheet, int totalRows)
{
String subsection = "";
object subsection2 = "";
int orders = 0;
//figures out how many different pages there are going to be
for (int n = 3; n < totalRows + 1; n++)
{
if (!(xlWorksheet.get_Range("B" + n.ToString()).Text == subsection))
{
subsection = xlWorksheet.get_Range("B" + n.ToString()).Text;
orders++;
}
}
MessageBox.Show(orders.ToString());
int[,] source = new int[orders, 2];
int excelrow = 3;
subsection2 = xlWorksheet.get_Range("B" + excelrow.ToString()).Text;
int i;
for (i = 0; i < orders + 1; i++)
{
int j = 1;
if (excelrow == totalRows + 1)
{
break;
}
//Out of bounds exception is found in the below if statement updating subsection2:
if (!(xlWorksheet.get_Range("B" + excelrow.ToString()).Text == subsection2))
{
source[i, 0] = excelrow;
//MessageBox.Show(xlWorksheet.get_Range("B" + excelrow.ToString()).Text.ToString());
subsection2 = xlWorksheet.get_Range("B" + excelrow.ToString()).Text;
excelrow++;
}
for (int iter = 0; iter < 1;)
{
if (excelrow == totalRows + 1)
{
break;
}
if (xlWorksheet.get_Range("B" + excelrow.ToString()).Text == subsection2)
{
excelrow++;
j++;
}
if (!(xlWorksheet.get_Range("C" + excelrow.ToString()).Text == subsection2))
{
subsection2 = xlWorksheet.get_Range("C" + excelrow.ToString()).Text;
iter = 1;
}
}
source[i, 1] = j;
}
MessageBox.Show(source[2, 0].ToString());
return source;
}
I see the problem. You're declaring source as:
int[,] source = new int[orders, 2];
... okay, but look at your loop:
for (i = 0; i < orders + 1; i++)
... which later feeds into:
source[i, 0] = excelrow;
Okay, so if orders = 100, you've declared a 100 long array, going from 0-99. Then your loop, you go from 0 to "less than 100+1", aka 0-100. When you get to the last loop, you're using a value of i=100, and trying to put it into the array spot that doesn't exist.
You need to either decrease your loop by one, or increase your array size by 1.
Related
I'm trying to add an item to an array in C#. I can not take shortcuts such as using lists.
I understand that to do this I must create a new array. This is the code that I have already.
public void addAtLocation(int location, String element)
{
String[] newMyArray = new string[myArray.Length + 1];
for (int oldIndex = 0, newIndex = 0; oldIndex < myArray.Length + 1; oldIndex++, newIndex++)
{
if (newIndex == location)
{
newMyArray[oldIndex] = element;
oldIndex--;
}
else
{
newMyArray[newIndex] = myArray[oldIndex];
}
}
myArray = newMyArray;
}
I'm not looking for just a fix my code solution. I need to understand why this is happening.
In the for loop, the condition must be either oldIndex <= myArray.Length - 1
or oldIndex < myArray.Length, not oldIndex < myArray.Length + 1.
public void addAtLocation(int location, String element)
{
String[] newMyArray = new string[myArray.Length + 1];
for (int oldIndex = 0, newIndex = 0; oldIndex <= myArray.Length - 1; oldIndex++, newIndex++)
{
if (newIndex == location)
{
newMyArray[oldIndex] = element;
oldIndex--;
}
else
{
newMyArray[newIndex] = myArray[oldIndex];
}
}
myArray = newMyArray;
}
Your troubles stem from it being hard to read. Try a different approach.
public void addAtLocation(int location, String element)
{
String[] newMyArray = new string[myArray.Length + 1];
int addedUnit = 0;//sort of like a flag to indicate the element has been inserted
for (int i = 0; i < myArray.Length; i++)
{
if (i == location)
{
newMyArray[i] = element;
newMyArray[i+1] = myArray[i]; //add two elements
addedUnit = 1;
}
else
{
newMyArray[i+addedUnit] = myArray[i];
}
}
myArray = newMyArray;
}
So the main problem is the conditional of the for loop. You are trying to decrease oldIndex inside the loop to keep track of which items have been copied but since it is your loop variable, you actually end up running past the end of the new array as newIndex gets incremented every time.
Change newIndex to be the loop variable in the condition:
for (int oldIndex = 0, newIndex = 0; newIndex < myArray.Length + 1; oldIndex++, newIndex++)
Note that this works better than changing the condition to be oldIndex < myArray.Length which would miss adding the new item at the last position.
Note that this is actually overly complicated even if you can't use List<string> because there are built-in methods for copying arrays. For example:
public void addAtLocation(int location, string element)
{
string[] newMyArray = new string[myArray.Length + 1];
Array.Copy(myArray, 0, newMyArray, 0, location);
newMyArray[location] = element;
Array.Copy(myArray, location, newMyArray, location + 1, myArray.Length - location);
myArray = newMyArray;
}
Your code:
for (int oldIndex = 0, newIndex = 0; oldIndex < myArray.Length + 1; oldIndex++, newIndex++)
is going to throw an index out of bounds exception. Why? Well, just carefully walk through the code. Basically, you need to pretend that you are the Visual Studio debugger, and step through the code (trust me, we all do this). As you walk the code, I think you will quickly realize that this is what you really need to do:
for (int oldIndex = 0, newIndex = 0; oldIndex < myArray.Length; oldIndex++, newIndex++)
Reason being, your intention was to walk the old array (the one that's 1 less than the new one), and copy the values over to the new array. But the actual code was trying to walk the old array for the number of elements in the new array plus one... Yeah - you had the opposite operator. Easy peasy!
This solution factorizes a number (numInput), it works perfectly well except for a logic error I can't seem to find no matter how much I track the solution. The logic error causes the returned result to be 0 no matter the value initialized for numInput.
using System;
namespace factorizer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(factorialise());
Console.ReadKey();
}
private static int factorialise()
{
int numInput = int.Parse(Console.ReadLine());
int[] number = new int[numInput];
for (int i = 1; i < numInput; i++) //stores the (n-1)...(n-i) value for the number input'd in the array number[i]
{
number[i - 1] = numInput - i; //the element indicating the index number is 'i - 1' index values start from zero
}
for (int index = 0; index < number.Length; index++) //multiplies the element corresponding the index number with the number input'd
{
numInput = numInput * number[index];
}
return numInput;
}
}
}
Your last item in array stays uninitialized (i.e. equal to zero). Change items count:
int[] number = new int[numInput-1];
Also why not simply use for loop?
int result = 1;
for(int i = 1; i <= numInput; i++)
result *= i;
And another sample just for fun
Enumerable.Range(1, numInput).Aggregate(1, (a,i) => a * i)
I feel like an idiot for asking this but I can't for the life of me figure out why this IndexOutOfRangeException is happening. (I mean, i know WHY it's happening, I just don't know what is invalid about my code) Check the code below for where the error is being thrown:
public int[, ,] FindTablePairings(System.Text.RegularExpressions.MatchCollection mcBegin, System.Text.RegularExpressions.MatchCollection mcEnd)
{
int[,,] intTablePairs = new int[mcBegin.Count, 1, 1];
int[] intBegin = new int[mcBegin.Count];
int[] intEnd = new int[mcBegin.Count];
for (int q = 0; q < mcBegin.Count; q++)
{
intBegin[q] = mcBegin[q].Index;
}
for (int q = 0; q < mcEnd.Count; q++)
{
intEnd[q] = mcEnd[q].Index;
}
int intBeginCount = mcBegin.Count;
int intEndCount = mcEnd.Count;
int i = 0;
int j = 0;
int k = 0;
while (i < intBeginCount)
{
j = i;
while (j < intEndCount)
{
if (intBegin[i + 1] < intEnd[j])
{
j++;
}
else
{
intTablePairs[i, 0, 0] = intBegin[i];
intTablePairs[i, 1, 0] = intEnd[j];
intEnd[j] = -1; //EXCEPTION OCCURS HERE
break;
}
}
if (j == intEndCount)
{
intTablePairs[i, 0, 0] = intBegin[i];
intTablePairs[i, 1, 0] = intEnd[j - 1];
intEndCount--;
}
while (k < intEndCount)
{
if (intEnd[k] == -1)
{
k++;
}
else
{
intTablePairs[i,0,0] = intBegin[i];
intTablePairs[i,1,0] = intEnd[k];
intEnd[k] = -1;
k=0;
break;
}
}
}
return intTablePairs;
}
The code is just looking at character indexes of occurrences of beginning tags and ending tags. Nothing super complicated...but the worst part is that the exception is thrown at intEnd[j] = -1;, and in the Debugger, before that statement is executed, all the arrays and MatchCollections are properly initialized and populated, including intEnd[]! I've debugged to make sure the array exists and is initalized, and I've also cleaned the solution and rebuilt it.
Anybody have any suggestions as to what's going on here??
I believe the error is actually on this line
intTablePairs[i, 1, 0] = intEnd[j];
The problem here is that you've defined the length of last 2 dimensions to both be 1 on intTablePairs. Using the index 1 is hence invalid as it's equal to the length. It seems like you meant to define the bounds as
int[,,] intTablePairs = new int[mcBegin.Count, 2, 2];
Maybe look at this:
int[] intEnd = new int[mcBegin.Count];
Replace mcBegin on mcEnd and try it out.
I suppose intEnd should be set with mcEnd.Count capacity. So instead of:
int[] intEnd = new int[mcBegin.Count];
You should have:
int[] intEnd = new int[mcEnd.Count];
Hope it helps.
im tunning this loop and what to populate the array with the output of my methods, im not sure about that last part "array2DB[i,i] =" how shold i do this.
updated loop based on replyes
private void BackGroundLoop()
{
for (int i = 1; i < 31; i++)
{
string txbName = "br" + i + "txt" + '3';
TextBox txtBCont1 = (TextBox)this.Controls[txbName];
string string1 = txtBCont1.Text.ToString();
UpdateFormClass.runUserQuery(string1);
array2DB[0, i - 1] = int.Parse(UpdateFormClass.gamleSaker.ToString());
array2DB[1, i - 1] = int.Parse(UpdateFormClass.nyeSaker.ToString());
}
}
I'm not 100% sure what you want to do, but you want probably this instead of your last line:
array2DB[0, i - 1] = int.Parse(UpdateFormClass.gamleSaker.ToString());
array2DB[1, i - 1] = int.Parse(UpdateFormClass.nyeSaker.ToString());
-1 in index is needed, because arrays are indexed from 0 in .NET.
This is the most you can do, without running into exception:
int[,] array2DB = new int[2, 30];
for (int i = 0; i < 30; i++)
{
string txbName = "br" + i + "txt" + '3';
TextBox txtBCont1 = (TextBox)this.Controls[txbName];
string string1 = txtBCont1.Text.ToString();
UpdateFormClass.runUserQuery(string1);
array2DB[0,i] = int.Parse(UpdateFormClass.gamleSaker.ToString());
array2DB[1,i] = int.Parse(UpdateFormClass. nyeSaker.ToString());
}
Note that you can't have array2DB[2, *] or above because it will generate an arrayoutofbound exception.
You have to use two for loops. One for each the x and y axis of the array.
for (int i = 0; i < 2; i++){
for (int j = 0; j < 30; j++)
{
....
array2DB[i,j] = int.Parse(UpdateFormClass.gamleSaker.ToString())
, int.Parse(UpdateFormClass.nyeSaker.ToString());
}
}
I've been working on an Access file editor in C#, and i've been trying to get a search feature added to my program. So far, I have the database file populate a 2D array, which i then use to populate a ListView box in another window. From this new window, I would like to be able to search each entry by Model Number. So far, i've managed to incorporate the Levenstein Algorithm, which seems to have much use. I can get the algorithm to assign the distance value between each entry and the search keyboard, and assign that value to another integer array. I can also sort the results in increasing order.
However, my current problem is that i'd would like to have the Model numbers sorted with the same respect to the distance values from the Levenstein Algorithm, so that the most relevant result becomes the first choice in the ListView box. Any ideas anyone??!?!
Here's what i've got so far:
private void OnSearch(object sender, System.EventArgs e)
{
string a;
string b;
int[] result = new int[1000];
int[] sorted = new int[1000];
for (int i = 0; i < rowC; i++)
{
a = PartNum[i]; // Array to search
b = SearchBox1.Text; // keyword to search with
if (GetDistance(a, b) == 0)
{
return;
}
result[i] = GetDistance(a, b); //add each distance result into array
}
int index;
int x;
for (int j = 1; j < rowC; j++) //quick insertion sort
{
index = result[j];
x = j;
while ((x > 0) && (result[x - 1] > index))
{
result[x] = result[x - 1];
x = x - 1;
}
result[x] = index;
}
}
public static int GetDistance(string s, string t)
{
if (String.IsNullOrEmpty(s) || String.IsNullOrEmpty(t))
{
MessageBox.Show("Please enter something to search!!");
return 0;
}
int n = s.Length;
int m = t.Length;
if (n == 0)
{
return m;
}
else if (m == 0)
{
return n;
}
int[] p = new int[n + 1];
int[] d = new int[n + 1];
int[] _d;
char t_j;
int cost;
for (int i = 0; i <= n; i++)
{
p[i] = i;
}
for (int j = 1; j <= m; j++)
{
t_j = t[j - 1];
d[0] = j;
for (int i = 1; i <= n; i++)
{
cost = (s[i - 1] == t_j) ? 0 : 1;
d[i] = Math.Min(Math.Min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
_d = p;
p = d;
d = _d;
}
return p[n];
}
Do you have LINQ available to you? If so:
var ordered = PartNum.OrderBy(x => GetDistance(x, SearchBox1.Text))
.ToList();
// Do whatever with the ordered list
Note that this has the disadvantage of not aborting early if you find an exact match, as well as not making the actual distances available - but it's not entirely clear how you're using the results anyway...
Another option would be:
var ordered = (from word in PartNum
let distance = GetDistance(word, SearchBox1.Text))
orderby distance
select new { word, distance }).ToList();
Then you've got the distance as well.
In order to sort your array by Levenstein distance you need to include the model numbers as part of your array so that, when you sort the array by Levenstein number, the model numbers will go along for the ride.
To do this, create a class representing each part:
public class Part
{
public string PartNumber;
public int LevensteinDistance;
}
and then create an array of Part:
Part[] parts;
You can then reference each element like so:
parts[n].LevensteinDistance
parts[n].PartNumber