Name: _____________________ Class: Comp 217
SSN/ID:   _____________________ Section & Group: ____________
Console & Library Functions


Introduction

Today's exercise involves a series of experiments, each investigating a different aspect of a fundamental C++ concept: the expression. The term expression can be defined as follows:

An expression is a sequence of one or more operands, and zero or more operators, that, when combined, produce a value.

To illustrate, the sequence

12

fits the definition of an expression, since it consists of one operand (12) and zero operators that combine to produce a value (12). Perhaps more familiarly, the sequence

2 + 3

fits the definition of an expression, since it consists of two operands (2 and 3) and one operator (+) that combine to produce a value (5). Operands need not be constants: the sequence

2.5 * x - 1.0

fits the definition of an expression, since it consists of three operands (2.5, x, and 1.0) and two operators (*, -) that combine to produce a value (1 less than the product of 2.5 and x).

These last two examples have been arithmetic expressions; that is, expressions whose operators are familiar arithmetic operators. As we shall see in today's exercise, C++ provides a rich set of arithmetic operators, as well as many non-arithmetic operators that allow C++ programmers to construct non-arithmetic expressions.

C++ Program Structure and Basic I/O

There are three basic parts to a C++ program:
  1. Instructions to the C++ preprocessor and compiler;
  2. Instructions that describe the processing to be done.
  3. Documentation comments (program header, function header, and inline)
However, before we can describe these instructions, we must have a way of naming things so that we can tell the compiler about them and describe what we want to have done to them. We name things (data types, data objects, and actions) by giving them an identifier. An identifier is made up of letters, numbers, and underscores, but must begin with a letter or an underscore.

We use the words identifier and name interchangeably.

Beware: C++ is case sensitive. That means that Value, VALUE, value, and vaLue are four separated identifiers.

C++ Program Structure

Let's examine the following C++ program. We have numbered the lines so that we can discuss them.

1	/************************************************************
2	*	FileName: sampleio.cpp
3	*	Author:	  Ada Lovelace
4	*	Purpose:  Demonstrate Basic I/O operation 
5	*		  by inputting a unmber and outputting 
6	*		  the number just entered.
7	**************************************************************/
8
9	#include <iostream>
10	using namespace std;
11
12	int main()
13	{
14	   int number;
15	   cout << "Please enter a number.";
16	   cin >> number;
17	   cout << "You entered: " << number << endl;
18	   return 0;
19	}
20	// end program

So what's going on in this program???

Simple Data Types

A data type is a set of values and a set of operations on these values. In the preceding program, we used the data type int which is an identifier for the integer data type.

We used data type int in four ways in the preceding program. int precedes main, the name of the main function in the program to indicate that the function returns the value of type int. In line 18 an int literal (zero) is returned as the result of the main function main. In line 14, a variable number is declared to have the data type int. In line 16, an integer number was read from the keyboard and stored in the storage of variable number.

The following are some fundamental/simple data types:

Integral Types
short		int		long		char
unsigned short	unsigned	unsigned long	unsigned char

Floating Types
float		double		long double

Variables and Constants

Variables

Variables are named memory locations that have a type, such as an integer or character, and, consequently, a size, which is inherited from their type. Since variables are types, they have a set of operations that can be used to change or manipulate them.

Each variable in your program must be declared and initialized. There are two ways in which we can do this. We can declare our variables first, like this:

                                                                           
  char letter;                                                                  
  int x;                                                                        
  long student_id;                                                              
  float payRate;                                                                
  double pi;                                                                    
  bool valid;                                                                   

then initialize them later in the program as a separate statement.

                                                                           
  letter = 'A';                                                                 
  x = 7;
  student_id = 200201202;
  payRate = 12.85;
  pi = 3.1415926536;                                                            
  valid = true;                                                                 

The other way is to initialize them at the same time as they are declared (in one statement).

                                                                           
  char letter = 'A';                                                            
  int x = 7;                                                                    
  long student_id = 200201202;
  double pi = 3.1415926536;
  float payRate = 12.85;                                                        
  bool valid = true;                                                            

However, a variable can be used only after its value is set.

Constants

We can also declare our initialized variable as a constant, by adding the type qualifier const before the defintion. The general format for a const declaration is shown below:

const type variable-name = any value you like

Inside of a program, you will see constants written like this:

                                                                           
  const float payRate = 12.85;                      
  const double pi = 3.1415926536;                   

C++ Basic I/O Symbols

Here is a table of C++ basic I/O symbols we saw in the preceding program:

OperatorSymbol	Meaning
			
cout A special variable --- used along with the insertion operator << to write out the values of variables and expressions to the standard output device such as screen.
<< Insertion operator --- takes two operands. Its left-hand operand is a stream expression (e.g. just an ostream variable cout). Its right-hand operand is an expression which could be as simple as a literal string. << can be used several times in a single output statement.
cin A special variable --- used along with the extraction operator >> to input values from the standard input device such as keyboard to a variable.
>> Extraction operator --- takes two operands. Its left-hand operand is a stream expression (e.g. just a istream variable cin). Its right-hand operand is a variable into which we store the input data. >> can be used several times in a signle input statement.

Words and Symbols with Special Meanings

Certain words have predefined meanings within the C++ language; these are called reserved words. Examples of reserved words: int, namespace, using, include, cin, cout, and return, etc.. You cannnot use them as your user defined identifier such as variable names.

Semicolons terminate statements in the C++ program. There are six semicolons in the preceding program, so there are six statements in the program.

Converting Numeric Types

If an integral and a floating point variable or constant are mixed in an operation, the integral value is changed temporarily to its equivalent floating point representation before the operation is executed. This automatic conversion of an integral value to a floating point value is called type coercion. Type coercion also occurs when a floating point value is assigned to an integral variable. Coercion from an integer to a floating point is exact. However, when a floating point value is coerced into an integral value, the fractional part is truncated.

Type changes can be made explicit by placing the value to be changed in parentheses and placing the name of the new type before it. This is called type casting or type conversion. For example, intValue = 10.66; and intValue = int(10.66) produce the same result 10. The safe, modern way to typecast is to do static_cast<int>(intValue).

In summary, we have explicit and implicit data type conversion.

Type coercion The implicit (automatic) conversion of a value from one data type to another.
Type casting The explicit conversion of a value from one data type to another; also called type conversion.

Formatting the Output

To format a program's output means to control how it appears visually on the screen or on a printer. We use the special ostream variable cout together with the insertion operator << to accomplish this. Here is what an output statement looks like:

cout << ExpressionOrManipulator << ExpressionOrManipulator << ... ;

The C++ standard library supplies many manipulators, here are five of them:

Manipulator Description
endl Inserts an end-of-line character and forces the next output to begin on the next line by flushing the buffer.
setw(n) Controls how many character positions the next data item should occupy when it is output. setw is only for formatting numbers and strings. Its argument is the fieldwith (number of character positions). The output is right justified.
fixed Forces all subsequent floating-point output to appear in decimal form rather than scientific notation.
showpoint Forces decimal points to be displayed in subsequent floating-point output and even in whole number output.
setprecision(n) Controls the number of positions for fractional digits.

In this table, the manipulators without arguments (such as endl, fixed, showpoint) are available through the header file <iostream>. Those with arguments (such as setw(n) and setprecision(n)) require the header file <iomanip>.

Now look at an example and see how those manipulators are used:

// Program Format demonstrates the use of fieldwidth specifications.

#include <iostream>
#include <iomanip>
using namespace std;

// GLOBAL variables declarations:
const int INT_NUMBER   = 1066;      //define an int constant
const float FLT_NUMBER = 3.14159;   //define a float constant

int main () {
   float fltValue;  // declare a float type variable
   int   intValue;  // declare an int type variable

   // To set all printout in decimal format with decimal points appearing
   cout << fixed << showpoint;

   intValue = INT_NUMBER + FLT_NUMBER;         // Type coercing
   fltValue = float(INT_NUMBER) + FLT_NUMBER;  // Type casting
   cout << INT_NUMBER  << endl;
   cout << intValue  << endl;

   // Reserve 10 character positions for intValue
   cout << setw(10)  << intValue;
   cout << setw(10)  << intValue  << intValue /10  << endl;

   // Reserve 10 character positions for fltValue
   cout << setw(10)  << fltValue  << endl;

   // Set precision to 10 decimal positions
   cout << setprecision(10)  << fltValue  << endl;

   // Reserve 10 character positions for fltValue
   // and reset precision to 3 decimal positions
   cout << setw(10)  << setprecision(3)  << fltValue << endl;
   cout << fltValue << endl;

   // Print intValue takeing as many character positions as needed, and then
   // reserve 3 character positions for intValue
   // and then reserve 7 character positions for intValue
   cout << intValue  << setw(3)  << intValue << setw(7) 
        << intValue  << endl;
    
   return 0;
}

You may run this program and compare the output with what you expected.

Software Engineering

Our problem today is to learn how to design and write a program. Since doing so is creating software, this endeavour is sometimes called software engineering. The particular design technique we will be using is called object-centered design (OCD), a methodology explicitly designed to help novice programmers get started writing software.

The process of developing a program to solve a problem involves several stages:

  1. Design: Carefully plan your program using OCD...
    1. Behaviour: Describe as precisely as possible what the program must do;
    2. Objects: Using the behavioural description, identify the objects needed to solve the problem;
    3. Operations: Using the behavioural description, identify the operations needed to solve the problem;
  2. Algorithm: Organize the objects and operations into an algorithm -- a sequence of steps that solves the problem;
  3. Coding: Translating your algorithm into a programming language like C++;
  4. Testing: Running your program with sample data to check for errors, and debugging those errors until it can be deemed correct; and
  5. Maintanence: Performing any modifications needed to improve the program.
To illustrate these stages, today's exercise will use them to develop a program that, given the lengths of the two legs of a right triangle, will display the length of its hypotenuse.

Design

Yogi Berra once supposedly said,


   If you don't know where you're going,
   you'll end up somewhere else!
This idea is especially important when writing software: you need to "know where you are going" before you sit down to write a C++ program. In order to "know where you are going", you need to spend some time designing your program.

A good design makes a program easy to write.

If you are not a novice programmer, spending the time to design a program may seem like a waste, especially at the beginning when problems are relatively easy. However, the problems will soon become more difficult. If you get in the habit of carefully designing your software now (while doing so is easy), then designing elegant solutions for more difficult problems will also be relatively easy. But if you take a "short cut" now and skip the design stage, you will not master object-centered design, and when the problems get more difficult, you will find that your peers are writing better programs and writing them faster than you.

So be disciplined and get into the habit of carefully designing your software. The remainder of this section will teach you how.

As we saw earlier, object-centered design consists of five sub-stages: describing how the program must behave to solve the problem, identifying its objects, identifying its operations, and organizing those objects and operations into an algorithm.

Behaviour

We might describe how our program needs to behave as follows:


 Our program should first display on the screen a greeting, after which 
 it should display a prompt for the lengths of the legs of a right triangle.
 It should then read these two values from the keyboard.  Once it has the 
 two leg lengths, it should compute the hypotenuse length.  It should then 
 display the hypotenuse length (and appropriate labels) on the screen.

This behavioural description gives us all of the information we need to get started designing our program. In particular, it provides us with the objects and the operations our program requires to solve the problem. We will examine how next.

Objects

If you study our behavioural description and circle all of the nouns (ignoring nouns like "program" and "user"), the result is a list of the objects our program needs to define:

Description Information
Type
Information Kind
(Varying or Constant)
Name
the screen ostream varying cout
a greeting string constant --
a prompt for the legs string constant --
the first leg value double varying leg1
the second leg value double varying leg2
the keyboard istream varying cin
the hypotenuse value double varying hypotenuse
labels for the hypotenuse string constant --

For each noun, we have described some of its attributes:

These attributes are not strictly necessary at this point, but identifying them now saves us from having to do so later on.

Once we know the objects in our problem, it is useful to specify the basic flow of information in our program in terms of them. For example, we can write:

   Specification:
      input(keyboard): leg1 and leg2, two double values.
      output(screen):  hypotenuse, a double value.

Such a specification succinctly states what the program does to solve the problem in terms of its inputs and outputs. (Output items like a greeting, prompts and labels are assumed.) It is good programming style to provide such a specification as part of the program's opening comment, for documentation purposes.

Operations

If you study our behavioural description and underline all of the verbs the result is a list of the operations our program needs to perform:

Description Predefined? Name Library?
display a string (the greeting) yes << iostream
display a string (the prompt) yes << iostream
read a double (the first leg value) yes >> iostream
read a double (the second leg value) yes >> iostream
compute the hypotenuse length ?? ?? ??
display a double (the hypotenuse) yes << iostream
display a string (the label) yes << iostream

In addition to listing the basic operations, we also list whether or not the operation is predefined; if so, how it is specified, and where the operation is defined. As with our objects, these extra steps are not necessary, but doing them now will save us time later on.

This table provides us with the basic operations needed to solve our problem; however, there is no predefined operation to compute the length of the hypotenuse of a right triangle. To do so, we must refine this operation by breaking it down into smaller ones. In particular, the Pythagorean Theorem tells us that we need these operations to compute the hypotenuse length:

Description Predefined? Name Library?
find the square of a double value yes pow() cmath
add two double values yes + built-in
find the square root of a double value yes sqrt() cmath
store a double value in a variable yes = built-in

If this seems like a lot of information to digest, don't get bogged down in the details. You will find that when you use a function and/or library frequently, you will naturally begin to remember its details, so all you need is practice. The important thing for now is to understand what steps we are taking to design our software, and why.

Algorithm

Once we have identified all of the objects and operations needed to solve our problem, we can organize them into a sequence of steps that solves our problem, which is called an algorithm for the problem. An algorithm should specify what a program does in fair detail, but it need not worry about the syntax details of a particular language like C++ (i.e., it's expressed in pseudocode).

For our problem, we can organize the objects and operations as follows:

  1. Display via cout a greeting for the user.
  2. Display via cout prompts for the two leg lengths.
  3. Read from cin two double values, storing them in leg1 and leg2.
  4. Compute the hypotenuse length using the Pythagorean Theorem:
          hypotenuse = sqrt(pow(leg1, 2.0) + pow(leg2, 2.0))
            
  5. Display via cout the value of hypotenuse. along with an appropriate label.
This algorithm provides the blueprint for our C++ program. Once we have it, we are done designing our program, and are ready to begin implementing our design.

Coding

Begin by creating a new directory or folder for this exercise (e.g., lib_fxns) and then save a copy of source_lab03_hypotenuse.cpp in this directory, and rename it to hypotenuse.cpp. hypotenuse.cpp contains just a fragmentary opening comment (documentation that explains what the program does, who wrote it, and so on), so start by using your text editor and customizing this comment with your name, the date, schoolname, course number, the problem specification, etc..

Coding is the task of taking an algorithm and translating it into a high-level language like C++. We can begin this task by adding a minimal C++ program to hypotenuse.cpp after the opening comment:

int main() {
   return 0;
}

Every C++ program must have a main function where execution begins and ends. The lines above make up a minimal main function, and thus provide a framework to which we can add other statements that perform the steps of our algorithm.

When you have added these lines to hypotenuse.cpp, translate your program into machine language, as we did in the last few labs. Please call the compiled, executable program hypot.

No errors or warnings should appear when you compile it. (When you run this program, nothing should happen because it doesn't do anything yet.)

If error messages appear, then what you have entered contains syntax errors (i.e. your program is not a "grammatically correct C++ sentence"). Errors in a program are frequently called bugs. In order for your program to compile, you must return to the editor and correct these errors, which is called debugging your program.

Note: the line

   return 0;
after the { and before the } in the main function causes your main function to terminate and return the integer zero, which signals "normal termination" to many operating systems.

Once we have the minimal C++ program constructed and can translate it, we are ready to encode our algorithm. To do so, we want to take each step of the algorithm and write one or more C++ statements that perform that step. Step-wise translation is the process of translating an algorithm into a program, one step at a time. We therefore begin with the first step.

1. Display via cout a greeting for the user.

This step can be performed using a C++ output statement. In general, to display a sequence of values Value1... ValueN on the screen, we can use the following output statement pattern:

   cout << Value1 <<  Value2 << ... <<  ValueN;

Add an output statement to your source program following the { that displays the following message, using \n to print blank lines before and after the message, so that it is easy to read:
   Given two right triangle leg lengths,
    this program computes the hypotenuse length.
When you have added the commands to your source program, re-compile it. The compiler should generate an error message like the following:

        hypotenuse.cpp: In function int main()
        hypotenuse.cpp: 'cout' undeclared...
The problem is that the meanings of the symbols cout and << are declared in a system file named iostream, not in your program. To access these declarations from that file, we can instruct the compiler to insert the contents of iostream into hypotenuse.cpp, by adding an #include directive just before the int main() line:
   #include<iostream>

   using namespace std;
This #include directive must appear in any program that performs output using cout and <<. The # symbol should be the first column, in order for it be processed correctly. The <> symbols around the file name tell the compiler to look for iostream in a special system "include" directory, rather than in your current directory. The using namespace std; directive tells the compiler that we will be using standard C++ naming conventions, which will be the case throughout this lab manual. Try to remember the error message (or make a note of it) so that if you see that message again, you will know how to "debug" that error.

Now, retranslate your program to check that what you have written is free of syntax errors. If not, you can infer that the error lies in the text you have added since your last correct compilation. Find your error(s) within those lines and use the editor to correct them.

When your source program compiles correctly, run hypot to test that it displays the intended message. If it does not, the statements you have added contain logic errors (i.e., your program is a valid C++ 'sentence', but it 'says' something different than you intended.) Compare your source program statements against the output produced by hypot, and modify them as needed to correct the error.

When your program is error-free, proceed to the next step of our algorithm.

2. Display via cout prompts for the two leg lengths.

Like our first step, this step can also be accomplished using an output statement. Add to hypotenuse.cpp an output statement that displays the following prompt for input:

   Enter the two leg lengths: 
Use \n to leave a blank line between the greeting and this prompt and leave a space after the colon. Check the correctness of what you have written by translating your program and continue to the next step when it is correct.

3. Read from cin two double values, storing them in leg1 and leg2.

This step can be performed using a C++ input statement. In general, to read a sequence of values from the keyboard and store them in Var1...VarN, we can use the following input statement pattern:

   cin >> Var1 >>  Var2 >> ... >>  VarN;

Using this pattern, add an input statement to hypotenuse.cpp to perform step 3 of our algorithm. Then check its correctness by retranslating your program. Similar (but different) errors should be generated, but this time it is our objects that are undefined. C++ requires that an object be declared before it can be used, using a declaration statement whose pattern is:

   Type Var1,
        Var2,

        ...
        VarN;
where Type is the type of the object being declared, and Var1, ..., VarN are the names of those objects, as specified back in our Design stage.

In C++, the type double is used to define objects capable of storing real numeric values. One of the nice features of C++ is that declarations are statements and thus can appear anywhere a C++ statement is permitted. Insert a declaration for leg1 and leg2 just before your input statement. Then, re-translate your program and continue when it is free of syntax errors.

4. Compute the hypotenuse length using the Pythagorean Theorem.

As we have seen, this step can be performed using the sqrt() and pow() functions that perform square root and exponentiation, respectively.

   hypotenuse = sqrt(pow(leg1, 2.0) + pow(leg2, 2.0))
As noted previously, the sqrt() and pow() functions are declared in the library file cmath, so add a #include directive before your main function to insert the contents of cmath into hypotenuse.cpp.

To perform this step, we can use a variant on the declaration statement that allows us to declare and initialize an object. Since hypotenuse is to store a double value, we write:

   double hypotenuse = sqrt(pow(leg1, 2.0) + pow(leg2, 2.0));

Such a statement declares hypotenuse as a double object, and initializes it with the value of the expression to the right of the = symbol. Add this statement after your input statement (since it depends upon the values of leg1 and leg2). Then retranslate your program and continue to the final step when it is free of syntax errors.

5. Display via cout the value of hypotenuse. along with an appropriate label.

This final step of our algorithm is another output statement. Since the pattern for the output statement allows us to output multiple values:

   cout << Value1 <<  Value2 << ... <<  ValueN;

a single output statement is sufficient to accomplish this step. Add an output statement to hypotenuse.cpp, such that if the value of hypotenuse is 1.414214, then the message

   --> The hypotenuse length is: 1.414214
is displayed with blank lines above and below it (to make the result stand out). Retranslate your program, and when it is free of syntax errors, continue to the next stage of program development.

Testing

The third stage of program development is thorough testing. The basic idea is to execute the program using sample data values that "exercise" the program, to see if it contains any logic errors. Execute hypot with the following easy-to-check values, to see if you get the correct results.

leg1 leg2 predicted
hypotenuse
observed
hypotenuse
1.0 1.0 1.414214 ________________
3.0 4.0 5.0 ________________
5.0 12.0 13.0 ________________

If you do not get the predicted results, then the error most likely lies in the formula by which you are calculating the hypotenuse value, so double-check it for accuracy and fix any mistakes it contains. Then retranslate and retest hypot until you have a reasonable degree of confidence that it is correct.

Maintenance

Unlike programs that are written by students, "real world" programs may be used for many years. It is often the case that such programs must be modified several times over the course of their lifetimes, a task which is called program maintenance. Maintenance is thus the final (and usually the longest) stage of program development. Some studies have shown that the cost of maintaining a program can account for as much as 80% of its total cost! One of the goals of object-oriented programming is to try to reduce this maintenance cost, by writing code that is reusable.

To simulate program maintenance, suppose that hypot should display only three decimal digits instead of the default number. To do so, its source program must be altered, so return to your text editor.

The number of decimal digits displayed for a real number is called the precision of that number. To show only three decimal digits, we must alter the default precision. This can be done with an I/O manipulator called setprecision() (declared in the file iomanip) whose general form is:

   setprecision( IntegerExpression )

A manipulator can be inserted into cout just like a value. That is, if setprecision() is placed in an output statement:
   cout << Val1 << setprecision(i) << Val2 <<  ... << ValN;

then real values before it (i.e., Val1 ) will be displayed with the default precision, but real values following it (i.e., Val2 << ... << ValN) will be displayed with precision i. Modify your source program so that hypotenuse is displayed with precision 3. Don't forget to #include the file iomanip before the int main() line! Then test the correctness of your modification, continuing when hypot works as intended.

Phrases you should now understand:

Design, Behaviour, Object, Operation, Algorithm, Coding, Testing, Debugging, Maintenance, Specification, Stepwise Translation, Source Program, Executable Program, Input Statement, Output Statement, I/O Manipulator.


The Experimental Laboratory

Using the UNIX commands you learned last week, begin by making a new directory named labs, if it doesn't already exist. Then, change your working directory to the labs sub-directory.

We will use the file source_lab03_express.cpp as a software laboratory for most of the experiments in this exercise. Click on the preceding link, and then use your browser's

File -> Save As

menu choice to save this file in your labs  subdirectory within your $HOME directory.

Then, rename the file to express.cpp  in your Terminal  console shell.

Using your text editor (emacs), open the file (emacs express.cpp &), and take a moment to study its contents.

The form of the C++ iostream interactive output statement can be given as follows:

cout << Expression1 << Expression2 << ... << ExpressionN;

When execution reaches such a statement, Expression1 is evaluated and displayed, after which Expression2 is evaluated and displayed, after which ..., after which ExpressionN is evaluated and displayed. An output statement thus provides a simple "laboratory" in which we can "experiment" with expressions by building them and viewing the values they produce.


Experiments

Below is a list of the experiments available for this exercise. For each experiment that you are to perform, click its link and print a hard copy of the resulting web page. Then record your experimental results on that hard copy. The objectives of the assignment are to acquaint you with console I/O in C++ and provide an introduction to predefined library functions.

I.      Console I/O

II.      Library Functions: Part 1

III.     Library Functions: Part 2

Deliverables: printout of express.cpp.


I.    Console I/O

Input and Output Expressions

Unlike most languages, C++ performs I/O through the use of expressions. To illustrate, the general form of an output expression is

outputStream << Expression

where outputStream is the name of an ostream (a type defined in the iostream library), << is the output or extraction operator, and Expression is any valid C++ expression.

When execution reaches such an expression, Expression is evaluated and its value is inserted onto outputStream. For example, in the output statement

cout << 2 + 3 ;

cout is the name of an ostream object defined in the iostream library that connects an executing program to an interactive output device (e.g., a computer monitor, a window, etc.). The expression 2 + 3 is evaluated and its value 5 is inserted onto cout, and since cout is a stream, the value "flows" through it to your screen.

Does this indicate that the << operator is higher or lower in precedence than the + operator? Why?





We have also seen that output expressions can be chained together, as follows:

cout << 1 << 3 << 5 << endl;

What is displayed? (Use your source program, if necessary.)





Does this indicate that the << operator is left, or right, associative? Explain why.





In order for the the generalized output expression given above to be correct, the value produced by the << operator must be its left operand (the outputStream). That is, our generalized expression says that the left operand of << must be an outputStream, and since an expression like

cout << 1 << 3 << 5 << endl;

inserts 1, then 3, and then 5 into cout, the first subexpression

cout << 1 << 3 << 5 << endl;

must produce cout as its result, in order for the next subexpression to insert its value into cout

resultA << 3 << 5 << endl;

and that subexpression must in turn produce cout as its value, in order for the next subexpression to insert its value into cout:

resultB << 5 << endl;

and so on down the chain of operators. This is important because cout is not the only ostream into which we can insert values, as we shall see in a future exercise.

The input/extraction operator has the same precedence and associativity as the output/insertion operator, and the value it produces is its left operand (an inputStream), to permit the chaining of input expressions:

cin >> x >> y >> z;

You should now understand that the << and >> operators are truly operators, that produce a value as their result. In the case of <<, the value produced is the ostream that was its left operand, which is usually cout. In the case of >>, the value produced is the istream that was its left operand, which is usually cin. You should also understand that each of these operators is left-associative, and how this associativity is used by chained input or output expressions.

  1. Create a new section in express.cpp and comment that section with the label The I/O Section, as in the following:
    //**************************************************
    // The I/O Section
    //**************************************************
    
    Define three variables: c1  as type char, i1  as type int, and f1  as type float.  Prompt the user with the following lines of code:

    cout << "Enter some data";
    cin >> i1;
    cin >> c1:
    cin >> f1;
       

    Display the results to the screen, one per line.  (Here is one way.)

    cout << "c1 = " << c1 << endl;
    cout << "i1 = " << i1 << endl;
    cout << "f1 = " << f1 << endl;

    Compile the program and run it with the following input: (Please Note: enter means pressing the Enter key on the keyboard)

    3.14   enter

    What are the contents of i1, c1, and f1? 




  2. cout  is a versatile tool for displaying information to the console (screen).  cout  formats its output on the type of variable being printed.  However, typecasting can override the default behaviour.

    Add the following lines of code to The I/O Section:

    cout << "c1 = " << static_cast<int>(c1) << endl;
    cout << "i1 = " << static_cast<char>(i1) << endl;

    Compile the program and run it with the following input:

    66 A 3.14  enter          

    67 B 3  enter          

    96 3.14  enter          
  3. cout can be used to format output in other ways.  Add the following lines to The I/O Section:

    cout << hex << 32 << endl;
    cout << oct << 32 << endl;

    What does this display? What has cout  done?


Hints: 

  1. If you have trouble logging in or compiling your program, consult our First Linux Lab.
  2. Make sure you're saving the files in the correct directory.
  3. Observe how cin  works with whitespace.  Try to store a space or a tab in c1.

 

II.    Library functions: Part 1

Create a new section in express.cpp and comment that section with the label The Trigonometry Section, as in the following:
//**************************************************
// The Trigonometry Section
//**************************************************
Here, you will perform some basic trigonometry on the right triangle.  Recall the following:
  1. Prompt the user for the angle at the hypotenuse-adjacent corner of the triangle (in degrees).
  2. Prompt the user for the length of the adjacent side of the triangle.
  3. Display the length of the opposite side and hypotenuse of the triangle.  Display the results in formatted table form.  Angles should be displayed to two significant figures. Lengths should be displayed to eight digits of precision.  Below is an example (the program's output is displayed in blue and user input is in green).

    Enter the angle at the hypotenuse-adjacent corner of the triangle (in degrees): 45

    Enter the length of the adjacent side of the triangle: 1

    Angle:  45.00 degrees     Adjacent:  1.00000000     Opposite:  1.00000000     Hypotenuse:  1.41421356

    Some other values to aid in your testing:

    Enter the angle at the hypotenuse-adjacent corner of the triangle (in degrees):
    45

    Enter the length of the adjacent side of the triangle: 5

    Angle:  45.00 degrees     Adjacent:  5.00000000     Opposite:  5.00000000     Hypotenuse:  7.07106781


    Enter the angle at the hypotenuse-adjacent corner of the triangle (in degrees): 60

    Enter the length of the adjacent side of the triangle: 1

    Angle:  60.00 degrees     Adjacent:  1.00000000     Opposite:  1.73205081     Hypotenuse:  2.00000000

Hints: 

  1. The C++ trigonometric functions expect the input angle to be specified in radians.  Therefore, you must convert the user's input from degrees to radians before using the trig functions (please remember, 3.14 radians/180o).
  2. Also, you might want to use the Pythagorean Theorem: hypotenuse2 = opposite2 + adjacent2.
  3. Store all of your floating-point numbers in variables of type double. Be sure to include cmath for the trig functions and iomanip for the formatting functions! Please refer to your text for assistance in formatting your output and for assistance with library (or predefined) functions.
    Description Predefined? Name Library
    find the sine yes sin() cmath
    find the cosine yes cos() cmath
    find the tangent yes tan() cmath

III.    Library functions: Part 2

Create a new section in express.cpp and comment that section with the label Quadratic Roots Section, as in the following:
//**************************************************
// Quadratic Roots Section
//**************************************************
Here, you will calculate the real roots of a quadratic equation.  Prompt the user for three float  values: a, b, and c.  Display the two roots to the screen.  

Test your program with the values: a = 1, b = -6, and c = 8.  Does your program provide the correct answers?  Determine some other test values.

Hints: 

  1. Use the formula for the quadratic equation: [-b +- √(b2-4ac)]/2a
  2. Remember to include the cmath library.
  3. You may use the sqrt() or pow(base, exponent) functions once you've included the cmath library.
  4. Do not test quadratic equations with complex roots (where b2 - 4ac  is negative). 
  5. Do not test quadratic equations where a = 0.  We have not covered the C++ structures necessary to deal with these equations in a reasonable manner. 



Hand In: This lab handout with the answers filled in attached to a listing of your final programs
(use the enscript  command from your Programming Style Sheet to print it out:
enscript -E -G -2rj -M Letter -PECT2_PS <filename>  or a2ps <filename>).


Ricky J. Sethi <rickys at sethi.org>
Last modified: Tue Apr 18 16:39:43 PDT 2006