Sample Array CodeΒΆ

// arrays.cpp

#include <iostream>
#include "cmpt_error.h"

using namespace std;

void test1() {
    const int N = 5; // It's a good idea to make the size of an array a const.
                     // This gives the size a name, and also makes sure that
                     // we always use the same size and never change it.

    int score[N];  // Declares a sequence of N contiguous ints.
                   // The values of these ints are unknown and
                   // could be anything.

    // We have no idea what values the following loop will print because score
    // has been created but not initialized.
    for(int i = 0; i < N; ++i) {
        cout << "score[" << i << "] = " << score[i] << "\n";
    }

    // Set all the value of score to 0.
    for(int i = 0; i < N; ++i) {
        score[i] = 0;
    }

    // Now all the value of score are 0.
    for(int i = 0; i < N; ++i) {
        cout << "score[" << i << "] = " << score[i] << "\n";
    }

    // C++ does *not* check the bounds of an array, so you are free to access
    // elements outside of an array. However, this is almost always an error,
    // and it is up to the programmer to make sure they never do this.
    cout << "\nscore[-1] = " << score[-1] << "\n";
    cout << "\nscore[" << N << "] = " << score[N] << "\n";
}

// If you know the values of the array at the time you define it, you can use
// array initializer notation.
void test1a() {
    int arr1[5] = {1, -2, 3, 0, 0};

    int arr2[] = {1, -2, 3, 0, 0}; // C++ automatically infers the length of arr2

    // These are for-each loops, which are in some cases simpler than regular
    // for-loops.
    for(int n : arr1) {
        cout << n << "\n";
    }

    cout << "\n";

    for(int n : arr2) {
        cout << n << "\n";
    }
}


// Let's write a small program that asks the user to enter some numbers, and
// then prints the average of them.
void test2() {
    // get the size from the user
    cout << "How many numbers do you want to enter? ";
    int n;
    cin >> n;

    // make sure the size is 0 or higher
    if (n < 0) {
        cmpt::error("an array must have size 0 or more");
    }

    // create a new array of n uninitialized numbers
    double nums[n];

    // read in each number from the user
    for(int i = 0; i < n; ++i) {
        cout << "? nums[" << i << "] = ";
        cin >> nums[i];
    }

    // calculate the average
    double avg = 0.0;
    for(int i = 0; i < n; ++i) {
        avg += nums[i];
    }
    avg = avg / n;
    cout << "\nAverage: " << avg << "\n";
}

// The C++ compiler determines the size of an array using it's size and value
// type:
//
//    int score[5];
//
// This is an array of 5 ints, so it uses 5 * sizeof(int) bytes of memory.
//
// The number of elements in score is sizeof(score) / sizeof(int).
void test3() {
    cout << "  sizeof(char) = " << sizeof(char) << " byte\n";
    cout << "   sizeof(int) = " << sizeof(int) << " bytes\n";
    cout << "sizeof(double) = " << sizeof(double) << " bytes\n";

    const int N = 5;

    char arr_char[N] = {'a', 'a', 'a', 'a', 'a'};
    cout << "\narr_char uses " << sizeof(arr_char) << " bytes\n";
    cout << "arr_char has " << (sizeof(arr_char) / sizeof(char)) << " elements\n";


    int arr_int[N] = {0, 0, 0, 0, 0};
    cout << "\narr_int uses " << sizeof(arr_int) << " bytes\n";
    cout << "arr_int has " << (sizeof(arr_int) / sizeof(int)) << " elements\n";

    double arr_double[N] = {0.0, 0.0, 0.0, 0.0, 0.0};
    cout << "\narr_double uses " << sizeof(arr_double) << " bytes\n";
    cout << "arr_double has " << (sizeof(arr_double) / sizeof(double)) << " elements\n";
}

// We can pass arrays to functions. Note that we don't include the size of the
// the array in the parameter argument so that we can use this with any size
// of array.
//
// Notice that we use "const" for the array parameter. This tells us, and the
// compiler, that the print does not modify arr in any way. It just reads it.
// If print (accidentally) changed a value in arr, then the compile would give
// an error message saying that you can't modify a const array.
void print(const int arr[], int size) {
    if (size < 0) cmpt::error("array size can't be negative");

    if (size == 0) {
        cout << "{}";
    } else if (size == 1) {
        cout << "{" << arr[0] << "}";
    } else {  // size > 1
        cout << "{" << arr[0];
        for(int i = 1; i < size; ++i) {  // note i starts at 1, not 0
            cout << ", " << arr[i];
        }
        cout << "}";
    } // if
}

void println(const int arr[], int size) {
    print(arr, size);
    cout << "\n";
}

void test4() {
    const int N = 5;
    int score[N];

    println(score, N); // score is uninitialized: any values could be printed!

    // Set all the value of score to 0.
    for(int i = 0; i < N; ++i) {
        score[i] = 0;
    }

    println(score, N); // prints all 0s
}

// You might wonder why the size of the array is passed as a parameter in
// print and println. Why not just calculate the size use sizeof, e.g.:
//
//   void print(int arr[]) {
//       int size = sizeof(arr) / sizeof(int);
//       // ... same as before ...
//   }
//
// This doesn't compile because the C++ compile cannot determine the number of
// elements in arr. All it knows is that arr refers to the start of an array,
// and that arr could have 0 or more elements. So we need to pass the size
// along as well.
//

// When arrays are passed as parameters, they are not copied. The function
// gets the actual array. This is efficient, and also convenient for functions
// that need to modify the array.
void fill(int arr[], int n, int size) {
    for(int i = 0; i < size; ++i) {
        arr[i] = n;
    }
}

void test5() {
    const int N = 5;
    int score[N];

    fill(score, 0, N); // set all values of score to 0

    println(score, N); // prints all 0s
}

// It would be nice if we could write a function that returns a newly
// created array, e.g.:
//
//    int[] make_int_array(int size) {
//        int arr[size];
//        for(int i = 0; i < size; ++i) {
//            arr[i] = 0;
//        }
//        return arr;
//    }
//
// Unfortunately, this doesn't compile because C++ forbids functions from
// returning arrays. However, it is possible to return pointers to arrays,
// which is practically the same thing, and we'll see that when we discuss
// pointers.

int main() {
    // test1();
    // test1a();
    // test2();
    // test3();
    // test4();
    test5();
}