Chapter 8 - High-Level Language Programming

(8.1) - Where Do We Stand?

It's much easier to write a program in assembly language than in machine language but a programmer must still consider all the intricate details of the machine: what is the instruction set? how many registers? how many bits are in each register? how are conditions treated?, etc., etc.

As the cost of computers came down, more and more of them were sold and the number of computer programmers increased dramatically. Rather than insist that every programmer learn assembly language and machine details, high-level languages were developed to further simplify the programming task.

(8.2) - High-Level Languages

An assembly-language programmer must take a very microscopic view of the task being programmed. For example, the simple pseudocode statement:

Set the value of A to (B + C).

is coded in assembly language as:

LOADB
ADDC
STOREA
..
..
..
A:.DATA0
B:.DATA0
C:.DATA0

Assembly language has the following problems:

  1. The movement of data items must be coded explicitly.
  2. Even a simple operation like addition must be coded as a number of subtasks.
  3. An assembly-language program is specific to one machine.
  4. Statements are not like English.

High-level programming languages overcome these deficiencies:

  1. The programmer need not manage the details of data movement or pay attention to where the items are stored.
  2. The programmer can take a macroscopic view of the problem.
  3. Programs written in a high-level language can be run on many different machines.
  4. Statements are closer to the English language and use standard mathematical notation.
Another piece of system software, called the compiler, is required to translate a high-level language program into machine language. Since the source language is no longer close to machine language a compiler is more complicated than an assembler. Figure 8.1 illustrates the typical translation process for a program written in a high-level language:

  1. The source program written in a high-level language is run through a language translator called the compiler to produce an intermediate program in a low-level code.
  2. The intermediate program is run through a second translator (the assembler) to produce an object program in machine language.
  3. The linker combines the object program with code modules from the system library to produce an executable module.
  4. The loader loads the executable module into memory.
  5. The machine hardware runs the code to produce the results.

(8.3) - Introduction to C++

In this chapter we use C++ to illustrate the concepts of a high-level language - the next chapter describes other high-level languages.

As an example, Fig. 8.2 shows a very simple C++ program.


//program numerology
//this program gets the user's favorite number
//and prints a greeting.

#include < iostream >
using namespace std;

void main() 
{
    int your_number; //stores the number entered by the user

    cout << "Please enter your favorite number: ";
    cin  >> your_number;
    cout << endl;
    cout << "Your favorite number is " << your_number << "."
                   << endl;
    cout << "That is a nice number." << endl;
}

In order to describe what the lines in this program do we add comments with line numbers on the right-side of this program:
//program numerology                                           //Line  1
//this program gets the user's favorite number                 //Line  2
//and prints a greeting.                                       //Line  3

#include < iostream >                                          //Line  4
using namespace std;                                           //Line  5

void main()                                                    //Line  6 
{                                                              //Line  7
    int your_number; //stores the number entered by the user   //Line  8

    cout << "Please enter your favorite number: ";             //Line  9
    cin  >> your_number;                                       //Line 10
    cout << endl;                                              //Line 11
    cout << "Your favorite number is " << your_number << "."   //Line 12
                   << endl;
    cout << "That is a nice number." << endl;                  //Line 13
}                                                              //Line 14

Fig. 8.3 shows the overall form of a typical C++ program:
prologue comment   [optional]
include directives [optional]
using directive    [optional]
functions          [optional]
main function
{
      declarations [optional]
      main function body
}

(8.4) - Virtual Data Storage

A declaration in C++ specifies the name and type of a data item but not the memory location of the item. The C++ compiler will figure out the best locations of the declared data items - it might, for example, decide to store some items in machine registers instead of RAM locations because the program uses them frequently.

The name of a data item is an identifier - a sequence of one or more letters, digits, and/or underscore symbols, _, that doesn't start with a digit. An identifier cannot be any of the keywords in C++ such as if, int etc. C++ is case-sensitive so, for example, FinalTotal and Finaltotal are names of two different data items. Most data items in a C++ program are variables with values that change as the program is executed or values that are not known ahead of time.

Each declaration defines the type of the variable being declared. Three of the C++ Standard Data Types are:

One can declare a number of variables of the same type in one declaration. For example:
    double Radius, Circumference ;
declares that Radius and Circumference are two real numbers.

To declare a constant we add the keyword const at the start of the declaration. For example:

     const double PI = 3.1416;
declares that PI is a real constant with 3.1416 for its value.

One declaration can declare an array of variables. For example:

    int Hits[12];
declares that Hits is an array of 12 integers as shown in Fig. 8.6. Note that C++ indexes the elements of an array starting at 0 instead of 1 - the first integer of this array is stored in Hits[0] and the last integer is stored in Hits[11].

moveto(50, 60); lineto(150, 60) ; moveto(50, 70); lineto(150, 70) ; Every variable and constant must be declared before it can be used.

(8.5) - Statement Types

C++ statements correspond to the pseudocode operations described in Chapter 2:

Pseudocode OperationC++ Statement
InputInput
OutputOutput
ComputationAssignment
Conditionalif-else
Iterativewhile

This makes it easier for a programmer to take an algorithm written in pseudocode and translate it into a C++ program.

(8.5.1) - Input/Output Statements

An input operation in pseudocode gets data from the outside world - the data may come from a user sitting at the computer console, from a file stored on a disk, from another computer, etc., etc. A C++ program can read data from any of these sources but here we only describe how it can read data from a user sitting at the computer console.

Whenever a program expects to get some data from the user it should display a message on the screen, a prompt, to tell the user to enter the data. A pseudocode input operation like:

Get value for speed

should really be preceded by a pseudocode output operation like:

Prompt user to enter speed

Lines 9 and 10 in the numerology program is an example of a prompt followed by an input statement.

Line 12 in the numerology program is an output statement sending four items to the console screen:

  1. the literal string of characters,
    Your favorite number is 
    (including the space at the end;)
  2. the value of your_number;
  3. a period; and
  4. the end-of-line character, endl.

Outputting Real Numbers: The C++ statement:

    cout.setf(ios::fixed) ;  
prints all subsequent output of real numbers in fixed-point format while:
    cout.setf(ios::scientific) ;  
prints all subsequent output of real numbers in scientific notation.

For example, 1234.56789 in fixed-point format is printed as 1.23456789e+3 in scientific notation.

The C++ statement:

    cout.precision(2) 
sets the number of fractional digits in all subsequent output to 2. For example, the number 1234.56789 will be printed as 1234.57 in fixed-point format or as 1.23e+3 in scientific notation.

(8.5.2) - The Assignment Statement

The C++ assignment statement corresponds to the computation operation in pseudocode -

Set the value of "variable" to "arithmetic expression"

in pseudocode corresponds to:

                  variable = expression;
in C++. The expression on the right gets evaluated and the result is then written into the memory location named on the left - the new result overwrites the previous value in that location. For example, read the comments in the following C++ code:
   int A, B, C;
   
   B = 2;     //sets the value of B to 2
   C = 5;     //sets the value of C to 5
   A = B + C; //sets the value of A to 7
   A = A + 1; //changes the value of A to 8
   B = A + B; //changes the value of B to 10
The symbols for addition, subtraction, multiplication, and division are: +, -, *, and /, respectively. These operations are illustrated by the comments in the following C++ code:
   int A, B, C, D;
   
   A = 20 + 5;   //sets the value of A to 25
   B = 20 - 5;   //sets the value of B to 15
   C = 20 * 5;   //sets the value of C to 100
   D = 20 / 5;   //sets the value of D to 4
Dividing an integer by an integer is like long-division in grade school - the quotient is always an integer and you might get a non-zero remainder. C++ uses the % symbol to obtain the remainder:
   int A, B, C, D;
   
   A = 17;
   B = 6;
   C = A / B ; //sets the value of C to the quotient, 2
   D = A % B ; //sets the value of D to the remainder, 5
When the operands are real numbers, the results are real numbers:
   double A, B, C, D, E, F; 
   
   A = 6.75 ;
   B = 4.5 ;
   C = A + B;  //sets the value of C to 11.25
   D = A - B;  //sets the value of D to 2.25
   E = A * B;  //sets the value of E to 30.375
   F = A / B;  //sets the value of F to 1.5
If an arithmetic operation combines an integer with a real number then the integer is converted to a real number before the operation is performed.

If the variable on the left side of an assignment statement is real and the value of an expression is an integer then the expression value is converted to a real value as it is stored in the variable.

If the variable on the left side of an assignment statement is an integer and the value of an expression is real then the expression value is truncated (by removing the digits of the fraction part) to an integer when it is stored. For example,

double A, B ;
int C ;
A = 4.125 ;
B = 1.5 ;
C = A / B ; // C is set to 2 since that is the integer part of 2.75 

The assignment statement can also set the value of a character variable to a particular character:

   char  A, B, C, D ;
   
   A = 'm' ; //Sets the value of A to the lower-case m
   B = '4' ; //Sets the value of B to the digit 4
   C = ' ' ; //Sets the value of C to the space character
   D = '&' ; //Sets the value of D to the ampersand character
It's good practice to assign initial values to variables when they are declared:
  int count = 0 ;
declares count to be an integer variable and sets its initial value to 0.

(8.5.3) - Control Statements

A C++ if-else statement corresponds to a conditional operation in pseudocode and a C++ while statement corresponds to an iterative operation in pseudocode. Both statements evaluate a Boolean condition and modify the flow of control in a program based on the truth or falsehood of that condition.

Boolean Conditions: A Boolean condition can compare two arithmetic values with any of the six comparison operators shown in the following table:

SymbolCondition Tested
==the two values are equal
!=the two values are not equal
<the first value is less than the second value
<=the first value is less than or equal to the second value
>the first value is greater than the second value
>=the first value is greater than or equal to the second value

The following table shows some examples of Boolean conditions:

Boolean ConditionThe condition is true if and only if:
count == 0the value of count equals 0.
divisor != 0the value of divisor is non-zero.
count < limitthe value of count is less than the value of limit.
sum >= 100the value of sum is greater than or equal to 100.

C++ has three Boolean operators, AND, OR, and NOT, to build complex Boolean conditions from simple coonditions. The symbols of the Boolean operators and examples are shown in the following table:

SymbolBoolean
Operator
ExampleCondition Tested
&&AND(x>0)&&(x<10) is x greater than 0 and less than 10
||OR(k == 0)||(k == 1) does k equal 0 or 1
!NOT!(x > y) is x less than or equal to y

Conditional Statements: The flow chart for a conditional operation in pseudocode is:

The if-else statement in C++ corresponds to the conditional operation in pseudocode:
   if(Boolean condition)
        Statement1; 
   else
        Statement2;

First the Boolean condition is evaluated. If the condition is true then Statement1 is performed - else (i.e., if the condition is false) then Statement2 is performed. Consider the following example where A, B, and C are integer variables:

   if( 2*B < (A + C))
       A = B ;
   else
       C = B ;
Suppose that A = 2, B = 4, and C = 7 when the condition is evaluated, then 2*B = 8 is less than (A + C) = 9 so the first statement, A = B, is performed to set A to 4.

But now suppose that A = 2, B = 5, and C = 7 when the condition is evaluated, then 2*B = 10 is not less than (A + C) = 9 so the second statement, C = B, is performed to set C to 5.

An if statement in C++ is an if-else statement without the else clause - no statement is performed if the Boolean condition is false. For example:

  if ( A > LargestSoFar )
      LargestSoFar = A ;
sets LargestSoFar to the value of A if A is larger than LargestSoFar, else it does nothing.

A compound statement is a sequence of C++ statements put between curly braces, { and }. For example, the following C++ code sets Max to the larger of A and B and Min to the smaller of A and B:

  if( A > B )
    { 
      Max = A ;
      Min = B ;
    }  
  else
    { 
      Max = B ;
      Min = A ;
    }
Note that if A and B have the same value then the code sets Max and Min to their common value.

Looping (Iterative) Statements: The left side of the following diagram shows the flowchart of a While Loop in pseudocode and the right side shows the corresponding while statement in C++:

    while(Boolean Condition)
    {
        ...
        ...
        Body of the While Loop    
        ...
        ...
    }

As an example, a while loop is used in the following C++ code that adds a series of non-negative numbers together.

Sum = 0; //Initialize Sum
cout << "Please enter numbers to add; ";
cout << "terminate with a negative number." << endl ;
cin  >> Number ; //Get the first number
while(Number => 0) 
{
    Sum = Sum + Number;
    cin >> Number; //Get another number
}
cout << "The total is " << Sum << endl ;

8.6 - Putting the Pieces Together

Figure 8.16 is pseudocode for a program to process circles.


Get user's choice about continuing
While the user wants to continue
    Get the value of the radius
    Get value for the user's choice of task
    If task choice is circumference then compute and print circumference
        otherwise compute and print area
    Get user's choice about continuing

Figure 8.14 shows the corresponding C++ program.
//program circle - Allows the user to compute the 
//circumference or area of circles from their radii.
#include < iostream>
using namespace std;
void main() 
{   const double PI = 3.1416;
    double Radius, Circumference, Area ;
    char Task_to_do, More;
    cout.setf(ios::fixed);
    cout.precision(2);
    cout << "Do you want to process a circle? (Y or N): "
    cin  >> More;
    cout << endl;
    while((More == 'Y') || (More == 'y')) //if the shift key is forgotten 
    {   cout << "Enter the radius of the circle: "
        cin  >> Radius;
        cout << endl ;
        cout << "Enter your choice of task. << endl ;
        cout << "C to compute circumference, "
             << "A to compute area: ";
        cin  >> Task_to_do ;
        cout << endl ;
        if((Task_to_do=='C')||(Task_to_do=='c')) //if the shift key is forgotten 
        {   Circumference = 2 * PI * Radius ;
            cout << "A circle of radius << Radius 
                 << " has a circumference of " << Circumference << endl ; 
        }
        else 
        {   Area = PI * Radius * Radius ;
            cout << "A circle of radius << Radius  
                 << " has an area of " << Area << endl ;
        }
        cout << endl ;
        cout << "Do you want to process more circles? (Y or N): " 
        cin  >> More;
        cout << endl ;
    }
    cout << "Program will now terminate." << endl ;
}

8.7 - Managing Complexity

The circle program above is fairly easy to write and understand because it has less than 40 lines. How do we manage the complexity of writing and understanding a 50,000-line program?

(8.7.1) - Divide-and-Conquer

Divide-and conquer is a common technique for handling complex tasks: if a task is very hard to solve then divide it into a number of simpler tasks - for example, Figure 8.17 shows a task, T, divided into four simpler tasks: A, B, C, and D.

Divide-and-conquer can be applied recursively - for example, Figure 8.18 shows task A being further divided into three simpler tasks: A1, A2, and A3.

Divide-and-conquer is used to manage the complexity of large programs - the code is divided into a number of modules (sub-programs) with each module performing part of the overall task.

Structure charts like Figures 8.17 & 8.18 are used to show how the overall program is divided into smaller and smaller sub-programs until each sub-program is so simple that it is easy to write its code.

(8.7.2) - Using Functions

In C++ each module is called a function. The main function at the top-level of the structure chart calls (invokes) its sub-programs in the proper order so as to perform the overall task.

As an example, we divide the circle program of Fig. 8.14 into three modules (Get input, Compute area, and Compute circumference) as shown in the structure chart of Fig. 8.19.

The pseudocode for the main function of the circle program is shown in Fig. 8.20.

To write the C++ code for the main function we need to give each sub-function an identifier and decide what information is passed between the main function and the sub-function. For the circle program we decide that:

To call (invoke, run) each of these functions the main function uses a call statement:

        Get_Input(Radius, Task_to_do) ;
        Do_Circumference(Radius) ;
        Do_Area(Radius) ;

Each call statement contains the identifier for the called function followed by the argument list enclosed in parentheses - the argument list shows all variables pertaining to the called function. Each call statement is a sequential statement - control is passed to the code in the called function and when that code is completed, then control is passed back to the statement following the call statement in the main function.

Figure 8.21 shows the main function of the circle program using these call statements.


void main() 
{
    double Radius ;
    char   Task_to_do, More ;
    cout.setf(ios::fixed) ;
    cout.precision(2) ;
    cout << "Do you want to process a circle? (Y or N): " ;
    cin  >> More ;
    cout << endl ;
    while((More == 'Y') || (More == 'y')) 
    {
        Get_Input(Radius, Task_to_do) ;
        if((Task_to_do == 'C') || (Task_to_do == 'c'))
        {
            Do_Circumference(Radius) ;
        }
        else
        {
            Do_Area(Radius) ;
        }
        cout << endl ;
        cout << "Do you want to process more circles? "
             << "(Y or N): "
        cin  >> More ;
        cout << endl ;
    }
    cout << "Program will now terminate." << endl ;
}

(8.7.3) - Writing Functions

Here we consider how to write functions. The general outline for any function is:

        function header 
        {
            local declarations //optional
            function body
        }

where the function header has three parts:

  1. A return indicator to indicate whether the function returns the value of a variable or not. The return indicator is void if the function doesn't return any value.

  2. The function identifier which can be any legal C++ identifier.

  3. A parameter list enclosed in parentheses corresponding to the argument lists of any statements calling the function. For each argument in an argument list the parameter list contains the type of the information being passed (int, double, char, etc.) followed by an identifier. If the parameter is passing information from the called function to the caller then the identifier must be preceded by an ampersand (&) - no ampersand is required if the parameter is only passing information from the caller to the called function.
Figure 8.23 shows the C++ code for the Get_Input function:
void Get_Input(double &Radius, char &Task_to_do )
//The ampersands are required because Radius and Task_to_do 
//are passed from Get_Input to the caller. 
{
    cout << "Enter the value of the radius of the circle: " ;
    cin  >> Radius ;
    cout << endl ;
    
    cout << "Enter your choice of task to do." << endl ;
    cout << "C to compute circumference, " 
         << "A to compute Area: " ;
    cin  >> Task_to_do ;
    cout << endl ; 
}

Figure 8.24 shows the C++ code for the Do_Circumference function:
void Do_Circumference(double Radius)
//No ampersand is required because Radius is only passed from the 
//caller to Do_Circumference.  
{
    double Circumference ;
    Circumference = 2 * PI * Radius ;
    cout << "If the radius of a circle is " << Radius  
         << " then the circumference is " << Circumference << endl ;
}

The C++ code for the Do_Area function is shown below.
void Do_Area(double Radius)
//No ampersand is required because Radius is only passed from the 
//caller to Do_Area.  
{
    double Area ;
    Area = PI * Radius * Radius ;
    cout << "If the radius of a circle is " << Radius  
         << " then the area is " << Area << endl ;
}

Figure 8.25 shows the C++ code for the modularized Circle Program.

Nonvoid Functions: The Do_Circumference function described earlier computes the circumference of a circle and then outputs it to cout. The Circumference function shown below just computes the circumference:


double Circumference(double Radius)
{
    return 2 * PI * Radius ;
}

The return indicator in the function header is changed from void to double to indicate the type of the value returned and a return statement is added to show how the return is computed.

A nonvoid function is invoked whenever its return value is used. For example, the following statement in the main function invokes the Circumference function:

    cout << "If the radius of a circle is " << Radius  
         << " then the circumference is " 
         << Circumference(Radius) << endl ;

8.8 - Object-Oriented Programming

The traditional approach to programming is divide-and-conquer - break the overall task up into simpler sub-tasks that are easily programmed. A different approach is Object-Oriented Programming (OOP) - consider the program as manipulating objects in some domain of interest. As examples:

Each object belongs to a class of similar objects. For example, a savings account in a bank is an object in the savings account class and like other savings accounts it has certain properties such as: name, SSN, account type and account balance. Each savings account has a specific value for each of these properties.

The idea of a class of objects is similar to the idea of a data type in C++. In the circle program Radius, Circumference, and Area are objects in the double class with one property, numeric quantity - each object in this class has its own specific value for that property.

But in OOP each class of objects may also have some subtasks associated with it - each object in the class can perform those subtasks. For example, a subtask in the savings account class may compute the compound interest - each savings account in the class can compute the interest due on its balance whenever it receives a request to perform that service.

Three terms associated with OOP are:

Figure 8.28 shows these three key elements of OOP in a PIE chart.

(8.8.1) - A C++ Example

Figure 8.29 shows a C++ program with four classes: Circle, Rectangle, Square, and Square2. After

#include < iostream>
using namespace std ;
the program defines the interfaces of the four classes: The main function declares objects in each of these classes and asks them to perform their subtasks:
void main() 
{
    Circle Joe ;
    Joe.Set_Radius(23.5) ;
    Joe.Do_Area() ;

    Rectangle Luis ;
    Luis.Set_Width(12.4) ;
    Luis.Set_Height(18.1) ;
    Luis.Do_Area() ;

    Square Anastasia ;
    Anastasia.Set_Side(3) ;
    Anastasia.Do_Area() ;

    Square2 Tyler ;
    Tyler.Set_Side(4.2) ;
    Tyler.Do_Area() ;
}

The program then implements the code of each subtask. As examples
void Circle::Set_Radius(double value)
{
    Radius = value ;
}

void Circle::Do_Area()
{
    double Area ;
    Area = PI * Radius * Radius ;
    cout << "A circle with radius " << Radius << " has an area of "
         << Area << endl ;
}

void Rectangle::Set_Width(double value)
{
    Width = value ;
}

void Square2::Set_Side(double value) ;
{
    Width = value ;
    Height = value ;
}

Inheritance can be carried out through multiple generations - Figure 8.31 shows an inheritance chart with a Shape class having three subclasses (Circle, Rectangle, and Triangle) and the Square2 class as a subclass of Rectangle.

(8.8.2) - What Have We Gained?

OOP is a popular way of programming because it has these advantages:

8.9 - Graphical Programming

User input and output in early computers was text-oriented - users would enter data on a keyboard and see the output as text on a screen. Now we have graphical user interfaces (GUIs) that display output as imagery on a screen and allow the user to use a mouse to enter input.

For example, to copy, edit, delete, move, and print files, users don't have to learn dozens of text-oriented commands - a GUI can present users with a simple, easy to understand image like the one on page 398 of the text.

(8.9.1) - Graphics Primitives

A modern terminal screen uses a bitmapped display - thousands or millions of pixels (picture elements) arranged in a two-dimensional array as shown in Figure 8.32.

A high-resolution (1560 x 1280) display has 1280 horizontal lines (maxY = 1279) and 1560 pixels in each line (maxX = 1559) for a total of 1,996,800 pixels.

The image on the display is stored internally in a frame buffer. The color of each pixel is some mixture of the three primary colors, red, blue, and green so each pixel requires three bytes of storage. The frame buffer for a high-resolution display needs 5,990,400 bytes. Figure 8.33 shows that if the three bytes in column 24 of row 47 of the frame buffer all have zero values, then the color of pixel (24, 47) on the screen is black.

The typical graphics library contains hundreds of functions that can be used to draw an image on the screen. The text describes a simple black-and-white graphics library with the following ten functions:

  1. clearscreen(I): Clears the graphics window to an all-white background if integer I = 0 or to an all-black background if I = 1.

  2. moveto(x, y): Moves the pen to pixel (x, y) on the screen without drawing anything.

  3. getmaxx(): Returns the integer value of maxX to show the width of the graphics window.

  4. getmaxy(): Returns the integer value of maxY to show the height of the graphics window.

    For example the following code moves the pen to the middle of the graphics window:

        X = getmaxx() ;
        Y = getmaxy() ;
        moveto(X/2, Y/2) ;
    

  5. setcolor(I): Sets the color of the pen to white if I = 0 or to black if I = 1. Setting the pen color to the color of the background will erase part of an image.

  6. lineto(x, y): Draws a straight line from the current pen position to pixel (x, y). For example, the code:
        clearscreen(0) ;
        setcolor(1) ;
        moveto(20, 20) ;
        lineto(100, 100) ;
    
    draws a black line from pixel (20, 20) to pixel (100, 100).

  7. rectangle(x1, y1, x2, y2): Draws a rectangle with pixels (x1, y1) and (x2, y2) in the upper-left and lower-right corners. For example, the code:
        rectangle(25, 60, 75, 100) ;
    
    or the code:
        rectangle(75, 100, 25, 60) ;
    
    draws a rectangle with corners at pixels (25, 60), (75, 60), (75, 100), and (25, 100).

  8. circle(x, y, r): Draws a circle of radius r centered at pixel (x, y). For example, the code:
        circle(100, 150, 125) ;
    
    draws a circle where every part that is beyond the window boundaries being clipped.

  9. writedraw(value, x, y): Displays the value of an integer or a text-string starting at pixel (x, y) in the lower-left corner. For example, the code:
        circle(200, 200, 40) ;
        writedraw("Stop", 186, 200) ;
    
    draws a circle with the message "Stop" in the middle.

  10. getmouse(x, y): Inputs the pixel coordinates (x, y) of the last mouse click. For example, if earlier code:
        rectangle(100, 100, 150, 200) ;
        writedraw("Stop", 111, 150) ;
    
    drew a rectangle labelled "Stop";

    then this code will test to see if the user clicked the mouse inside the rectangle:

        getmouse(X, Y) ;
        if( (X >= 100) && (X <= 150) && (Y >= 100) && (Y <= 200) )
        { 
            //the user clicked inside the rectangle
            //and wants to Stop
        }
        else 
        {
           // the user clicked somewhere else
        }
    
Question: How can you test if the user clicked the mouse inside a circle or not?

Hint: Use the Pythagorean Theorem for right triangles - the square of the hypotenuse equals the sum of the squares of the other two sides.

(8.9.2) - An Example of Graphics Programming

Here we show the code for drawing a titled window.

This code draws a narrow Title rectangle with a large rectangle below it:

    clearscreen(0) ;
    setcolor(1) ;
    rectangle(50, 50, 350, 80) ;
    rectangle(50, 80, 350, 330) ;

Then this code draws four lines to divide the top rectangle into thirds horizontally and vertically:

    moveto(50, 60);  lineto(150, 60) ;
    moveto(50, 70);  lineto(150, 70) ;
    moveto(250, 60); lineto(350, 60) ;
    moveto(250, 70); lineto(350, 70) ;

and then a writedraw command is added to insert the title:

    clearscreen(0) ;
    setcolor(1) ;
    rectangle(50, 50, 350, 80) ;
    rectangle(50, 80, 350, 300 ) ;
    moveto(50, 60) ;  lineto(150, 60) ;
    moveto(50, 70) ;  lineto(150, 70) ;
    moveto(250, 60) ; lineto(350, 60) ;
    moveto(250, 70) ; lineto(350, 70) ;
    writedraw("Title", 180, 70 ) ;

Kenneth E. Batcher - 10/23/2006