CONTINUING our long-ago-started
intro to ARRAYS!!

*   C++ arrays are KIND of analogous to
    Racket lists --

    a COLLECTION of items all under one name,
    if you will

    BUT the C++ array is more restricted
    example of a data STRUCTURE,
    that is very efficient in a number of ways;

    *   how is it restricted?
        *   ALL of its elements are of the same TYPE
        *   its size MUST be given in advance,
	    and is then set (can't be changed)

    *   and in C++, the elements of the array
        are together -- contiguous -- in memory;

    *   when you declare an array,
        the C++ compiler tries to grab enough memory
	to hold that many of that type of
	value;

    *   SO, when you declare an array, you need to tell
        C++ *3* pieces of info:

	*   the name of the desired array
	*   the type of each of its elements
	*   how MANY elements there are

	array_type array_name[array_size]

        *   declare an array of array_size elements,
	    each of type array_type,
	    with the name array_name

	    IMPORTANT STYLE RULE:
	    ...consider these to be EMPTY, not-yet-set,
	    and so SET them/initialize them BEFORE
	    using them!

        *   another style rule (admittedly less vital):
	    WHEN you happen to know the size of the
	    array and it does not change in your
	    program,
	    try to use a named constant for that size...

*   for example, then:

    const int NUM_STUDENTS = 50;

    // this declares quiz_grades to be an array 
    //    of type int -- it now has 50 "slots"
    //    each able to hold an int

    int quiz_grades[NUM_STUDENTS];

*   what if you were, say, ASKING the user how
    many things are desired?

    int num_cities;

    cout << "How many cities do you want?: ";
    cin >> num_cities;

    // now this_trip should be an array containing
    //    num_cities' strings

    string this_trip[num_cities];

*   there is some syntactic sugar (convenient syntax)
    for 2-dimensional array-kluging:

    const int NUM_ROWS = 3;
    const int NUM_COLS = 5;
    double two_dim[NUM_ROWS][NUM_COLS];

*   you access the elements in an array
    by basically saying how many "steps"
    from the beginning of the array the
    desired element is --

    this is called giving the INDEX of
    the desired array element,

    and in C++, then, this index always
    starts at 0

    (the first array element is 0 steps
    from the beginning of the array)

    ...this also means, for an array of
    size n, that the indices go from
    0 to (n-1)
    (the first element has index 0,
     the nth element has index (n-1))

*   and, to indicate that you want JUST
    element that is index steps from the
    beginning of an array, you say:

    array_name[index]

    (that is,

    array_name

    ...is a simple expression representing the
    ENTIRE array, and

    array_name[index]

    ...is an expression representing the single
    element that is index steps from the beginning
    of array_name

*   SO, if I have:

    const int NUM_STUDENTS = 50;

    int quiz_grades[NUM_STUDENTS];

    quiz_grades[0] = 97;

    cout << quiz_grades[0] << endl;

*   by the way --

    it IS okay to say stuff like:

    quiz_grades[0]++;
    ++quiz_grades[0];
    quiz_grades[0] += 1;

*   YES, you can use a loop to do something
    to (or with) each element in an array!!

    int index = 0;
    const int NUM_STUDENTS = 50;
    int quiz_grades[NUM_STUDENTS];
    
    while (index < NUM_STUDENTS)
    {
        quiz_grades[index] = 100;
        index = index + 1;
    }

*   there IS a shortcut,
    that can ONLY be used when an array is
    first declared,
    
    to initialize its values to different values:

    array_type array_name[array_size] = {val1, val2, ...};

*   an IMPORTANT note:
    a C++ array "knows" where it starts in memory;
    BUT! it does not "know" its size;

    SO, when a C++ function expects an array argument,
    it is considered GOOD PRACTICE (and we'll also
    a class STYLE STANDARD) to ALSO have an argument
    giving the SIZE of that array;

*   so, I decide I would indeed like to
    have a function that expects an array and its
    size amongst its arguments;

    ...how will I write that function's signature?

    ...write the type followed by [] to say,
    an ARRAY of that type;

    if I want a function sum_array, that expects
    an array of doubles and its size,
    and returns the sum of those elements in
    that array,

    I'd use the signature:

    // signature: sum_array: double[] int -> double

    and the purpose is as usual:

    /*
        purpose: expects an array of doubles and its size,
           and returns the sum of those elements in
           that array
    */

    *   and in the function HEADER, you indicate
        an array ARGUMENT without giving its size
	(because the argument, eventually, will know
	its size, having already been declared...!)

    double sum_array(double values[], int values_size)

                            ^ values is a parameter array of
			      type double

    *   examples!

        /*
	    examples:
	       IF I have:

	       const int NUM_VALS = 5;
	       double my_list[NUM_VALS] = {10, 20, 3, 4, 100.1};

	       sum_array(my_list, NUM_VALS) == 137.1

               IF I have:
	       
	       const int NUM_WTS = 3;
               double worm_wts[NUM_WTS] = {10, 20, 30};

               sum_array(worm_wts, NUM_WTS) == 60
    */

*   INTERLUDE: the for loop

    the for loop is a specialized loop statement
    ESPECIALLY good for a count-controlled loop!

    for (<init_part>; <bool>; <update_part>)
    {
        statement;
	statement;
	...
    }

THIS:

    for (int i=0; i<limit; i++)
    {
        action;
    }

has the SAME behavior (mostly) as:

    int i=0;
    while (i<limit)
    {
       action;
       i++;
    }