⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter09.html

📁 think like a computer scientist
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD>  <TITLE>Chapter 9</TITLE>  <LINK REL="STYLESHEET" HREF="downey.css" tppabs="http://rocky.wellesley.edu/downey/ost/thinkCS/c++_html/downey.css"></HEAD><BODY><H2>Chapter 9</H2><H1>More Structures</H1><BR><BR><H3>9.1 Time</H3><P>As a second example of a user-defined structure, we will define a type called <TT>Time</TT>, which is used to record the time of day. The various pieces of information that form a time are the hour, minute and second, so these will be the instance variables of the structure.</P><P>The first step is to decide what type each instance variable should be. It seems clear that <TT>hour</TT> and <TT>minute</TT> should be integers. Just to keep things interesting, let's make <TT>second</TT> a <TT>double</TT>, so we can record fractions of a second.</P><P>Here's what the structure definition looks like:</P><PRE>struct Time {  int hour, minute;  double second;};<</PRE><P>We can create a <TT>Time</TT> object in the usual way:</P><PRE>  Time time = { 11, 59, 3.14159 };<</PRE><P>The state diagram for this object looks like this:</P><P CLASS=1><IMG SRC="images/time.png" tppabs="http://rocky.wellesley.edu/downey/ost/thinkCS/c++_html/images/time.png" ALT="Time Image"></P><P>The word ``instance'' is sometimes used when we talk about objects, because every object is an instance (or example) of some type. The reason that instancevariables are so-named is that every instance of a type has a copy of the instance variables for that type.</P><BR><BR><H3><TT>9.2 printTime</TT></H3><P>When we define a new type it is a good idea to write function that displays the instance variables in a human-readable form. For example:</P><PRE>void printTime (Time& t) {  cout << t.hour << ":" << t.minute << ":" << t.second << endl;}<</PRE><P>The output of this function, if we pass <TT>time</TT> an argument, is <TT>11:59:3.14159</TT>.</P> <BR><BR><H3>9.3 Functions for objects</H3><P>In the next few sections, I will demonstrate several possible interfaces forfunctions that operate on objects. For some operations, you will have a choice of several possible interfaces, so you should consider the pros and cons of each of these:</P><DL>  <DT>pure function:</DT><DD> Takes objects and/or basic types as arguments but  does not modify the objects.  The return value is either a basic type or a   new object created inside the function.</DD>  <DT>modifier:</DT><DD> Takes objects as parameters and modifies some or all   of them. Often returns void.</DD>   <DT>fill-in function:</DT><DD> One of the parameters is an ``empty'' object   that gets filled in by the function. Technically, this is a type of   modifier.</DD></DL><BR><BR><H3>9.4 Pure functions</H3><P>A function is considered a pure function if the result depends only on the arguments, and it has no side effects like modifying an argument or outputting something. The only result of calling a pure function is the return value.</P><P>One example is <TT>after</TT>, which compares two <TT>Time</TT>s and returnsa <TT>bool</TT> that indicates whether the first operand comes after the second:</P><PRE>bool after (Time& time1, Time& time2) {  if (time1.hour > time2.hour) return true;  if (time1.hour < time2.hour) return false;  if (time1.minute > time2.minute) return true;  if (time1.minute < time2.minute) return false;  if (time1.second > time2.second) return true;  return false;}</PRE><P>What is the result of this function if the two times are equal? Does that seem like the appropriate result for this function?  If you were writing the documentation for this function, would you mention that case specifically?</P><P>A second example is <TT>addTime</TT>, which calculates the sum of two times.For example, if it is <TT>9:14:30</TT>, and your breadmaker takes 3 hours and 35 minutes, you could use <TT>addTime</TT> to figure out when the bread will bedone.</P><P>Here is a rough draft of this function that is not quite right:</P><PRE>Time addTime (Time& t1, Time& t2) {  Time sum;  sum.hour = t1.hour + t2.hour;  sum.minute = t1.minute + t2.minute;  sum.second = t1.second + t2.second;  return sum;}</PRE><P>Here is an example of how to use this function. If <TT>currentTime</TT> contains the current time and <TT>breadTime</TT> contains the amount of time ittakes for your breadmaker to make bread, then you could use <TT>addTime</TT> tofigure out when the bread will be done.</P><PRE>  Time currentTime = { 9, 14, 30.0 };  Time breadTime = { 3, 35, 0.0 };  Time doneTime = addTime (currentTime, breadTime);  printTime (doneTime);</PRE><P>The output of this program is <TT>12:49:30</TT>, which is correct. On the other hand, there are cases where the result is not correct. Can you think of one?</P><P>The problem is that this function does not deal with cases where the number of seconds or minutes adds up to more than 60. When that happens we have to ``carry'' the extra seconds into the minutes column, or extra minutes into the hours column.</P><P>Here's a second, corrected version of this function.</P><PRE>Time addTime (Time& t1, Time& t2) {  Time sum;  sum.hour = t1.hour + t2.hour;  sum.minute = t1.minute + t2.minute;  sum.second = t1.second + t2.second;  if (sum.second >= 60.0) {    sum.second -= 60.0;    sum.minute += 1;  }  if (sum.minute >= 60) {    sum.minute -= 60;    sum.hour += 1;  }  return sum;}</PRE><P>Although it's correct, it's starting to get big. Later, I will suggest an alternate approach to this problem that will be much shorter.</P><P>This code demonstrates two operators we have not seen before, <TT>+=</TT> and <TT>-=</TT>. These operators provide a concise way to increment and decrement variables. For example, the statement <TT>sum.second -= 60.0;</TT> isequivalent to <TT>sum.second = sum.second - 60;</TT> <BR><BR><H3>9.5 <TT>const</TT> parameters</TT><P>You might have noticed that the parameters for <TT>after</TT> and <TT>addTime</TT> are being passed by reference. Since these are pure functions,they do not modify the parameters they receive, so I could just as well have passed them by value.</P><P>The advantage of passing by value is that the calling function and the callee are appropriately encapsulated---it is not possible for a change in one to affect the other, except by affecting the return value.</P><P>On the other hand, passing by reference usually is more efficient, because it avoids copying the argument. Furthermore, there is a nice feature in C++, called <TT>const</TT>, that can make reference parameters just as safe as valueparameters.</P><P>If you are writing a function and you do not intend to modify a parameter, you can declare that it is a <B>constant reference parameter</B>. The syntax looks like this:</P><PRE>void printTime (const Time& time) ...Time addTime (const Time& t1, const Time& t2) ...</PRE><P>I've included only the first line of the functions. If you tell the compiler that you don't intend to change a parameter, it can help remind you. If you try to change one, you should get a compiler error, or at least a warning.</P><BR><BR><H3>9.6 Modifiers</H3><P>Of course, sometimes you <I>want</I> to modify one of the arguments. Functions that do are called modifiers.</P><P>As an example of a modifier, consider <TT>increment</TT>, which adds a givennumber of seconds to a <TT>Time</TT> object. Again, a rough draft of this function looks like:</P><PRE>void increment (Time& time, double secs) {  time.second += secs;  if (time.second >= 60.0) {    time.second -= 60.0;    time.minute += 1;  }  if (time.minute >= 60) {    time.minute -= 60;    time.hour += 1;  }}</PRE><P>The first line performs the basic operation; the remainder deals with the special cases we saw before.</P><P>Is this function correct? What happens if the argument <TT>secs</TT> is muchgreater than 60? In that case, it is not enough to subtract 60 once; we have tokeep doing it until <TT>second</TT> is below 60. We can do that by replacing the <TT>if</TT> statements with <TT>while</TT> statements:</P><PRE>void increment (Time& time, double secs) {  time.second += secs;  while (time.second >= 60.0) {    time.second -= 60.0;    time.minute += 1;  }  while (time.minute >= 60) {    time.minute -= 60;    time.hour += 1;  }}</PRE><P>This solution is correct, but not very efficient. Can you think of a solution that does not require iteration?</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -