Contents

Important takeaways

  • arrays allow us to keep track of lists of data of the same type (e.g., a list of numbers or strings or chars, etc.)
  • there are two types of arrays: static and dynamic; right now, we only care about knowing how to use static
    • static arrays require that we know the size at compile time
    • dynamic arrays let us wait until run time to set the size
  • arrays can be of any dimension (1, 2, 3, etc.) and each dimension can have any size (as long as your computer has enough memory)
  • for loops are the most appropriate structure to iterate over an array; indexes start at 0, not 1
  • using 1D arrays:
    • Declaring + initializing: string rooms[NUM_ROOMS] = {"LSB101", "LSB201"};
    • Declaring only: float rooms[NUM_ROOMS];
    • Accessing the first element of an array: rooms[0]
    • Printing the element at index i of an array: cout << rooms[i] << endl;

Background

Arrays are a way of storing a list of items. If we wanted to store five integers up until now, we would create five separate variables, one for each integer. However, arrays allow use to declare one variable and store a number of values in it. For instances, we could create an array that stores a list of names (strings), ages (ints), heights (floats), or even custom types (we'll get to that later in the semester). In an array, each value gets its own bucket. We can refer to a particular bucket based on its index in the list. Indexes are a little strange as they start at 0, not 1—this is a detail that is important to remember! Here's how arrays are typically visualized compare to a variable:

A single int variable:
age →
66
An array that contains ints:
ages →
66
53
39
24

There are two types of arrays we'll talk about in this class: static and dynamic. Static arrays store their values on the stack, and their size must be known at compile time. This has major repercussions. If you want an array to be sized based on input from the user, then you cannot use static arrays. Dynamic arrays allow us to specify the size of an array at run-time. We won't discuss dynamic arrays until later in the course; if you are interested, feel free to take a look at the Pointers and dynamic memory chapter.

Static 1D arrays

As stated earlier, static arrays are stored in the program's memory stack. Because of this is we must know the size of the array at compile time. There are two ways we can declare and initialize a static array, as shown below.

In both declarations (lines 8 and 12), on the left hand side we see the type of the array (int in this case), the name of the array, and then a pair of square brackets with the size or length of the array ([5] in this case). What's on the right side differs.

In the first example we have a combination declaration and initialization. This is great if we know the exact values that should go in the list. On the right hand side we have a pair of curly braces with each of the elements of the array separated by commas and in the order that we want them to appear in the list. We can only ever use curly braces like this if they are part of a declaration + initialization—we cannot break up the two and still use curly braces.

In the second example, we have a lone declaration, that is, there is no initialization on the right hand side. Then, on the line below. we start to assign a value to each element of the array. Let's consider line 13: myIntArray2[0] = 1;. This says: assign the integer 1 to the element at index 0 of our array. Now, let's stop right there. What's an index again? An index is our way of referring to an element of an array. As strange as it may seem, indexes start at 0, not 1. So, myIntArray2[0] is talking about the first element of the array. This looks similar to the declaration because of the square brackets, but it's not! The square brackets, when part of a declaration, signify the size of the array. When not part of a declaration, they are used to specify the index of the element to access. We can use myIntArray[0] just like a variable—we can assign values to it, we can assign it to other variables, and we can use it in expressions (e.g., cout << myIntArray2[0];.

A word about constants

Let's take a moment to clean up the code from above. I used int literals for the array sizes. This is generally bad form, because anytime you want use the size, you have to copy an paste the actual value. If you ever want to change the size, you have to change it everywhere you've used it. So, the preferred method for static arrays is to use a global const value. Here's a cleaner version of our code with constants:

(Back to top)

Iterating over arrays

In the example above, we set each element of the second array with its own dedicated line of code. That is fine if we know the values a head of time and if they do not follow any pattern. However, often when we us arrays, we want to do something similar for each element of the array, such as ask the user for some data and then store that data in the array. Or, we want to print out the value stored in each element of the array.

It turns out we can execute a block of code for each item in the array (e.g., set the value at each index, print the value, modify the value, etc.). This is called iterating over an array or walking down an array. A for loop is the most appropriate loop to perform such an iteration. We traditionally use an int variable named i to keep track of the index (think "i" for "index"), and we start at 0. Since an array with size elements has the index range 0–(size-1), our for loop for iterating over the array should almost always look like: for(i = 0; i < size; i++). If the size is stored in a different variable, then of course use that variable instead of size.

Here's an example of how we can iterate over an array and fill in each element with a value read from the user, then iterate over the array again to print out each value.

(Back to top)

Static multi-dimensional Arrays

So far we have only seen one-dimensional arrays—arrays that store a list of numbers, strings, etc. However, arrays can also store arrays of numbers, strings, etc. An array of arrays is called a two-dimensional array (similarly, an array of arrays of arrays is called a three-dimensional array, and so on). You are actually pretty familiar with 2D arrays in real life, even if you don't realize it. Anything that is a table of rows and columns can be thought of as a 2D array: pixels on a screen, values in an Excel table, etc.

A typical way to visualize 2D arrays is as an n×m table, where n is the number of rows and m is the number of columns. They are, respectively, the first and second dimensions of our array. Let's look at a concrete example. Say we want to keep track of the set of exam scores (exams 1, 2, 3, and the final exam) for three students in a class. One way to do this is to create a 2D array with dimensions 3×4 (3 rows, and 4 columns). Here's what it would look like:

scores
95.590.393.189.5
85.395.288.785.2
76.582.373.470.3

Our scores variable refers to an array (the column of boxes to the left of the arrows). This array doesn't contain any exam scores itself, but each element refers to another array with the exam scores for the respective students—these are the rows to the right of the arrows. So, to find the second student's first exam score, we would need to consider the row at index 1, and the column at index 0: scores[1][0]. Note that both the row and the column get their own pair of square brackets.

So, how does this play out in code? The example below demonstrates how to create static 2D arrays (where we know the two dimensions at compile time), how to pass them around, and how to iterate over both the rows and columns. Note that unlike 1D arrays, we have to have to for loops with one inside the other (also called nested for loops).

This program prints out the following:

99.5 90.3 93.1 89.5 
85.3 95.2 88.7 85.2 
76.5 82.3 73.4 70.3 

99.5 90.3 93.1 89.5 
85.3 95.2 88.7 85.2 
76.5 82.3 73.4 70.3 

One last thing. We can create arrays with as many dimensions as we want. 1D and 2D are the most common, but there is nothing preventing you from creating a 10D array. At that point, however, there tend to be better options, such as relying on structs (which we will learn about later).

(Back to top)