Please send questions to st10@humboldt.edu .

dynamically-allocated ARRAYS

int *quant_array_ptr;
int num_quants;

cout << "how many quantities are there? ";
cin >> num_quants;

// now I want to dynamically allocate an array of ints
//    of that size

quant_array_ptr = new int[num_quants];

// and now, I can STILL use the array notation I'm used to!

for (int i=0; i<num_quants; i++)
{
    cout << "what is the next quantity? ";
    cin >> quant_array_ptr[i];
}

// do other stuff

for (int i=0; i < num_quants; i++)
{
    cout << quant_array_ptr[i] << endl;
}

// but BE CAREFUL!!! to FREE the dynamically-allocated
//     array, you need to use SPECIAL SYNTAX!!!!!
// (compiler needs to know -- pointer is pointing to
//    an ARRAY of dynamically-allocated memory, not just
//    the FIRST element;)

delete [ ] quant_array_ptr;

// it OUGHTA be a syntax error if you don't free it this way --
//    but that's not guaranteed!!

// ...so that you deallocate the ENTIRE array!

************************************
*   NOTE: the above can be seen in-action in:
    dyn_arr_ex.cpp
************************************

QUICK NOTE -- an array of objects is just fine!

*****NOTE!!!*******
I MIS-SPOKE in lab!!
You CANNOT use the [] notation WITHOUT giving a size!
(so -- for dynamic allocation later in the program,
    you MUST use the pointer notation INSTEAD!!!)
*****************

/* this IS OKAY */

const int BOA_QUANT = 4;
boa my_boas1[BOA_QUANT];

// this is NOT OK
boa my_boas1[];   // NO NO NO NO NO

// and the following IS okay for dynamic allocation!!

boa *my_boas2;
int num_boas;

cout << "how many boas do you have? ";
cin >> num_boas;

my_boas2 = new boa[num_boas];

...my_boas2[0] ...

...
cout << my_boas2[5].get_color() << endl;

*   remember to DEALLOCATE this dynamically-allocated array
    when we are done...!

delete [ ] my_boas2;

************************************
*   see example:
    boa_array_play.cpp 
    ....to see dynamic allocation of
    an array of boas in action...
************************************

QUICK INTRO to C++ FILE I/O (note that Savitch Section 6.1 also
discusses this)

...because, now that we have dynamically-allocated arrays,
we'd love to be able to read huge quantities o'stuff from a
file into an array!

cout: output stream to the screen (to standard output)
cin: intput stream from the keyboard (from standard input)

iostream sets these two streams up for us;

for file i/o, YOU set up the streams, and then use them quite like 
cout and cin;

for THIS kind of file i/o, you use the fstream library:

#include <fstream>

*  decide if you want an input stream (of type ifstream)
   or an output stream (of type ofstream)
   and declare each that you desire:

ifstream my_in_stream;
ofstream my_out_stream;

*   ifstream and ofstream are classes with a variety of methods!
    one of these is an open method, to connect to, say, a file
    to open a stream to that file for input or output;

    ...you give open a string (is it a char*?) argument, the NAME
       of the file according to your operating system in the form
       of a string;
       *   YES -- sadly, it DOES have to be an old-style char* string,
           NOT a modern string type instance;

           WORKAROUND: if you HAVE a string variable, and you'd like to
           use it, call its c_str method -- it returns an old-style
           char* version of the calling string instance!

           string a_name;   
	   
           a_name          // has type string
	   a_name.c_str()  // has type char* (c_str returns a char*
                           //    version of the calling string, here a_name

    // but these literals below ARE char* ...

    my_in_stream.open("infile.txt");
    my_out_stream.open("outfile.txt");

    *   when you open an input stream, the stream is now ready to
        read the FIRST thing in that file;

        *   and how do you read it? just like reading from
	    the keyboard!

            double weight;
            my_in_stream >> weight;

            ...the next thing from infile.txt is converted to
	       double and read into weight;

        *   and how do you write to it? just like writing to
            the screen!

            my_out_stream << "howdy!" << endl;

*   when  you are done with a stream, it is GOOD PRACTICE
    (and yes, a class coding standard) to CLOSE it:

    my_in_stream.close();
    my_out_stream.close();

*   one more method, before we go on:

    method fail() is true if a stream could NOT be opened --
    if gives you a chance to bail out gracefully!

    my_in_stream.open("blah.txt");
    if (my_in_stream.fail())
    {
        cout << " OH NO!!! couldn't open blah.txt!" << endl;
        return;
    }

************************************
*   these are demonstrated in the posted example:
    file_io_ex.cpp
************************************

QUICK POINT: you CAN have pointers to objects;

boa *boa_ptr1;
boa *boa_ptr2;

...and you can dynamically allocate a boa for boa_ptr to point to:

boa_ptr1 = new boa;
boa_ptr2= new boa("red", 15, "pizza");

...you can then call the methods of the pointed-to boas using one
   of two different notations: (EITHER of these is acceptable!)

boa_ptr1->set_color("purple");
(*boa_ptr1).set_weight(113);

you STILL should free these boas when done:

delete boa_ptr1;
delete boa_ptr2;

************************************
*   you can see an example of a pointer to a boa 
    in the posted function:
    display_boa.cpp (and in its testing main, display_boa_test.cpp)
************************************

PASS-BY-REFERENCE (call-by-reference)
*   this is an ALTERNATIVE means of passing parameters!

*   reminder: in pass-by-value, the argument's value is COPIED
    into the parameter's memory;
*   pass-by-reference is different: 
    ...C++ passes the ADDRESS of the argument, not a copy of the
       argument's value;
       SO: when you change such a parameter in a function,
           it CHANGES the corresponding argument!
    *   you use pass-by-reference, typically,
        when you might want to change the corresponding argument!

    *   has nice "syntactic sugar" -- you still use the
        pass-by-reference int parameter like a regular int,
	the pass-by-reference double parameter list a regular
	double, etc.

*   the CLASSIC first example of this:
    you want a function that SWAPS the values of its two arguments!

    *   you CAN'T do this with pass-by-value (without using explicit pointers)

    *   you CAN with pass-by-reference;

*   so HOW do you tell C++ you want this pass-by-reference?
    ...you put an AMPERSAND & after the parameter type:

    // I want val1 and val2 to be pass-by-reference parameters:

    void swap(int& val1, int& val2)  

    *   once you've declared the parameters this way, just
        use val1 and val2 as normal! BUT if the function CHANGES
        these, be aware that the calling arguments are ALSO changed;

    *   BECAUSE	they MIGHT be changed -- only variables and things
        that can be set (lvalues) can be pass-by-reference ARGUMENTS

/* 
signature: swap: int& int& -> void

purpose: expects two pass-by-reference integer variables,
         and produces nothing, but AFTERWARDS has the side-effect
         that the value in the 1st will become the new value of
	 the 2nd, and the value in the 2nd will be the original
         value of the 1st

examples:
    int length1 = 5;
    int length2 = 7;
    swap(length1, length2);

    afterwards:
    length1 == 7
    length2 == 5

void swap(int& val1, int& val2)
{
    int temp;

    temp = val1;
    val1 = val2;
    val2 = temp;
}

*****************************************
* see swap.cpp and swap_ck_expect.cpp
*****************************************

*   people talk about INPUT PARAMETERS -- these are JUST to be used
    and not to be set;
    (typically, you use pass-by-value for these...)
 
    people talk about OUTPUT PARAMETERS -- these are MEANT to be
    changed by the function;
    (typically, you use pass-by-reference for these...)

    people talk about INPUT/OUTPUT parameters -- these are
    meant to be used AND changed by the function;
    (swap's parameters are input/output parameters...)
    (typically, you use pass-by-reference for these...)