++ won't do, because once we hit 25, the hour goes back to 1. So,
we might want a function incHour that increments the hour
correctly, which means that the hour variable with which the function gets
called should be modified.
We might be tempted to write incHour() as follows:
|
|
incHour() a
copy, nothing really gets changed! (See diagram above.)
int hour = 18;
for(int i = 1; i <= 8; i++)
{
cout << "Hour " << i
<< " of my 8 hour day starts at "
<< hour << ":00" << endl;
incHour(&hour); // *** pass by address!! ***
}
Note that the type of &hour is int*. So, now the
input parameter should be of type int*. Using this address (i.e.,
using the input pointer), the function can directly access the variable
hour defined outside the function incHour and
modify its value.
Of course, in order to access the object with a given address, the function must use the dereference operation.
|
|
Be careful when you increment *ph by 1.
| Wrong | Correct |
*ph++
| (*ph)++ or *ph += 1
|
Explanation: Because of the operator precedence, *ph++
means *(ph++).
Hour 1 of my 8 hour day starts at 18:00 Hour 2 of my 8 hour day starts at 19:00 Hour 3 of my 8 hour day starts at 20:00 Hour 4 of my 8 hour day starts at 21:00 Hour 5 of my 8 hour day starts at 22:00 Hour 6 of my 8 hour day starts at 23:00 Hour 7 of my 8 hour day starts at 24:00 Hour 8 of my 8 hour day starts at 1:00
swap!swap.
For example, suppose we read two int's in from the user and we want to print out all the integer values from the smaller of the two up to the larger (comma-separate). If the user is kind enough to enter the numbers so that the frst is the smaller, we would write:
If we had a function swap that took two ints and
swapped their values, we could do the following:
int a, b;
cin >> a >> b;
if (b < a)
swap(&a,&b); // the famous swap: pass by address!
for(int i = a; i < b; i++)
cout << i << ',';
cout << b << endl;
... which is a whole lot more convenient than, for example,
writing separate for-loops for the a<b case and the b<a case.
The function swap will need to change the values of
the variables it's passed, so they must be passed by address.
void swap(int* pa, int* pb)
{
int temp = *pa; // We need a temporary variable. Why?
*pa = *pb;
*pb = temp;
}
For example, you may want to have a function fileMinMax that works as follows:
N = 4 3.1 4.1 5.1 6.1
void fileMinMax(double* pMax, double* pMin);
That is, using the pass-by-address (pMax and pMin above), the function can
return two values.
In the main function, you can call the function like:
double min, max;
fileMinMax(&min, &max);
cout << "min= " << min << " max= " << max << endl;
Please define fileMinMax (see the mandatory practice problem below).
Disallowed: Assignments for streamsConsider the following code:
Q: Compile the code. Does this code compile successfully?
Answer: No, I see a massive amount of error messages.
|
Disallowed: Pass-by-value for streamsFor the same reason (pass-by-value involves copying the argument into the parameter), the following code will not compile, either.
|
ostream and istream) by address.
In other words, when I need to read in a time from the keyboard, we call
readtime() function as follows:
int k = readtime(&cin);
With this in mind, we'd define a function:
int readtime(istream* pin)
{
int h, m, s;
char c;
(*pin) >> h >> c >> m >> c >> s; // dereference: *pin
return h*3600 + m*60 + s;
}
As you see, the function reads the elapsed amount of time in our
hh:mm:ss format.
Note: The address of cin and the address of all the
ifstream objects can be all passed as a pointer to
istream.
As you know, ifstream almost works the same as
istream. In fact, ifstream a is sub-type of
istream, so the conversion (i.e., ifstream* →
istream*) is implicited executed.
Therefore, I can also say:
ifstream fin("data.txt");
int m = readtime(&fin); // typeof(&fin) is ifstream*, then conversion(ifstream* → istream*)
... when I need to read in a time from a file data.txt
using the same function readtime.
It is wonderful to have a function readtime that can take
either cin or fin as an argument, read the elapsed
time in hh:mm:ss format, and return it in seconds.
fileMinMax: Answer.
Note: The get() function reads in a character
without skipping space. That is, when the input buffer has a
newline, that get() will return 10, which is the ASCII code
for the new line. The code uses this feature in order to see when to exit
the while loop.