We will now concentrate exclusively on the content of programs.
We return to the elementary program used in the previous chapter, and discuss its features.
// Program written by EF // October 1991 #include <iostream.h> main() { cout << "Hi there!\n"; // The "\n" represents a newline character } // end of the main program
Notes:
The identifier cout is used in combination with the "<<" operator in printing instructions as follows.
// Program written by EF // October 1991 #include <iostream.h> main() { // to print several lines of text cout << "My room is\n1102 Tower\nUninott\n"; // or you could write cout << "My room is\n" << "Room 1102\n" << "Uninott\n"; // and to combine values and text cout << "One seventh is " << 1.0 / 7 << "\n"; } // end main
Text between double quotes is printed exactly as given, arithmetic values are evaluated and printed as numbers.
We will wish to have identifiers to represent
For each identifier that we use, we must tell the computer the type of object which we wish to use it for.
// Program written by EF // October 1991 #include <iostream.h> // A float constant, value fixed const float pi = 3.14159; main() { // A integer variable, initialised // Its value may be reassigned int number = 7; // A float variable, initialised // It can contain non-integral values float reciprocal = 1.0 / number; // An integer variable, not initialised // to any particular value int square;
// Now to print some results cout << "The reciprocal of " << number << " is " << reciprocal << "\n"; cout << "The area of a unit circle is " << pi << "\n"; square = number * number; cout << "Square is " << square << ".\n"; } // end main
The first print ( "cout <<" ) instruction will print the text
The reciprocal of 7 is 0.142857
The second prints
The area of ... is 3.14159
The third will print
Square is 49.
Each print instruction in the above examples ends with a newline character. You will generally want to end with a newline, unless you are printing a prompt requesting the user to enter a reply.
The identifiers you choose to represent constants and variables must satisfy various rules and recommendations.
Examples of identifiers are:
It is common practice to use either
April_total_pay
or
AprilTotalPay
Declarations are program statements which tell the compiler which identifiers we intend to use. If an identifier occurs which we have not declared (either we forgot to declare it, or, more likely, we mistyped an identifier) the compiler will print an error message. Declarations such as those in the above program do two things:
At a later stage, we may need to distinguish between these two effects by separating a declaration into two parts.
You may combine a declaration with the assignment of an initial value. If you do not initialise a variable, you cannot rely on it containing any particular value before you use it.
We will insist (although it is not strict in C++) for the moment that you put const declarations before the main() line, and variable declarations after it, before any executable program code.
The basic variable types in C++ are given below, together with their sizes in bytes on some implementations.
type | PDP | 68000 | VAXVMS |
char | 1 | 1 | 1 |
int | 2 | 4 | 4 |
long int | 4 | 8 | 4 |
short int | 2 | 2 | 2 |
float | 4 | 4 | 4 |
double | 8 | 8 | 8 |
A denotation is a representation of a particular value. Typical denotations for constants of various types are as follows.
25 -15 +99 0177 //leading zero denotes octal 0XFF //leading zero and X denotes hexadecimal
1999L 0L
'a' 'Z' '+' '.' ' ' '\t' // tab '\n' // newline '\a' // alert = bleep '\177' // ASCII octal code '\0' '\\' // backslash '\'' // prime
111.222 1.2345E6
The latter denotation represents the value 1234500.
Comments are from a double slash to end-of-line.
// ... comment ... float velocity; // velocity in kph
There is another type of comment in C++, compatible with that used in C, but I will stick with the above convention.
Lay out your program carefully, with plenty of white space, indented as appropriate. I don't mind which convention you use, but be consistent! As programs become larger, program layout becomes more and more important. Don't forget the general document [ref 1] [content] for details.
We use cout and the operator "<<" for output, and cin and the operator ">>" for input to the program.
// Program written by EF // October 1991 #include <iostream.h> main() { int number; float reciprocal; cout << "Type a number: "; // "cin" expects a value valid // for the given type. cin >> number; // If you use "1" instead of "1.0" // it would be an integer result. reciprocal = 1.0 / number; cout << "Reciprocal of " << number << " is " << reciprocal << "\n"; } // end main
Note that the prompt does not have a newline character, and has a space before the final closing quote.
This second program reads two values.
// Program written by EF // Calculate the area of a rectangle #include <iostream.h> main() { // Declare three float variables float length, breadth, area; cout << "Type length and breadth: "; // Read two values cin >> length >> breadth; // Compute area area = length * breadth; // Print results cout << "Length " << length << ", breadth " << breadth << ", area is " << area << "\n"; } // end main
You could avoid the variable "area" all together, and print the results with
cout << "Area is " << length * breadth << "\n";
but this is not good practice.
It is good practice at this stage of your course to print out all of the values you have read in, so that the output gives a complete picture of what has been calculated.
You may loose a few marks on the dynamic testing if you do not do this. You will certainly loose marks if you do not put explanatory text into your output.
You can now write simple programs to read in some values, evaluate a formula, and print the result.
We will now have a thorough tour of all of the available operators and their significance.
The simple arithmetic operators you would expect to see are
+ - * /
representing addition, subtraction, multiplication and division, respectively. As everywhere in C++, types are important here. Between two "int"s the result is an "int", otherwise (between two "float"s, or between an "int" and a "float") the result is a "float". This is fairly obvious for addition, subtraction and multiplication.
Beware of "/" between integers; the result is an "int", which may not be what you expected. It gives the quotient as an integer rounded down towards zero if the result is positive. If you type
float x = 1 / 7; float y = 6 / 7;
you may not get the expected result; both x and y will be set to zero! If the result would be negative, the language does not define exactly what will happen, for example whether "10 / -7" is -1 (which you would get if you rounded towards zero) or -2 (if you rounded down).
The operator "%" between integers gives the remainder when the first is divided by the second. Thus "72 % 10" evaluates to 2, and "30 % 13" evaluates to 4. If either of the operands are negative there are ambiguities similar to those in division. The value of "10 % -7" might be -3 or +4. See the unit 2 exercises on time conversion [press here] and pay per hour [press here] for examples. The official definition says that the value of the expression
( a / b ) * b + a % b
must always equal the value of "a."
There is no operator in C++ for exponentiation (for raising any number to a given power).
In the example programs given from now on, we may give only the text within the "{" and "}" of the main program. To run the program, you would have to add the lines up to main(){ and the final "}". Further, we may not include the niceties of prompts and input/output if we are really demonstrating other types of statement.
float fahrenheit, celsius; cout << "Type Fahrenheit temperature: "; cin >> fahrenheit; celsius = (fahrenheit - 32) * 5 / 9; cout << "Celsius is " << celsius << "\n";
const int spokes_per_wheel = 44; int spokes, wheels, left_over; cout << "How many spokes? "; cin >> spokes; wheels = spokes / spokes_per_wheel; left_over = spokes % spokes_per_wheel;
integer won, drawn, lost, points; cin >> won >> drawn >> lost; points = won * 3 + drawn;
There are many other operators besides those used for arithmetic evaluations. We will need these in the next chapter for use in "if ... then" constructs.
a > b // greater than a < b // less than a >= b // g.t. or equal to a <= b // l.t. or equal to a == b // equals a != b // not equals // watch for the double "=" sign
These can be between (almost) any types of object. The result delivered is zero for FALSE, one for TRUE. In appropriate places in C++ generally, zero is always interpreted as meaning FALSE, while non-zero is interpreted as TRUE.
Note that testing for equality "==" between floats or doubles is not sensible, because of the possibility of rounding errors. The compiler will permit you to do it, but it is considered bad practice. You should instead look for a small absolute difference between the two values.
fahrenheit > 32
spokes >= 2 * spokes_per_wheel
For combining the results of comparisons, we need general logical operators. In fact, we are not limited to combining the results of comparisons; we can combine any values, and any zero value will be interpreted as FALSE, and non-zero value as TRUE. We use "&&" for the logical "and" and "||" for "or".
int number; // set "number" to some value ... number >= 0 && number < 10 // "&&" is "and", // so true if the number is from 0 to 9 inclusive // false otherwise number < 0 || number >= 10 // "||" is "or" (inclusive or) // one or the other or both // so true if the number is outside the range 0 to 9 ! ( number >= 0 && number < 10) // "!" is logical "negation" // this expression has the same value as the previous one // a monadic operator
5 < celsius && celsius < 15
spokes >= 2 * spokes_per_wheel && spokes % spokes_per_wheel < 10
These are unique to C and C++. Their real significance and use will become apparent later.
++i // increment, deliver new value i++ // increment, deliver old value --i // decrement, deliver new value i-- // decrement, deliver old value
The word "increment" means "increment by a suitable value". Compare
i = 0; cout << i++;
which prints the value 0, with
i = 0; cout << ++i;
which prints the value 1. In both cases, "i" takes the value 1 after the instruction.
Note that
j = p + i++;
is equivalent to
j = p + i; i = i + 1;
where
j = p + ++i;
or
j = p + (++i);
is equivalent to
i = i + 1; j = p + i;
You will often see the free-standing increment
i++; // increment i, could be ++i
to add 1 to i, used instead of writing
i = i + 1;
You will see examples of these operators later.
The values being assigned will be cast or coerced (their types will be changed and their values converted between types) as required. Examples of assignments include the following.
int i, j; char c, lc; i = ( j + 2 ) / 3; // integer divide c = 'X'; j = c - 'A'; // j is ordinal of char c lc = c - 'A' + 'a'; // lc is lower case char // for upper case char c i += 3; // "plus-and-becomes" i -= j; // "minus-and-becomes i *= 10; // "times-and-becomes"
Assignment is an operator, and delivers as its result the value just assigned. Thus
i = ( c = getchar() ) - 'A';
is equivalent to
c = getchar(); i = c - 'A';
To assign the same value to several variables use
i = j = k = 0;
which is interpreted as
i = ( j = ( k = 0 ));
Note that in initialising declarations, you MUST still write in full
int i = 0, j = 0, k = 0;
These operations could all be performed as two separate instructions; express them as two statements if you feel happier that way.
spokes_used = ( wheels = spokes / spokes_per_wheel ) * spokes_per_wheel;
Beware of using "=" instead of "==", such as writing accidentally
if ( i = j ) ....
with a single equals sign. This copies the value in "j" into "i", and delivers this value, which will then be interpreted as TRUE if is is non-zero.
The real significance and use of this operator will appear later. An expression consisting of statements separated by commas, as in
statement1, statement2, statement3
causes each statement to be executed in turn; the result finally delivered is that delivered by the last statement. Thus you can write
i = ( c = getchar(), j = i - 'A' ) + k;
or
if ( c = getchar(), i = c - '0', c != '\n' ) { ...
The effect of this last statement is exactly the same as if you had typed
c = getchar(); i = c - '0'; if ( c != '\n' ) { ...
It is necessary to define carefully the meaning of such expressions as
a + b * c
to define the effect as either
(a + b ) * c
or
a + ( b * c )
All operators have a priority, and high priority operators are evaluated before lower priority ones. Operators of the same priority are evaluated from left to right, so that
a - b - c
is evaluated as
( a - b ) - c
as you would expect.
Exact details are in any book on C++. There are many operators here that we have not yet met, but they are all entered here for completeness.
If you are ever in doubt, use extra parentheses to ensure the correct order of evaluation, and (equally important) to ensure the easy readability of the program.
From high priority to low priority the order is
( ) [ ] -> . ! ~ - * & sizeof cast ++ -- (these are right->left) * / % + - < <= >= > == != & ^ | && || ?: (right->left) = += -= (right->left) , (comma)
Thus
a < 10 && 2 * b < c
is interpreted as
( a < 10 ) && ( ( 2 * b ) < c )
and
a = b = c = spokes / spokes_per_wheel + spares;
is interpreted as
a = ( b = ( c = ( spokes / spokes_per_wheel ) + spares ) );
We strongly suggest that you lay out your program as in the above examples, with the lines between "main" and the final "}" indented about 4 spaces, all other lines starting at the left hand edge, and a comment after the last closing "}". You should also put additional helpful comments at appropriate intervals throughout the program. The following example follows those rules.
// Program written by EF // Calculate the area of a rectangle #include <iostream.h> main() { // Declare three float variables float length, breadth, area; cout << "Type length and breadth: "; // Read two values cin >> length >> breadth; // Compute area area = length * breadth; // Print results cout << "Length " << length << ", breadth " << breadth << ", area is " << area << "\n"; } // end main
The exercises in this unit are marked partly on dynamic correctness and partly on Typographic layout. For dynamic correctness we run the program against samples of test data, and look in the output for the correct results; we also check for words in your output, so that you should print for example
123 degrees Fahrenheit corresponds to 65.34 degrees Celsius
rather than merely print a few numbers. In general you should also at this stage print out the values you have just read in, so that the output is complete in itself.
Your program itself should be easily "readable" to others. The "typographic" marker checks that your program is laid out as suggested above and in lectures; that it is indented correctly, that it contains a reasonable amount of "white space" (blank lines and spaces within lines), that you have a reasonable number of comments in the program, that the identifiers you have chosen are meaningful, and that you have done all the other things mentioned above to make a program readable to others.
The exact typographic marking metrics vary from exercise to exercise, but as a rough guide the typographic mark is formed as follows. The marking looks for correct indentation, approximately 20 to 30 characters per line, 30 to 60% comment in the program with comments after every "}", 20 to 50% blank lines, 20 to 30% white space in a line, and an average identifier length between 5 and 10.
Copyright Eric Foxley Fri Dec 6 08:40:19 GMT 1996
Notes converted from troff to HTML by an Eric Foxley shell script, email errors to me!