=====
CS 111 - Week 14 Lecture 1 - 2025-12-02
=====

=====
TODAY WE WILL:
=====
*   Announcements
*   intro to ARRAYS!!
*   prep for next class

=====
intro to ARRAYS
=====
*   arguably the most basic data structure in Racket is
    the list;

*   arguably the most basic data structure in C++ is
    the array (the 1-dimensional array)

    *   (but Racket also does have arrays,
        and you can build Racket-style lists in C++...!)

[NOTE: we are talking about STATIC arrays here...
    DYNAMIC arrays are a topic for CS 112!]

*   an array is more "restricted" than a list --
    BUT that makes it more efficient/faster for certain
    tasks;

    *   each item in a C++ array must be of the same data type
    *   and you have to specify its size -- the number of elements --
        in advance,

    ...because the compiler will set aside a chunk of consecutive
    memory able to hold THAT many elements of THAT data type

*   so -- when you declare a [static] array,
    you have to indicate the type of its elements,
    the number of elements,
    (and the fact that you want an array...!),
    as well as its name

    Here is the basic syntax for that:

    item_data_type arr_name[num_items];

    *   NOTE: the expression used for the number of items
        MUST be of type int!!!!!!!

    *   We'd say that arr_name's data type is an "array of type
        item_data_type" -- that is, the data type of the elements
        in an array is considered to be part of that array's data type

    const int NUM_STUDENTS = 42;

    // this is declaring an array named quiz_grades
    //    that has space for 42 double values
    
    double quiz_grades[NUM_STUDENTS];

    // this is declaring an array named city_list
    //   that has space for 3 city names in an itinerary

    string city_list[3];

*   Now -- just as you should assume that a newly-declared
    local variable is UNDEFINED until you have somehow
    set it to some value,

    you should LIKEWISE assume that the elements within
    a newly-declared array are UNDEFINED until you have
    somehow set them to some value;

    *   and you should not attempt to USE an array element
        before you have, one way or another, given it
        some value;

*   so -- how CAN you access an array and its elements,
    both for giving them values and for using them?

=====
accessing an array (and its elements)
=====
*   if you mean the WHOLE array, the whole collection,
    you just write the array's name....

    // calling a function my_average with an array
    //    and its size

    my_average(quiz_grades, NUM_STUDENTS)

    *   that is -- there are NOT square brackets involved!

*   but, to indicate/access an individual item/element in an array,
    you give its INDEX, the number of steps it is
    from the BEGINNING of the array, in square brackets,

    using this syntax:

    arr_name[desired_index]
             ^ must be an int expression!!!!!!!!

    ...this is a compound expression whose data type is the
       item_data_type for array_name, whose value is the
       value in that array at index desired_index

    *   number of steps from the beginning?
        that's 0 for the first element!!

        THE INDICES of AN ARRAY are
        0 to (its size minus 1) !!!

        *********
    *   IMPORTANT: C++ does not check as closely as some languages,
        so it is especially important to make sure your array
        index *is* in the range of your array --

        since the index of the first element is 0,
        note that the index of the LAST element is its size - 1,
        NOT its size...!
        ********

    *   you can CHANGE an array element's value!

        city_list[0] = "Vancouver";
        city_list[1] = "Ishpeming";
        city_list[2] = "Los Angeles";

        cout << "What is the first city in the next itinerary?"
             << endl;

        cin >> city_list[0];

        ...and there's also a shortcut (for not-too-big-arrays)
        for initializing them AT THE TIME OF DECLARATION:

        desired_type desired_array[desired_size] = {val0, val1, ... val_size_minus_1};

        int num_chairs[4] = {3, 6, 10, 1};

    *   so -- one more time -- like a local variable,
        just be sure to fill (or partially fill) the array before
        you try to USE an element from that array/part of the array

    *   CS 111 STYLE: INITIALIZE an array before you try to use
        elements from it!

===== EXAMPLE added AFTER class (since you don't see the
      in-class examples on the board here...)
      
*   for example:

    int looky[3];

    *   here is a common way that people visualize this array
        of 3 int values named looky:

      looky
      |------|
    0 |      |
      |------|    
    1 |      |
      |------|
    2 |      |
      |------|

    *   (those indices are NOT actually stored in the computer --
        it is just handy for us in thinking about arrays)

    *   (we shouldn't assume what is in those locations yet,
        because the C++ language definition does not specify,
	and C++ compilers thus differ -- might be whatever
	happened to be in that memory before, might be something else!)

    *   ONE way of initializing looky:
        because this IS a memory location you can change,
        you can use the array name followd by square brackets
	containing the desired element's index on the
	LEFT-hand-side of an assignment statement to initialize
	or change the value at that index:

        looky[0] = 13;

      looky
      |------|
    0 |  13  |
      |------|    
    1 |      |
      |------|
    2 |      |
      |------|

        looky[1] = 5;

      looky
      |------|
    0 |  13  |
      |------|    
    1 |   5  |
      |------|
    2 |      |
      |------|

        looky[2] = 100;

      looky
      |------|
    0 |  13  |
      |------|    
    1 |   5  |
      |------|
    2 | 100  |
      |------|

    *   and you can grab a particular array element using the
        array name followed by square brackets containing
	the desired element's index:

        // this would print 5 to the screen

        cout << looky[1] << endl;

    *   and you can change a particular element's value as
        desired:

        looky[2] = 44;

      looky
      |------|
    0 |  13  |
      |------|    
    1 |   5  |
      |------|
    2 |  44  |
      |------|

*   can the array index be a variable?
    Yep!
    *   Just make sure its type is int,
        and make sure its value is in the range of the array!

    *   for example, this will print the elements of looky
        to the screen, one value per line:

    int index = 0;

    // want the index to be strictly LESS than the array's size!

    while (index < 3)  
    {
        cout << looky[index] << endl;
	index = index + 1;
    }

===== END of EXAMPLE added AFTER class

=====
can a function have an array as a parameter?
YES! but note:
=====
*   ...a C++ array does not "know" its size

    ...C++ "sees" the array as where it BEGINS

    ...this is useful! because it allows functions
       with array parameters to be usable
       with array arguments of any size!

    ...(and it is efficient enough, because the array argument
       is passed by copying over the location where it starts,
       instead of copying over the entire array)

    ...in the meantime, since that poor function does not
       have a reasonable way to determine how big its
       array argument is,
       it is considered GOOD PRACTICE to also include a parameter
       giving the array's size

    *   CS 111 STYLE: when a function expects an array as one of its
        arguments, it should also expect its size as another of its
        arguments

*****
*   HOW do you indicate an array in a function signature comment?

    PUT the type of its elements followed by []

    *   for example:

    signature: sum_array: double[] int -> double

*****
*   HOW do you declare an array parameter (in the function header?)

    funct_ret_type funct_name(..., desired_type desired_name[], ...)

    *   that is, it looks like a local static array declaration,
        EXCEPT you do NOT specify the parameter array's size,
	because its eventual argument array's size is NOT yet known,
	and can vary for different array arguments!

        ...when this function is called, the argument array WILL have
	been declared to be a particular size at that point.

    *   for example:

    double sum_array(double num_set[], int set_size)

*****
*   And, when you CALL a function with an array argument,
    you JUST give the array argument's name as that argument
    (no square brackets!)

    *   for example:

    double prices[4] = {2.99, 3.00, 4.01, 1.00};

    this would print the result of calling function
    sum_array with this array and its size as its
    arguments:

    cout << sum_array(prices, 4) << endl;

*****
*   so -- given that --
    HOW do you write function TESTS when it has an array parameter?

    *   because, C++ does NOT give a means to write a literal array;

    *   you'll need to declare example arrays for the tests,
        and THEN write the bool expressions for those tests;

    *   for example:

    tests:
       double sales[3] = {120.10, 30.20, 1.01};
       double my_list[5] = {10, 20, 3, 4, 100};

       sum_array(sales, 3) == (120.10 + 30.20 + 1.01)
       sum_array(my_list, 5) == 137.0

*   and when you RUN these tests in a testing main function,
    you'll need to DECLARE these arrays, also:

    int main()
    {
        cout << boolalpha;

        cout << "*** Testing: sum_so_far ***" << endl;

        double sales[3] = {120.10, 30.20, 1.01};
        double my_list[5] = {10, 20, 3, 4, 100};

        cout << (sum_array(sales, 3) == (120.10 + 30.20 + 1.01)) << endl;
        cout << (sum_array(my_list, 5) == 137.0) << endl;

        ...