Suppose you accumulate 5 integer test scores in sum. And suppose that sum is 104.
Then to write an expression that is the average, you could write:
sum/5
and the value of that expression is 20 (a bit wrong - we lost the decimal fraction .8)
But if you write:
sum/5.0
Then the value of the expression is 20.8 (correct)
Suppose you don't know how many numbers there are when you write the program. So you can't use 5 or 5.0 because there might be 21 or 3 or 97 numbers. You could use a variable to hold the count of numbers: declare int count and write some instructions that will give it the proper value before you want to calculate the average. We'll see how to do this soon.
You can't write "count.0" to force it to be real (like we wrote 5.0 above). C++ simply does not allow this.
You must use a typecast - to tell C++ that it should temporarily use the variable as if it were some other data type. To do this, put the name of the data type you want in parenthesis before the variable name. It will not change the variable type or value permanently, but it will force C++ to temporarily treat the variable as a different type:
(double) sum/count // or sum /(double)count
(It is true that we could avoid the need to type cast here by declaring count to be double instead of int. But there are other situations where you will either want or need to do this.)
You cannot do just any typecast: (char) sum would not make sense and would not compile.
Common shortcuts for altering the value of a variable:
1. Add a value to a variable:
var += value_to_add; //var = var + value_to_add
x += 4; //add 4 to x
2. Multiply a variable by a value:
var *= val_to_mult_by //var = var * val_to_mult_by
x *= 4; //multiply x by 4
3. Same for / and - and %
Examples:
int n = 5; double x = 3.5, y = 2.0; n += 2; // now n is 7 x *= y; // now x is 7.0 x *= y + 2; // mult x (7.0) by (y+2) so x is 28.0
Note that the last line is equivalent to:
x = x * (y + 2);
4. Incrementing and decrementing by 1 is quite common; so there is a special even shorter notation:
i++; means "increment i by 1" n--; means "decrement n by 1"
So:
i++; i += 1; i = i + 1; // all the same j--; j -= 1; j = j - 1; // all the same
Example: use the new notations to accumulate (i.e. add up a series of values) and also to count the number of values :
int sum = 0; //initializing the sum to 0 is vital int count = 0; //ditto for count int val; //no need to initialize this double average; //or this cout << "\nEnter 1st number: "; cin >> val; sum += val; count++; cout << "\nEnter 2nd number: "; cin >> val; sum += val; count++; cout << "\nEnter 3rd number: "; cin >> val; sum += val; count++; //Now calculate an average... average = (double) sum/count;
Note the reuse of val - there is no need for a new variable for each new value, since we only need the sum.
Also - in some books or code you will see the notation ++i; This is also legal but is slightly different in some contexts. We will not cover this variation or use it in this course.
Example: Suppose we want to print squares of first few integers:
int i = 1; cout << i*i; //note use of expression i++; cout << i*i; //now i = 2; displays 4 i++; cout << i*i; //now i = 3; displays 9 ...
Example: Suppose we want to print squares of first few odd numbers:
int i = 1; cout << i*i; //i is 1; displays 1 i += 2; cout << i*i; //i is 3; displays 9 i += 2; cout << i*i; //i is 5; displays 25 ...
All the examples so far that have displayed numeric output have used the simplest possible method:
cout << num;
This will not always display the number in the way you would like. Often you want to control the field width (the number of display columns that the number takes up) or the number of significant figures, or the number of decimal places. cout has a number of moderately awkward ways to control these things.
First, in order to use them you must #include <iomanip>
Then, in the particular cout operation, you include one or more of several special modifiers to the command.
int num1 = 1234; int num2 = 56789; cout << setw(6) << num1; _ _ 1 2 3 4 cout << setw(6) << num1 << setw(6) << num2; _ _ 1 2 3 4 _ 5 6 7 8 9
If setprecision is used by itself, the value num specifies the total number of digits to display.
If setprecision is used in conjunction with the fixed flag, the value num specifies the number of digits to display after the decimal point
double val = 123.456; cout << setprecision(5) << val; 123.46
There are various flags that can be set to specify the kind of formatting to be performed.
To set a flag:
setiosflags( ios:: flag ) -or- setiosflags( ios::flag1 | ios:: flag2 ) -or- cout << flag ...
There are two ways to format floating point numbers:
fixed -- print with a fixed number of digits after the decimal point
scientific -- print in scientific notation
These will stay set until changed.
double y = 50.0512; cout << setiosflags( ios:: fixed ) << setprecision(2) << y; 50.05 cout << setiosflags( ios:: fixed ) << setprecision(2); cout << y; 50.05 cout << fixed << setprecision(2) << y; 50.05 cout << fixed << setprecision(2); cout << y; 50.05
There are three ways to justify numbers:
left -- left justify the number
right -- right justify the number (default)
internal -- for a signed number, the sign is left justified and the number is right justified
These will stay set until changed.
The output of the following program is shown below, assuming the user enters 3.14159, with notes about each output line.
#include <iostream> #include <iomanip> using namespace std; int main() { double d; double quo = 100.0/3.0; cout << "100.0/3.0 as double is: " << quo; // line A cout << "\nEnter a floating point number: "; cin >> d; cout << "Num in native format: " << d; // line B cout << "\nW= 5 p = 3: |" << setw(5) << setprecision(3) << d << "|"; // line C cout << "\nW= 5 fixed p = 3: |" << setw(5) << fixed << setprecision(3) << d << "|"; // line D return 0; }
Line A: "100.0/3.0 as a double is: 33.3333" Note that with no special formatting commands, 6 figures are displayed, although more could be: 33.3333333... If the division had been 100.0/2.0 the result would have been 50 (not 50.0000).
Line B: "Num in native format: 3.14159" Again, 6 figures display. If you had entered more digits, still only 6 would display. If you had entered fewer, fewer would display.
Line C: "W= 5 p = 3: | 3.14|" Here we first use the I/O format manipulators. Before we send the value (num) to display, we tell cout how to display it.
setw() tells cout how many display positions to use for the value. If the value needs more space, it will just take it. If the number requires less space, it will be padded with blanks. You can control left- or right-justification with left or right. See the below. In this example, notice that there is a space before the 3.
Note that you must use setw() for each numeric value you output, even if the width is the same:
cout << setw(5) << num1 << setw(5) << num2;
setprecision() tells cout how many significant figures to display. Here we see 3.14 which is just 3 significant figures. If we had specified setprecision(4) we would see 3.142. (The value is rounded.)
Line D: "W= 5 fixed p = 3: |3.142|" Here, the fixed tells cout that the precision applies to the number of decimal places, so we see 3 decimal places. Note that all 5 width spaces are used up, so there is no space before the 3.
Unlike setw(), once setprecision() and fixed have been set, they retain their values (or settings) until you change them.
If the field width (setw()) is larger than the number of characters needed, the data will display either all the way to the left or all the way to the right within the field, padded or filled with leading or trailing blanks. Numeric values will display to the right (right-justified) and strings to the left (left-justified). You can alter this behavior using the left and right manipulators:
cout << "xx" << right << setw(20) << "Jim Henry" << "xx"; cout << "\nyy" << setw(10) << left << quo << "yy";
will display:
xx Jim Henryxx yy3.333 yy
So far all programs execute from first to last instruction (in sequence top to bottom). So we have one pattern of execution so far:
1. Sequence
To write complex programs, we need to alter the flow of execution.
We will need only 3 new patterns:
2. decide which block of instructions to execute
3. repeat a set of instructions (also called looping)
4. branch to a separate group of instructions and return (or function calling - which we will study in detail later).
Any program - no matter how complex - can be written with just the first three patterns: sequence, repetition, decision.
Writing programs using these three patterns together is called structured programming.
Branch and return is nice and has real advantages in complex programs, but the first three are sufficient for any program.
Both looping and decision statements depend on a conditional expression, which is a logical expression that is either true or false.
The condition is enclosed in parenthesis (there is one exception - the for construct).
It usually uses a relational operator.
== equality != not equal > greater than < less than >= greater than or equal <= less than or equal !> not greater than !< not less than
(By the way, => =< >! will not compile.)
Numeric conditions are common:
( sum == 0 ) or (i < 10)
Other kinds of conditional expressions are possible. For example, we will study more about functions that "become" true or false later. In C++, integer values by themselves have a true or false meaning. Specifically, 0 is false and anything else is true. So it is legal to write:
( n )
Here, if n is 0 then the condition is false; if n is non-zero, the condition is true
Using one = is an assignment statement
which will compile and execute, but will not mean what you think it means.
In short: to compare for two things being equal, you must use two = signs: (x == 10) If you code: (x = 0) then you are assigning 0 to x and the truth of the condition will depend on the value stored into x. In C and C++ the value 0 is considered to be false and any other number is true. We will revisit this idea later. For now just remember to use
|
The decision structure allows the program to execute one or another set of instructions - to decide which set to execute. Or it can decide simply not to do a set of instructions.
So it determines whether or not sections of code are executed.
Example: imagine you need to calculate an average, but there is a possibility that actually no values have been accumulated. That is, the count of numbers whose average is to be found is 0.
We'd like to be able to code something that expresses:
"if count is 0 then display a message, otherwise calculate and display the average"
We should do this just when we are ready to try to calculate an average. And we can do it in C++ like this:
if (count == 0) //Note: two = signs for comparison { cout << "\nNo data entered"; } else { cout << "\nAverage: " << (double) tempSum/count; }
There are two basic forms of the if statement
if (condition) { block of statements to execute if condition is true; }
if (condition) { block of statements to execute if condition is true; } else { block of statements to execute if condition is false; }
If the block is only 1 statement long, the {} aren't required:
if (cond) stmnt;
if (cond) stmnt; else stmnt;
Note the use of ;
We will study a couple of further variations on if statements later as well as a couple of alternative instructions that implement decisions.
In C++ there are 3 instructions that build loops:
for - executes a block of instructions a certain number of times
while - repeats a block of instructions 0 to many times, as long as a given condition is true
do..while - executes a block of instructions once and then 0 to many more times, as long as a given condition is true. That is, the block is executed at least once.
Definitions:
"a block of instructions" are those that should be executed repeatedly. They are called the body of the loop.
"a given condition" is a logical condition that is true or false (i.e. is i > 10?). This condition is called the exit condition of the loop.
int i; for (i = 0; i < 10; i++) { cout << i; } ... the pgm continues...
This says:
This loop would produce the following output:
0123456789
Note that "running the loop" from 0 to 9 executes the body 10 times.
Recall the code to print the squares of the first few odd numbers? Now we can use a for loop to compress it:
int i; int num = 1; for (i = 1; i <= 5; i++) { cout << " The square of " << num << " is " << num*num << endl; num += 2; }
This would produce:
The square of 1 is 1 The square of 3 is 9 The square of 5 is 25 The square of 7 is 49 The square of 9 is 81
Notes:
If you don't code the {}, only the first statement following the for is considered to be part of the loop body.
and in the code above (without the {}), you would get:
The square of 1 is 1 The square of 1 is 1 The square of 1 is 1 The square of 1 is 1 The square of 1 is 1
because although i is incremented, num += 2; was not executed until after the loop finished.
The three expressions in the for loop's () can be thought of as:
the initialization part: this is done only once, before the body is executed the first time
the exit condition: this is tested before each execution of the loop body. When it is false, the loop body is not executed any more and whatever instruction is after the for construct is then executed.
the "final" part: this is executed after each execution of the loop body. It's as if it were added on to the end of the loop's body.
The initialization and the "final" part can have more than one instruction - they are separated by commas. For example, if you wanted to initialize two variables, i and j to 0 and to increment both after the body of the loop is executed, it would look like this:
for (i = 0, j = 0; i < 10; i++, j++) { loop body }
Finally, because the exit condition is tested before the loop body is executed, the for loop is classified as a top-driven loop. If the exit condition is true the first time it is tested, the loop body will not execute at all.
Often we don't know in advance how many times loop should execute, so we can't use for in its role as a counting loop as shown above.
Example: ask the user to enter some numbers and then find their average.
We could:
We'll use the while loop to code the second way.
Format of while loop:
while (condition) { body of loop }
This is a top-driven loop. The "condition" is tested before the execution of the code in the body of the loop. It is tested before the body is executed the very first time - and if it is false, the body of the loop will not be executed at all. So the loop could execute 0 times.
Here is the basic logic that will be used for the averages program.
get aTemp from the user while (aTemp > -999) //using special value for exit { process aTemp get next aTemp from user } calculate average
//Program to calculate average temperatures from user input. //User enters -999 or less to quit #include <iostream> #include <iomanip> using namespace std; int main() { int aTemp; int tempSum = 0; int tempCount = 0; cout << "\nEnter a temperature (-999 to quit): "; cin >> aTemp; while (aTemp > -999) { tempCount++; tempSum += aTemp; cout << "\nEnter next temperature (-999 to quit): "; cin >> aTemp; } cout << "\nAverage is " << (double)tempSum/tempCount; return 0; }
Notice that there is one flaw with the code. What is it?
Hint: what if user enters -999 as first number?
Some applications will not have any natural "special value" - e.g. a speed can be any + or - value.
So we need another way to tell when to stop the looping - that is, a different exit condition.
One way is to ask user each time, and accept an answer (as a string).
//Program to calculate average speeds from user input //User is asked after each value of there is more data. #include <iostream> #include <iomanip> using namespace std; int main() { int aSpeed; int speedSum = 0; int speedCount = 0; string choice = "y"; while (choice == "y") // see note below { cout << "\nEnter a speed: "; cin >> aSpeed; speedCount++; speedSum += aSpeed; cout << "\nAnother? (y/n) "; cin >> choice; } cout << "\nAverage is " << (double) speedSum / speedCount; return 0; }
Remember, though, In this case, as well as other comparisons for equality (e.g. for testing numbers) you must be careful to code two = rather than one. Using one is an assignment statement which will compile and execute, but will not mean what you think it means. In short, again:
to compare for two things being equal, you must use two = signs:
if (x == 10) if (s == "jim")
This version of a loop instruction ensures the body of the loop always executes at least once.
After each repetition, the exit condition is tested. So this is classified as a bottom-driven loop.
Format:
do // note: NO ; here { .. loop body } while (condition); // note: ; required here!!
You could re-write the average program using a do..while without having to initialize the variable choice.
#include <iostream> #include <iomanip> using namespace std; int main() { int aSpeed; int speedSum = 0; int speedCount = 0; string choice; do { cout << "\nEnter a speed: "; cin >> aSpeed; speedCount++; speedSum += aSpeed; cout << "\nAnother? (y/n) "; cin >> choice; } while (choice == "y"); cout << "\nAverage is " << (double) speedSum / speedCount; return 0; }
Be very careful. You must ensure that
The following will loop forever:
i = 1; while (i < 10) { n = i * 4 - j / 16; cout << n; }
Why?
Likewise:
i = 1; while (i < 10) n = i * 4 - j / 16; cout << n; i++;
Why?
You need to be careful to code loop exit conditions correctly for all three C++ loop constructs.
Symbolic Constants allow us to associate a value with a symbolic and meaningful name. You use the name wherever you want the value.
In this course we will restrict use of symbolic constants to numeric values.
By convention, symbolic constants are always CAPITALIZED as a signal to the (human) reader of the program that the value is a constant.
Use these whenever you have a fixed value used in several places in a program. This value will not change while the program is running, but the value may change at some later time (example: postal rates - cents per ounce). You would then change the value and recompile the program.
Using a symbolic constant allows a change to this value to be made in just one place rather than finding and changing it in many places in the program. Finding and changing in multiple places is error-prone. Then just re-compile the program.
Also, use symbolic constants for "magic" numbers whose values do not explain their meaning:
Which is clearer?
Total = amt + amt * 0.0625; Total = amt + amt * TAX_RATE; //TAX_RATE is a symbolic constant
You create C-style symbolic constants with #define statements at beginning of program (before main). The symbolic names are always capitalized by C and C++ programmers. In this course you should also capitalize them.
Note there are no commas or semi-colons in a #define:
#include <iostream> #include <iomanip> using namespace std; #define TAX_RATE 0.0625 //CAPS by convention #define INDENT_PRCNT 0.0625 //diff meaning; same value int main() { ... //0.0625 replaces TAX_RATE total = amt + amt*TAX_RATE; //0.0625 replaces INDENT_PRCNT x = 2 * INDENT_PRCNT; //then next is illegal: equivalent to 0.0625 = 0.07 and generates an error TAX_RATE = 0.07; ...
So:
Changing TAX_RATE in the #define changes it everywhere it occurs in the program (potentially many times), but does not change INDENT_PRCNT anywhere.
Meaning is clearer.
C++ has a alternate mechanism to create a symbolic constant. It is typically declared as a data item, but in the same place as a #define. The declaration is prefaced with the keyword const. The compiler will flag as an error any attempt by program instructions to alter the value of this data item.
#include <iostream> #include <iomanip> using namespace std; const double TAX_RATE = 6.025; const double PI = 3.14159; int main() { ... total = amt + amt*TAX_RATE; // ok - as above ... TAX_RATE = .07; // illegal - produces compiler error message ...