Comment Notes:
    Comments should be placed whereever something might not
    be immediately clear.  Every function prototype should
    have comments to elucidate its arguments, return type,
    and overall purpose.  Variables often have comments to
    explain what values they store.  Function definitions
    should explain HOW they do their job as well as what
    they do, their arguments, and return value.

    There are two styles of comments:  C-style and C++-style.
    C++ style comments start with a // symbol and continue
    until the end of the current line.  C-style comments
    begin with a /* and end with the next encountered */.
    Both are still popular among C++ programmers.  /**/ is
    often used in beginning comments (like the general program
    description) or on comments spanning multiple lines.

Indention:
    Every time you open a (curly) brace ({) you should indent all
    following statements one level.  Then, when you reach the
    matching closing (curly) brace (}), you should unindent that
    and all following lines.

    You will be tempted to use the Tab key (which produces tab
    characters in your file).  Unfortunately, every program that
    reads your code will treat the tab character a little dif-
    ferently.  One will represent it with 4 spaces.  Another will
    see it as 8 spaces.  Others will give it a variable width
    based on the context of lines around it.  Tab characters are
    generally to be avoided.  (Some rogue editors will forcibly
    convert your spaces to tabs when you reach 8 spaces.  Steer
    clear of them.)

    Another good tip to help is to close the (curly) brace as
    soon as you open it and then cursor/click up to insert your
    (indented) lines in between.  For instance, when you start
    a function definition, do this:

        int main(void)
        {
        }

    And then move up and insert your (indented) code between
    the (curly) braces ({}):

        int main(void)
        {
            // other code goes here
            return 0;
        }

    In fact, I just did it then out of habit.  *smile*

Variable Names:
    Try to choose good variable names -- even when a math formula
    tries to make you use a single letter.  (Sometimes this becomes
    tedious, of course.  Use your best judgement.  But if I catch
    you using a, b, c, d, ... for all of your variable names instead
    of even trying to make good clear ones, I'll whack you but hard!)

Streams:
    All streams have a property known as cascadability.  This means
    that you can output multiple things to the same cout by simply
    linking together several '<< item' segments:

        cout << "string1" << var << "string2" << endl;

    You can read several variable's values through cin the same
    way:

        cin >> var1 >> var2 >> var3 >> var4;

    Note also that you don't have to place everything on the same
    line:

        cout << "string1" << var
             << "string2"
             << endl;

    So if you have many things to print in a row, you can continue
    the statement on the next line of your code file.

Input:
    Inputs normally are assumed separated by spacing of some kind
    (spaces, Enters, tabs, etc.).  The only difference is when
    reading character data.  If you are reading a char type variable,
    the input stream (cin) will still skip spaces, but there don't
    have to be spaces separating multiple characters.  (If there
    were several numbers to be read, they would have to be separated
    by something non-numeric -- like spaces -- for cin to tell them
    apart.)

Output:
    Make sure when sending output to a stream (like cout) to place
    spacing correctly between variables.  If you don't place spacing
    (either with strings or characters), the computer will simply
    output the values abutting and they will look like one long
    value.  For instance, if you print the first three integers
    with no spacing:

        cout << 1 << 2 << 3;

    You'll get:

        123

    On the screen.  But with spacing:

        cout << 1 << '\t' << 2 << " " << 3;

    You get something more readable:

        1       2 3

    (Note the printing of the tab character vs. the single space.
    Either could have been a string or character literal (literal
    value, that is).  I could have said "\t" or ' '.  Or both could
    have been character literals or both could have been string
    literals.  As long as they are there to keep the numbers apart
    so the user can more easily see we are printing multiple values
    and not one longer value.)

Function Design:
    When designing a function, try to make it as re-usable as you
    can.  Note how the input function simply reads the input of
    the side.  It doesn't prompt.  That way the programmer of the
    main (still you here, but possibly someone else later) can
    simply decide how to prompt before calling the input function.

    This main-programmer decided to prompt for all the sides at
    once:

        cout << "Enter lengths of triangle's sides:  ";
        side1 = input();
        side2 = input();
        side3 = input();

    They could just as easily have decided to prompt for them
    individually:

        cout << "Enter length of first side of triangle:  ";
        side1 = input();
        cout << "Enter length of second side of triangle:  ";
        side2 = input();
        cout << "Enter length of third side of triangle:  ";
        side3 = input();

    Since the input function is so general, it is easy to use
    it in many different ways.

    Likewise, the heron function is re-usable to calculate a
    triangle area given three side lengths.  If the caller
    only has base and height, they can't use this function.
    But I would hope they could figure out the area themselves
    in that situation.  *smile*

Helper Functions:
    Other functions aren't there to be re-used many times.  They are
    there to clean up this application.  The other functions in this
    program are of this type.  The print function encapsulates our
    output format.  If we wanted to print other things in this same
    format, we could re-use it.  But at the very least, it is tucked
    out-of-the-way in a separate function.

    The greeting and goodbye functions likewise remove cluttering
    output statements from the main program.

Calling Functions:
    In algebra, you would evaluate a function at a particular value
    of the independent variable.  Programmers are more succinct.  We
    call (or invoke) a function.  The call is responsible for giving
    the function any values it requires.  Note how the greeting and
    goodbye functions take no arguments (have a void or empty argument
    list) and so the call has simply empty parenthesis at the end:

        welcome_user();
        goodbye_user();

    These functions also return no value and so they are simply in
    the statement alone (terminated by the ; as usual).

    The print function, though, takes a single argument which is
    the area to display.  But since it doesn't return anything
    either, it is also alone on the statement:

        print(area);

    The heron function requires three input values and returns the
    single calculated value:

        area = heron(side1, side2, side3);

    Finally the input function needs nothing to start working, but
    returns the value that was input:

        side1 = input();

    So if the function needs nothing to start working, it will have
    empty parenthesis after its name in the call.  If a function
    returns a calculated value, it should be stored with an assignment
    statement.  If it returns nothing, the call can be on the statement
    alone.

Local Variables:
    Sometimes you'll be writing a function and need to store something.
    If this calculation is the final answer, you could simply place
    it on the return statement.  But if it is a temporary value or
    something that merely needs to be kept for a short time in memory,
    you can create a variable inside the function.  Such variables
    are known as local variables.  (All the variables you've been
    using till now have been local to the main function.)

    For instance, the input function needs to read a value from the
    user.  Read values need a place to reside in memory.  So, to store
    the value, the input function creates a local variable:

        double input(void)
        {
            double side_length;
            cin >> side_length;
            return side_length;
        }

    side_length will exist only during a single function execution.
    When the input function returns, side_length will cease to
    exist.  Its value will be returned, but the variable itself
    will no longer be in the computer's memory.  (That's just one
    reason the returned value must be stored using an assignment
    statement.)

    The heron function also uses a local variable to hold the
    so-called semi-perimeter calculation (s):

        double heron(double s1, double s2, double s3)
        {
            double s;
            s = (s1+s2+s3)/2;
            return sqrt(s*(s-s1)*(s-s2)*(s-s3));
        }

    Here we create s and then store half the triangle's perimeter
    in it.  This quantity is then used (somewhat magically, I must
    say) to determine the area of the triangle in the return
    statement.

Arguments:
    Arguments are programmers way of saying 'independent variable'.
    They are the required inputs to the function which let it do
    its job.  If none are needed (if a function simply reads from
    the user directly), the word void can be placed inside the
    function's head -- but NOT in the call!

    An argument (or input) is a value that has already been stored
    or calculated in the program, but that this function needs in
    order to perform its calculations (or whatever job).  If the
    user has already entered a value and a function called later
    needs that value, we send it (or pass it) to the function
    through the argument list.

    There are many types of arguments.  Formal arguments are those
    listed in the function's head (be it on the definition or the
    prototype).  These arguments have a data type and a name.  The
    name of a formal argument is only valid during the funciton's
    execution.  After the return statement executes, all formal
    arguments disappear (just like local variables do).

    Actual arguments are those in the function call.  An actual
    argument is just a value:  literal, constant, calculation,
    varible.  No types are mentioned because they are implicit
    in the calculation or the variable/constant declaration.

    Finally, the arguments we've seen up till now are called value
    arguments because only the value of the actual argument is
    copied into the formal argument.  (No further connection is
    really made between the actual and formal arguments.)

Data Flow:
    All information (data) in your program must at some time
    reside in memory (except literals).  Most of them will be
    stored 'permanently' (that is for the entire program run)
    in main's local variables (which will exist until main does
    -- which is for the entire program execution).  But how do
    they get there and where do they go as the program runs?

    Values can be stored in a memory location by input ('cin >> var'),
    assignment ('var = value'), or initialization ('type var = value'
    or 'type var(value)').  We don't use initialization a lot (except
    for constants which cannot be input or assigned).  Values can
    be produced by calculation (a literal is here considered the
    simplest possible calculation) or entered by the user.

    In the triangle program, data flows like this:

                       main (side1, side2, side3, area)
              ----------------------
              |   |  |  |  ||  |   |
   welcome_user  s| s| s| s||  |a  goodbye_user
                 i| i| i| i||  |r
                 d| d| d| d||  |e
                 e| e| e| e||  |a
                 1| 2| 3| 1||  |
      input--->---->-->--  ||  ---->---print
        (side_length)     s||
                          i||
                          d||
                          e||
                          2||a
                           ||r
                          s||e
                          i||a
                          d||
                          e||
                          3||
                           ||
                           ||
                           |----<------
                           ----->------heron
                                         (s)

    In this data flow diagram, we see that main receives side1,
    side2, and side3 from input on three separate calls to that
    function.  These three are then sent to heron from whence
    area results.  area is then sent into print.  input receives
    nothing.  Neither do welcome_user and goodbye_user.  None of
    print, welcome_user, or goodbye_user return a value.  Finally,
    input has a local named side_length and heron has a local
    named s.

    A more complete diagram would also show how information flows
    to and from even library functions (like sqrt and cin's >>).
    This is often ignored to avoid clutter, however.
