List Index Out Of Bounds - c#

I am trying to retrieve one value from a combo box and place it into another combo box by using lists.
I successfully remove the value from the list, and implement it into the other list fine. But when I do this my list capacities malfunction and I get index out of bounds errors.
Scenario:
List Letter Selected: B
'Left Shift Button Pressed'
'B' Removed from Letters List
'B' Added to Numbers List
Print Out Values
Error: "Index was out of range. Must be non-negative and less than the size of collection
Line 66: Console.WriteLine("Numbers: " + numbers[i] + "\tIteration: " + i);
Number List Capacity: 8, Letters List Capacity: 4.
Number List: 1, 2, 3, 4, B. Letters List: A, C, D
CODE:
public partial class Form1 : Form
{
public List<string> letters = new List<string>();
public List<string> numbers = new List<string>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
InitialiseLists();
LoadListsIntoCombo();
}
public void InitialiseLists()
{
/*
* Add Letter Data
*/
letters.Add("A");
letters.Add("B");
letters.Add("C");
letters.Add("D");
/*
* Add Number Data
*/
numbers.Add("1");
numbers.Add("2");
numbers.Add("3");
numbers.Add("4");
}
public void LoadListsIntoCombo()
{
comboLetter.DataSource = letters;
comboNumber.DataSource = numbers;
}
public void PrintList()
{
/*
* Print Lists To Console
*/
for (int i = 0; i < numbers.Capacity; i++)
{
Console.WriteLine("NUM CAPACITY: " + numbers.Capacity);
Console.WriteLine("Numbers: " + numbers[i] + "\tIteration: " + i);
}
for (int i = 0; i < letters.Capacity; i++)
{
Console.WriteLine("LET CAPACITY: " + letters.Capacity);
Console.WriteLine("Letters : " + letters[i] + "\tIteration: " + i);
}
}
private void cmdLeft_Click(object sender, EventArgs e)
{
AddLetterToNumber(GetLetter());
RemoveLetter(GetLetter());
}
public void RemoveLetter(string value)
{
letters.Remove(value);
}
public void AddLetterToNumber(string value)
{
numbers.Add(value);
}
public string GetLetter()
{
string letter = comboLetter.SelectedItem.ToString();
return letter;
}
public int GetLetterIndex()
{
int letterIndex = comboLetter.SelectedIndex;
return letterIndex;
}
private void cmdRight_Click(object sender, EventArgs e)
{
PrintList();
}
}
}
Many thanks for any help you can provide.

Use Count property instead of Capacity. Because first one returns number of items contained in list. Second one is just says how many items you can add before list will be resized.
public void PrintList()
{
Console.WriteLine("Numbers count: " + numbers.Count);
for (int i = 0; i < numbers.Count; i++)
Console.WriteLine("Numbers: {0}\tIteration: {1}", numbers[i], i);
Console.WriteLine("Letters count: " + letters.Count);
for (int i = 0; i < letters.Count; i++)
Console.WriteLine("Letters : {0}\tIteration: {1}", letters[i], i);
}

You are using Capacity and not Count. Capacity is not the number of elements in the list.
Capacity: Gets or sets the total number of elements the internal data structure can hold without resizing.
Count: Gets the number of elements actually contained in the List<T>.
from here
http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx

Related

writing program using arrays and averages in C#

I am writing a program using GUI in C# that includes three text boxes (one for name input, one for grade input and one for grade output), and five buttons (one to take in the name/grade and add to corresponding arrays, one to display just the name and grade that were just entered, one to display lowest grade, one to display highest grade and one to display the class average).
I have the form designed but need help with some of the code, there are two arrays one for the grade and one for name both which have five values initially stored within them. Here is the code I have so far:
namespace WindowsFormsApplication3
{
using static System.Console;
public partial class highestGrade : Form
{
int[] grade = new int[] { 90, 80, 60, 70, 80, };
string[] name = new string[] { "Sally", "Joe", "Sue", "Pete", "Tom", };
double sum = 0;
double average;
int x = 4;
int y = 4;
int z = 0;
public highestGrade()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
private void addStudent_Click(object sender, EventArgs e)
{
if (x <= 9)
{
Array.Sort(grade, name);
name[x] = textBox1.Text;
grade[x] = Convert.ToInt32(textBox2.Text);
sum = sum + grade[x];
textBox1.Text = string.Empty;
textBox2.Text = string.Empty;
}
}
private void display_Click(object sender, EventArgs e)
{
outputText.Visible = true;
outputText.Text = textBox1.Text + " " + textBox2.Text;
}
private void lowestGrade_Click(object sender, EventArgs e)
{
Array.Sort(grade, name);
outputText.Visible = true;
outputText.Text = name[z] + " " + grade[z];
}
private void button4_Click(object sender, EventArgs e)
{
Array.Sort(grade, name);
outputText.Visible = true;
outputText.Text = name[y] + " " + grade[y];
}
private void averageGrade_Click(object sender, EventArgs e)
{
for (int y = 0; y < 5; y++)
{
sum = sum + grade[y];
}
average = sum / grade.Length;
string avgOutput = Convert.ToString(average);
outputText.Visible = true;
outputText.Text = "Class Average: " + avgOutput;
y++;
}
}
}
I need the program to take input for grade/name up to 10 students, while being able to output the lowest/highest grade continually whenever the user clicks. It also needs to output the total average continuously whenever the user clicks.
The average is not calculating correctly, it keeps adding to the sum for each time the average button is clicked and I cannot get the highest grade to hold its value. For example: if i enter a new grade as 100 then click highest grade, it displays that grade which is what I want. But for the next grade if i enter 95, it replaces the 100 with the 95.
Any help would be appreciated thank you.
You have to reset the current sum before adding the grades again to calculate the average correctly:
private void averageGrade_Click(object sender, EventArgs e) {
sum = 0; // reset sum
for (int y = 0; y < 5; y++) {
sum = sum + grade[y];
}
average = sum / grade.Length;
string avgOutput = Convert.ToString(average);
outputText.Visible = true;
outputText.Text = "Class Average: " + avgOutput;
}
You can also use LINQ to calculate sums and averages, no need to write for loops:
using System.Linq;
var sum = grade.Sum();
var average = grade.Average();
As for the problem with lowest/highest grade: calculate these every time the button is clicked. Eliminate the global variables y, z.
private void lowestGrade_Click(object sender, EventArgs e) {
// this probably only needs to be sorted if a value is added or removed (addStudent_Click)
Array.Sort(grade, name);
outputText.Visible = true;
// first element (with index 0) will be the lowest because arrays are sorted now
outputText.Text = name[0] + " " + grade[0];
}
You can also use LINQ .First() and .Last() to access the first or last element of a collection or without the need of sorting use LINQ .Min() and .Max() methods.

C# Index was outside the bounds of the array - specific help, please

I'm working on a small programme for booking seats on an airplane - And I keep getting this error. i want the programme to show me which seats on the plane (flysaeder) are being booking by what passenger (passagerer). Only, If I enter in more seats than I have passengers, it won't run - I need it to allow open seats (less "passagerer" than "flysaeder"). What am I doing wrong?
I'm kinda new at this, so I apologize for poor explanation.
Error occurs on "listeOverPassagerer[index] = listeOverPassagerer[i];".
namespace eksamenvingerne
{
public partial class Form1 : Form
{
int flysaeder;
int passagerer;
Random tilfældighed = new Random();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
listBox2.Items.Clear();
{
int.TryParse(txtsaeder.Text, out flysaeder);
int.TryParse(txtantalpassagere.Text, out passagerer);
if (passagerer > flysaeder)
{
MessageBox.Show("Ingen frie pladser!");
}
else
{
int[] listeOverPassagerer = Enumerable.Range(0, passagerer).ToArray();
int[] flypladser = new int[flysaeder];
for (int i = 0; i < flysaeder; i++)
{
int index = tilfældighed.Next(0, passagerer);
flypladser[i] = tilfældighed.Next(i, passagerer);
flypladser[i] = listeOverPassagerer[index];
listeOverPassagerer[index] = listeOverPassagerer[i];
}
for (int i = 0; i < flypladser.Length; i++)
{
listBox1.Items.Add("Sæde #" + i + ": Passagernr.:" + flypladser[i]); //listboxen udskriver indholdet af hver eneste plads.
}
}
}
}
}
}
Your logic actually is causing this problem:
First you make sure that passagerer <= flysaeder
if (passagerer > flysaeder)
{
MessageBox.Show("Ingen frie pladser!");
}
Then you do a for loop from 0 to flysaeder -1
for (int i = 0; i < flysaeder; i++)
But flysaeder might be larger than passagerer hence your access of listeOverPassagerer[i] will throw an exception since listeOverPassagerer is of length passagerer

Trying to delete a single value from array

I am trying to delete a value from a passed array at the selected index. Basically taking the selected index of a list box that displays the arrays and using it to delete an entry. For some reason nothing is deleted and stays the same when I run the program. I am programing in Visual Studio 2010 in C#
public double [] redrawArray(double[] ary, int selectedIndex)
{
double[] redoneArray = new double[ary.GetUpperBound(0)];
for (int i = selectedIndex; i < ary.GetUpperBound(0); i++)
{
redoneArray[i] = ary[i + 1];
}
//redoneArray[ary.GetUpperBound(0)] = 0;
return redoneArray;
}
Here is the delete button portion of code
private void btnDelete_Click(object sender, EventArgs e)
{
int selectedIndex;
if (this.lstClients.SelectedIndex <= 1)
{
return;
}
//else if ((this.lstClients.SelectedIndex - 2) < arrayIndex)
else
{
selectedIndex = this.lstClients.SelectedIndex - 2;
this.lstClients.Items.RemoveAt(this.lstClients.SelectedIndex);
lbSI.Text = (this.lstClients.SelectedIndex - 2).ToString();
redrawArray(mFirstNameArray, selectedIndex);
redrawArray(mLastNameArray, selectedIndex);
redrawArray(mAgeArray, selectedIndex);
redrawArray(mHeightArray, selectedIndex);
redrawArray(mStartWeightArray, selectedIndex);
redrawArray(mGoalWeightArray , selectedIndex);
redrawArray(mTotalWeeksArray, selectedIndex);
//arrayIndex += -1;
lstClients.Items.Clear();
loadListBox();
}
}
And here is my main code that loads it into the list
private void loadListBox()
{
string currentClient;
int lineNumber = 0;
string formattedName;
string strAvgBMI;
string strLowBMI;
string strHghBMI;
double dStartAvgBMI;
double dStartLowBMI;
double dStartHghBMI;
double dEndAvgBMI;
double dEndLowBMI;
double dEndHghBMI;
lstClients.Items.Add(" CLIENT NAME AGE HEIGHT(in) START WEIGHT START BMI GOAL WEIGHT GOAL BMI WEEKS");
lstClients.Items.Add("================= ===== =========== ============== =========== ============= ========== =========");
for (int index = 0; index < arrayIndex; index++)
{
if (mFirstNameArray[index] == null)
{
continue;
}
lineNumber++;
formattedName = mFirstNameArray[index];
formattedName += " ";
formattedName += mLastNameArray[index];
mStartBMI[index] = calcBMI(mHeightArray[index], mStartWeightArray[index]);
mEndBMI[index] = calcBMI(mHeightArray[index], mGoalWeightArray[index]);
currentClient = index.ToString() + " ";
currentClient += formattedName.PadRight(18) + " ";
currentClient += mAgeArray[index].ToString("##").PadLeft(4) + " ";
currentClient += mHeightArray[index].ToString("##.#0").PadRight(4) + " ";
currentClient += mStartWeightArray[index].ToString("###.0").PadRight(4) + " ";
currentClient += mStartBMI[index].ToString("##.#0").PadRight(4) + " ";
currentClient += mGoalWeightArray[index].ToString("###.0").PadRight(4) + " ";
currentClient += mEndBMI[index].ToString("###.#0").PadRight(4) + " ";
currentClient += mTotalWeeksArray[index].ToString("##").PadRight(4);
lstClients.Items.Add(currentClient);
}
dStartAvgBMI = sumAvg(mStartBMI, arrayIndex);
dStartHghBMI = maxArray(mStartBMI, arrayIndex);
dStartLowBMI = minArray(mStartBMI, arrayIndex);
dEndAvgBMI = sumAvg(mEndBMI, arrayIndex);
dEndHghBMI = maxArray(mEndBMI, arrayIndex);
dEndLowBMI = minArray(mEndBMI, arrayIndex);
strAvgBMI = "";
strHghBMI = "";
strLowBMI = "";
strAvgBMI = " Average: " + dStartAvgBMI.ToString("0#.#0") + " " + dEndAvgBMI.ToString("0#.#0");
strHghBMI = " High: " + dStartHghBMI.ToString("0#.#0") + " " + dEndHghBMI.ToString("0#.#0");
strLowBMI = " Low: " + dStartLowBMI.ToString("0#.#0") + " " + dEndLowBMI.ToString("0#.#0");
lstClients.Items.Add(strAvgBMI);
lstClients.Items.Add(strHghBMI);
lstClients.Items.Add(strLowBMI);
}
I'd strongly recommend using a List<double> instead, since it has a more graceful and efficient strategy for adding and removing items.
There is a significant problem with your algorithm, because you haven't actually used selectedIndex to filter out the 'deleted' item. I think it should look like this
public double[] redrawArray(double[] ary, int selectedIndex)
{
double[] redoneArray = new double[ary.GetUpperBound(0)];
int i = 0;
for (; i < selectedIndex; i++)
{
redoneArray[i] = ary[i];
}
for (; i < redoneArray.Length; i++)
{
redoneArray[i] = ary[i + 1];
}
return redoneArray;
}
Or even better:
public double[] redrawArray(double[] ary, int selectedIndex)
{
double[] redoneArray = new double[ary.GetUpperBound(0)];
Array.Copy(ary, redoneArray, selectedIndex);
Array.Copy(ary, selectedIndex + 1,
redoneArray, selectedIndex, redoneArray.Length - selectedIndex);
return redoneArray;
}
Update
The real problem, however, is that you're redrawArray method returns a new array rather than modifying the existing array. You'd have to use assign the result array back to your variables, like this:
mFirstNameArray = redrawArray(mFirstNameArray, selectedIndex);
mLastNameArray = redrawArray(mLastNameArray, selectedIndex);
mAgeArray = redrawArray(mAgeArray, selectedIndex);
mHeightArray = redrawArray(mHeightArray, selectedIndex);
mStartWeightArray = redrawArray(mStartWeightArray, selectedIndex);
mGoalWeightArray = redrawArray(mGoalWeightArray , selectedIndex);
mTotalWeeksArray = redrawArray(mTotalWeeksArray, selectedIndex);
You're starting from the selectedIndex.. but the new array doesn't contain any of the source array. This makes everything before the index 0. This can be solved with Array.Copy.
public static double[] redrawArray(double[] ary, int selectedIndex) {
double[] redoneArray = new double[ary.GetUpperBound(0)];
Array.Copy(ary, redoneArray, ary.GetUpperBound(0)); // copy the source into the destination minus one..
for (int i = selectedIndex; i < ary.GetUpperBound(0); i++) {
redoneArray[i] = ary[i + 1];
}
return redoneArray;
}
Example usage:
double[] arr = new double[] {2, 4, 6};
// remove first
arr = redrawArray(arr, 0); // {4, 6}
// remove second
arr = redrawArray(arr, 1); // {2, 6}
// etc..
If you want an array which you can delete things from, then its best to use something like List<double>, which will save you a lot of trouble.
Then to delete at a particular index, just call .RemoveAt(index)
If you still want to use Arrays externally, you can 'cheat' by using the array.ToList() function to get yourself a list, delete whatever it is you want, and then .toArray() it back. Yeah its quite inefficient, but I don't think what you're currently doing is that fast as it is.
public double[] RedrawArray(double[] ary, int selectedIndex)
{
var lst = new List<double>(ary);
lst.RemoveAt(selectedIndex);
return lst.ToArray();
}
With Linq I guess you can:
public double[] RedrawArray(double[] ary, int selectedIndex)
{
return ary.Where((d, i) => i!=selectedIndex).ToArray();
}
or:
public void RedrawArray(ref double[] ary, int selectedIndex)
{
ary = ary.Where((d, i) => i!=selectedIndex).ToArray();
}
depending on which syntax is most convenient when calling the method.
Note that in either case the array passed to this method should not be modified by other threads while the method is running. In the ref case, if a field or captured variable was passed, that variable must not be re-assigned by other threads.

how can we display the elements of an integer type array in C#

i M declaring an int type array and trying to print all its elements but it prints only last element .....give me the right code.....
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int[] arr;
int range;
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
range = Convert.ToInt32(textBox1.Text);
arr = new int[range];
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
for (int i = 0; i < range; i++)
{
arr[i] = Convert.ToInt32(textBox2.Text);
}
}
private void button1_Click(object sender, EventArgs e)
{
for(int i =0;i<range;i++)
{
textBox3.Text = textBox3.Text + arr[i].ToString();
}
}
}
}
This line: arr[i] = Convert.ToInt32(textBox2.Text); will set every element in the array to the value in textbox2. Is that your intent?
Int arrays are common. They store many integer values. And these values can be used in many ways. This introductory material covers int arrays, showing declarations, assignments, elements, loops and methods.please see here
this code is simple example that work array int
using System;
class Program
{
static void Main()
{
int[] arr1 = new int[] { 3, 4, 5 }; // Declare int array
int[] arr2 = { 3, 4, 5 }; // Another
var arr3 = new int[] { 3, 4, 5 }; // Another
int[] arr4 = new int[3]; // Declare int array of zeros
arr4[0] = 3;
arr4[1] = 4;
arr4[2] = 5;
if (arr1[0] == arr2[0] &&
arr1[0] == arr3[0] &&
arr1[0] == arr4[0])
{
Console.WriteLine("First elements are the same");
}
}
}
using System;
class Program
{
static void Main()
{
// Loop over array of integers.
foreach (int id in GetEmployeeIds())
{
Console.WriteLine(id);
}
// Loop over array of integers.
int[] employees = GetEmployeeIds();
for (int i = 0; i < employees.Length; i++)
{
Console.WriteLine(employees[i]);
}
}
/// <summary>
/// Returns an array of integers.
/// </summary>
static int[] GetEmployeeIds()
{
int[] employees = new int[5];
employees[0] = 1;
employees[1] = 3;
employees[2] = 5;
employees[3] = 7;
employees[4] = 8;
return employees;
}
}
Output
1
3
5
7
8
1
3
5
7
8
Is textBox2.Text one number, or a sequence of numbers? If it is, for example, 1,2,3 then you'll have to Split the string on , and then convert each entry of the String[] you get back to an integer, and store those in the array.
I am not sure what you are trying to do.
It appears that you are reading an input from a textbox whenever it is changed
and recreating the array to the size indicated in that textbox.
The second textbox fills the array whenever it is changed to whatever the second
textbox accepts as input (this makes no sense at all).
button1 displays array as a string, which is probably alright.
You might want to change the 2nd textbox into a button which fills the array.
Otherwise, rethink your intent of 2nd textbox, it makes no sense.
Where do you clear textBox3.Text ?
You are accumulating in this text box. When you do that, and the input overflows, you will only see the last thing added. Perhaps this is the problem. I might tweak:
private void button1_Click(object sender, EventArgs e)
{
textBox3.Text = "";
for(int i =0;i<range;i++)
{
textBox3.Text = textBox3.Text + arr[i].ToString();
}
}

Updating a list using a method?

This is a really simple question concerning a method. I'm pretty new to C# and am testing lists. How do I call the method "addTwo" so that it updates every element in the "Marks" list by two? Please note that I've already created this method (scroll down further below the main method). I just want to know how to call it in the main method.
namespace ParallelLists
{
class Program
{
static void Main(string[] args)
{
//create an list of 4 student names
List<string> names = new List<string>(4);
names.Add("Matt");
names.Add("Mark");
names.Add("Luke");
names.Add("John");
//create a list of 4 integers representing marks
List<decimal> marks = new List<decimal>(4);
marks.Add(88m);
marks.Add(90m);
marks.Add(55m);
marks.Add(75m);
Console.WriteLine("the mark of " + names[0] + " is : " + marks[0]);
Console.ReadLine();
//Upgrade everyone by 2 marks
...
}
public List<decimal> addTwo(List<decimal> mark)
{
List<decimal> temp = mark;
for (int i = 0; i < temp.Count; i++)
{
temp[i] += 2m;
}
return temp;
}
}
}
You need to make your method static, since you are accessing on a non object. also you need to update your marks collection with the returned value. You dont actually need to return the List because list is mutable.
class Program
{
static void Main(string[] args)
{
//create an list of 4 student names
List<string> names = new List<string>(4);
names.Add("Matt");
names.Add("Mark");
names.Add("Luke");
names.Add("John");
//create a list of 4 integers representing marks
List<decimal> marks = new List<decimal>(4);
marks.Add(88m);
marks.Add(90m);
marks.Add(55m);
marks.Add(75m);
marks = addTwo(marks);
Console.WriteLine("the mark of " + names[0] + " is : " + marks[0]);
Console.ReadLine();
Console.Read();
}
public static List<decimal> addTwo(List<decimal> mark)
{
List<decimal> temp = mark;
for (int i = 0; i < temp.Count; i++)
{
temp[i] += 2m;
}
return temp;
}
}
if you dont want to return the list, you can do the following:
class Program
{
static void Main(string[] args)
{
//create an list of 4 student names
List<string> names = new List<string>(4);
names.Add("Matt");
names.Add("Mark");
names.Add("Luke");
names.Add("John");
//create a list of 4 integers representing marks
List<decimal> marks = new List<decimal>(4);
marks.Add(88m);
marks.Add(90m);
marks.Add(55m);
marks.Add(75m);
addTwo(marks);
Console.WriteLine("the mark of " + names[0] + " is : " + marks[0]);
Console.ReadLine();
Console.Read();
}
public static void addTwo(List<decimal> mark)
{
List<decimal> temp = mark;
for (int i = 0; i < temp.Count; i++)
{
temp[i] += 2m;
}
}
}
Your list is already getting a reference to 'mark' why return anything when any operation you are doing will operate on that same list.
instead of:
public List<decimal> addTwo(List<decimal> mark)
{
List<decimal> temp = mark;
for (int i = 0; i < temp.Count; i++)
{
temp[i] += 2m;
}
return temp;
}
I would do:
public void addTwo(List<decimal> mark)
{
for (int i = 0; i < mark.Count; i++)
{
temp[i] += 2m;
}
}
Then in your code call is just as
addTwo(mark);
I would rename it to AddTwo to fit normal c# conventions as well.
//Upgrade everyone by 2 marks
var plustwo = addTwo(marks);
Console.WriteLine("the mark of " + names[0] + " is : " + plustwo[0]);
Console.ReadLine();
Note, that you will also need to make AddTwo a static method:
public static List<decimal> addTwo(List<decimal> mark)

Categories