0

I am having a issue with my current code. I am doing a project like a lot of other people, the famous SodaCrate project. I do NOT, want any solutions to the code, but I DO want to know why I can't solve the issue with "System.IndexOutOfRangeException". I get this error when I try to add more than 24 bottles into my crate (I apologize for the swedish comments).

Here is my code:

public void add_soda()
{

    Console.WriteLine("\"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\"");
    Console.WriteLine("|     Choose your beverage!        |");
    Console.WriteLine("|                                  |"); // Välkomnar användaren
    Console.WriteLine("|[1] Pepsi , Soda, 11kr            |");
    Console.WriteLine("|[2] Coca-Cola , Soda, 12kr        |");
    Console.WriteLine("|[3] Coors Light , Beer, 18kr      |");
    Console.WriteLine("|[4] Fiji, Water , 13kr            |");
    Console.WriteLine("|[5] Nocco , Energy drink , 22kr   |");
    Console.WriteLine("|[6] Redbull , Energy drink , 25kr |");
    Console.WriteLine("|                                  |");
    Console.WriteLine("\"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\"");

    //Console.WriteLine("[7] Randomize");                       <---------- Fixa

    int temp = 0;

    while (!int.TryParse(Console.ReadLine(), out temp) || !(temp < 7 && temp > 0)) // Detta är en failsafe, ifall väljaren väljer något som är över 7 eller under 1 kommer följande kod att skrivas ut.
    {
        // Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Invalid input, please try again.");
        // Console.ResetColor();
    }   

    switch (temp) // Denna switch statementen kommer låta oss lägga till flaskor i vår crate
    {
        case 1: //Om anändaren skriver in ett tal mellan 1 och 6, kommer följade cases att skriva ut deras WriteLines.
            Console.WriteLine(">>> You choose Pepsi <<<");
            myCrate[numberOfBottles] = new Bottle("Pepsi", "Soda", 11); // Här skapas en läsk med namnet Pepsi som kostar 11kr.
            numberOfBottles++; // Denna funktion gör så att en läsk läggs in i craten varje gång den skapas.
            break;
        case 2:
            Console.WriteLine(">>> You choose Coca-Cola <<<");
            myCrate[numberOfBottles] = new Bottle("Coca-Cola", "Soda", 12);
            numberOfBottles++;
            break;
        case 3:
            Console.WriteLine(">>> You choose Coors Light <<<");
            myCrate[numberOfBottles] = new Bottle("Coors Light", "Beer", 18);
            numberOfBottles++;
            break;
        case 4:
            Console.WriteLine(">>> You choose Fiji <<<");
            myCrate[numberOfBottles] = new Bottle("Fiji", "Water", 13);
            numberOfBottles++;
            break;
        case 5:
            Console.WriteLine(">>> You choose Nocco <<<");
            myCrate[numberOfBottles] = new Bottle("Nocco", "Energydrink", 22);
            numberOfBottles++;
            break;
        case 6:
            Console.WriteLine(">>> You choose Redbull <<<");
            myCrate[numberOfBottles] = new Bottle("Redbull", "Energydrink", 25);
            numberOfBottles++;
            break;
        default:
            //Console.ForegroundColor = ConsoleColor.Red;         // <<<<<-----------------   FIXA
            Console.WriteLine("Invalid choice!");
           // Console.ResetColor;
            break;
    }
    try
    {
        if(numberOfBottles >= 25)
        {   
            Console.WriteLine("The crate is currently full!");
        }
    }
    catch (IndexOutOfRangeException e)
    {
        Console.WriteLine(e.Message);
        throw new ArgumentOutOfRangeException("index paramater is out of range", e);
    }
}

Could anyone give me an idea or a hint of why the Exception is being thrown? I've tried a if-else statement as well I am currently quite confused.

György Gulyás
  • 1,290
  • 11
  • 37
  • 1
    Move to using a `List` instead of an array; your array length is set at initialization and you can't move past it without re-initializing. Easier to use a `List` when adding things. Writing answer now. – Hazel へいぜる Nov 29 '18 at 18:17
  • Because you have created `myCrate` as an array that has a size of 24 (it only can hold 24 elements) –  Nov 29 '18 at 18:20
  • Hi PerpetualJ, I haven't gotten far enough to have knowledge regarding Lists just yet, so even if it is easier (which I have read on multiple occasions), I was wondering if there is any other fale-safes I could try? Also, we are not(!) allowed to use Lists. – b.stenberg Nov 29 '18 at 18:20
  • Hi elgonzo. I am aware of that, we are to have an array which is limited to 24 elements. I want to both: Inform the user that the crate is full (which I have don), and also keep the system going without throwing an Exception. – b.stenberg Nov 29 '18 at 18:21
  • The create is full **when there are 24 bottles in it**. And you should check that **before** you try and add another bottle to it. – stuartd Nov 29 '18 at 18:22
  • 1
    Sorry, i deleted my previous comment. Note that array indexes are zero-based. So, for a 24-element array, valid indexes are 0, ..., 23. You use `numberOfBottles` as array index, so you should test if `numberOfBottles` becomes 24 or greater (indicating the array is full). Or, if you want to start with `numberOfBottles = 1` for the 1st bottle, use `numberOfBottles-1` as array index. –  Nov 29 '18 at 18:24
  • 1
    @elgonzo The index `numberOfBottles` should be compared to the `Length` of the array. In all cases it should be less than the `Length`. – Hazel へいぜる Nov 29 '18 at 18:25
  • Thank you guys for all of your answers. I will make sure to take all of your tips in consideration and solve this issue! Its amazing how quick you get a reply on here (Im new to this site). Amazing. – b.stenberg Nov 29 '18 at 18:28

2 Answers2

2

The issue you have occurring is due to your attempt to access a part of the Bottle[] that doesn't exist. Since you've instantiated the array with a certain length, you cannot go beyond that length. Initially (and always) you should check the index you wish to use against the Length property of your array prior to attempting to access it. Say we have an int[] for this entire example, and we initially give it a Length of 3.

int[] someNumbers = new int[3];

In the case above we have created a new int array with 3 slots of memory allocated. If we try to access it with hard coded numbers the problem becomes very obvious:

someNumbers[0] = 1;
someNumbers[1] = 2;
someNumbers[2] = 3;
someNumbers[3] = 4; // Blows up here.

The reason the fourth index of 3 doesn't work is because in C# collections are accessed with zero-based indices; this means that access starts at zero and climbs from there. So technically elements are one space behind where you think they are (if you're used to traditional number systems that start at one).

If you take the same principal and access the array with a variable instead, the same thing will happen but it is less obvious; I assume you know what the ++ operator does for this.

int index = 0;
int[] someNumbers = new int[3];
someNumbers[index++] = 1; // index = 0
someNumbers[index++] = 2; // index = 1
someNumbers[index++] = 3; // index = 2
someNumbers[index++] = 4; // index = 3 :: Blows up here.

This blows up on the fourth index of 3 for the exact same reason. The way to get around this is to check the index prior to access:

if (index < someNumbers.Length)
    someNumbers[index++] = 1;

This code works because the assignment will only execute if the index is within the bounds of the array.


Adjust Array Size

Now in other languages there are ways to resize an array quite easily; but C# doesn't let us do this. Good new for us, there is a work-around for it. Again I will be using int[] to demonstrate.

Say we create our initial array with a length of 3:

int[] someNumbers = new int[3];

Somewhere along the road, we decide we need more than 3 numbers for some reason; well, we need a bigger array now. To do this (very inefficiently) you can create a new array with a bigger size and just add all of the old values:

int[] newNumberArray = new int[someNumbers.Length + 10];
for (int i = 0; i < someNumbers.Length; i++)
    newNumberArray[i] = someNumbers[i];

The code above creates a bigger array, and puts all of your old values in it. Remember that this is a very inefficient way to accomplish this and I heavily recommend using List<T> or some similar object instead.

Hazel へいぜる
  • 2,751
  • 1
  • 12
  • 44
-1

In My opinion the problem is, you use the index operator on myCrate [] on array, which does not have enough space in it.

If you know you will have 7 item in the array then please create enough place for it. This code should be like this:

myCrate = new Bottle[7];

And now youa are able to use the index operator for 0 to 6 on this array

György Gulyás
  • 1,290
  • 11
  • 37