a standard graphics library. Although it is perfectly possible to learn about data structures and algorithms without using graphics, having a graphics library makes the process a lot more fun. And because you’re likely to learn things more easily if you can have a little fun along the way, the Stanford libraries include an interface called graphics.h that supports simple two-dimensional graphics on the platforms you’re most likely to be using.
Before looking at the contents of the graphics.h interface, it makes sense to consider a simple example that illustrates the capabilities of the graphics library. Just as the first program in Chapter 1 was the classic “hello, world” program, it is appropriate to begin this section with the GraphicHelloWorld program shown in Figure 2-15, which draws “hello, world” in big letters across the graphics window. And just to give the output some color, the program draws the string in white letters on top of a large blue rectangle. The output of the program, which includes several annotations to illustrate the coordinate system used in the graphics library, appears at the top of the next page in Figure 2-16.
The first line in the main program for GraphicHelloWorld is a call to the function initGraphics, which has the effect of initializing the graphics window and displaying it on the screen. Inside the graphics window, coordinates are measured in units called pixels, which are the individual dots that cover the surface
of the display screen. By default, the initGraphics function creates a relatively small window. You can, however, specify an explicit window size by calling
initGraphics(width, height);
where width and height are the desired number of pixels in each dimension.
Coordinates in the graphics window are represented using a pair of values (x, y) where the x and y values represent the distance in that dimension from the origin, which is the point (0, 0) in the upper left corner of the window. As in traditional Cartesian coordinates, the value for x increases as you move rightward across the window. Having the location of the origin in the upper left corner, however, means that the y value increases as you move downward, which is precisely opposite to the usual Cartesian plane. Computer-based graphics packages invert the y coordinate because text moves downward on the page. By having y values increase as you move downward, successive lines of text appear at increasing values of y.
The rest of the code for GraphicHelloWorld consists of calls to functions in the graphics.h interface, which is summarized in Table 2-2. The descriptions of those functions are somewhat cursory, and may not be sufficient in themselves for you to understand the intricacies of the graphics library. Given that the graphics library is only an optional component of this textbook, however, it isn’t appropriate to go through every one of those functions in complete detail.
F I G U R E 2 - 1 6 Annotated output of GraphicHelloWorld GraphicHelloWorld 300 pixels 150 pixels (0, 0) (50, 50)
hello, world
(60, 140) increasing values of y increasing values of xTable 2-2
T A B L E 2 - 2 Selected functions exported by the graphics.h interface
initGraphics()
initGraphics(width, height)
Initializes the graphics window. If width and height are omitted, this function creates a window with a default size.
drawLine(x0, y0, x1, y1) Draws a line from the point (x0, y0) to the point (x1, y1).
drawPolarLine(x, y, r, theta) Draws a line from the point (x, y) that extends r r pixel units at angle theta relative to the +x axis. This function returns the endpoint of the line as a GPoint.
drawRect(x, y, width, height) Draws the frame of the rectangle with the specified bounds. fillRect(x, y, width, height) Fills the rectangle with the specified bounds.
drawOval(x, y, width, height) Draws the frame of the oval inscribed in the specified rectangle. fillOval(x, y, width, height) Fills the oval inscribed in the specified rectangle.
drawArc(x, y, width, height, start, sweep)
Draws an elliptical arc. The x, y, width, and height parameters specify the bounding rectangle of the complete ellipse. The start parameter indicates the angle at which the arc begins; the sweep parameter indicates how far the arc extends. Both angles are measured in degrees counterclockwise from the +x axis.
fillArc(x, y, width, height, start, sweep)
Fills the wedge-shaped area bounded by the elliptical arc that would be produced by drawArc and the radial lines connecting the endpoints of the arc to the center of the ellipse.
drawImage(filename, x, y) Draws the image from the specified file with its upper left corner at the point (x, y). The graphics library looks for the image file in the current directory and then in a subdirectory called images. drawString(str, x, y) Draws the string str so that its baseline origin appears at the point
(x, y). The string appears in the current font and color. getStringWidth(str) Returns the width of the string str in the current font. setFont(font) Sets the font, where font is in the form "family-style-size". getFont() Returns the current font in the form "family-style-size".
setColor(color) Sets the current color The color parameter is either one of the standard color names or a string in the form "#rrggbb".
getColor() Returns the current color in the form "#rrggbb". saveGraphicsState() Saves the state of the graphics context.
restoreGraphicsState() Restores the graphics state from the most recent save. getWindowWidth() Returns the width of the graphics window in pixels. getWindowHeight() Returns the height of the graphics window in pixels.
repaint() Initiates an immediate update of the graphics window.
Fortunately, providing a complete description of the graphics library in the textbook seems to be unnecessary. Graphics is exciting enough that most students figure out how it works through some combination of the abbreviated descriptions in Table 2-2, the examples in the text, the complete listing of the interface in Appendix A, and their own experimentation. If you want to enjoy the process of learning this material to the utmost, I suggest you do the same.
Summary
In this chapter, you learned about functions, which enable you to refer to an entire set of operations by using a simple name. By allowing the programmer to ignore the internal details and concentrate only on the effect of a function as a whole, functions are an essential tool for reducing the conceptual complexity of programs.
The important points introduced in this chapter include:
• A function is a block of code that has been organized into a separate unit and given a name. Other parts of the program can then call that function, possibly passing it information in the form of arguments and receiving a result returned by that function.
• Functions serve several useful purposes in programming. Allowing the same set of instructions to be shared by many parts of a program reduces both its size and its complexity. More importantly, functions make it possible to decompose large programs into smaller, more manageable pieces. Functions also serve as the basis for implementing algorithms, which are precisely specified strategies for solving computational problems.
• Functions become even more useful when they are collected into a library, which can then be shared by many different applications. Each library typically defines several functions that share a single conceptual framework. In computer science, the process of making a function available through a library is called exporting that function.
• The <cmath> library exports several functions that are likely to be familiar from mathematics, including functions like sqrt, sin, and cos. As a client of the <cmath> library, you need to know how to call these functions, but do not need to know the details of how they work.
• In C++, functions must be declared before they are used. A function declaration is called a prototype. In addition to the prototype, functions have an implementation, which specifies the individual steps that function contains. • A function that returns a value must have a return statement that specifies the
result. Functions may return values of any type. Functions that return Boolean values are called predicate functions and play an important role in programming.
• A function that returns no result and is executed only for its effect is called a procedure.
• C++ allows you to define several functions with the same name as long as the compiler can use the number and types of the arguments to determine which function is required. This process is called overloading. The argument pattern that distinguishes each of the overloaded variants is called a signature. C++ also makes it possible to specify default parameters, which are used if the client omits them from the call.
• Variables declared with a function are local to that function and cannot be used outside of it. Internally, all the variables declared within a function are stored together in a stack frame.
• When you call a function, the arguments are evaluated in the context of the caller and then copied into the parameter variables specified in the function prototype. The association of arguments and parameters always follows the order in which the variables appear in each of the lists.
• C++ makes it possible for a function and its caller to share the value of a parameter variable by marking it with the ampersand character (&). This style of parameter transmission is referred to as call by reference.
• When a function returns, it continues from precisely the point at which the call was made. The computer refers to this point as the return address and keeps track of it in the stack frame.
• Programmers who create a library are its implementers; programmers who make use of one are called its clients. The connection between the implementer and the client is called an interface. Interfaces typically export functions, types, and constants, which are collectively known as interface entries.
• In C++, interfaces are stored in header files, which typically end with a .h suffix. Every interface should include several lines of interface boilerplate to ensure that the compiler reads it only once.
• When you design an interface, you must balance several criteria. Well-designed interfaces are unified, simple, sufficient, general, and stable.
• The random.h interface exports several functions that make it easy to simulate random behavior.
Review questions
1. Explain in your own words the difference between a function and a program. 2. Define the following terms as they apply to functions: call, argument, return.
3. True or false: Every function in a C++ program requires a prototype. 4. What is the prototype of the function sqrt in the <cmath> library? 5. Can there be more than one return statement in the body of a function? 6. What is a predicate function?
7. What is meant by the term overloading? How does the C++ compiler use signatures to implement overloading?
8. How do you specify a default value for a parameter?
9. True or false: It is possible to specify a default value for the first parameter to a function without specifying a default value for the second.
10. What is a stack frame?
11. Describe the process by which arguments are associated with parameters. 12. Variables declared within a function are said to be local variables. What is the
significance of the word local in this context? 13. What does the term call by reference mean?
14. How do you indicate call by reference in a C++ program?
15. Define the following terms in the context of libraries: client, implementation, interface.
16. If you were writing an interface called mylib.h, what lines would you include as the interface boilerplate?
17. Describe the process used to export a constant definition as part of an interface. 18. What criteria does this chapter list as important in the process of interface
design?
19. Why is it important for an interface to be stable? 20. What is meant by the term pseudorandom number?
22. What four steps are necessary to convert the result of rand into an integer value with a different range?
23. How would you use the randomInteger function to generate a pseudorandom number between 1 and 100?
24. By executing each of the statements in the implementation by hand, determine whether the randomInteger function works with negative arguments. What are the possible results of calling the function randomInteger(-5, 5)? 25. Assuming that d1 and d2 have already been declared as variables of type int,
could you use the multiple assignment statement d1 = d2 = RandomInteger(1, 6); to simulate the process of rolling two dice?
26. True or false: The rand function ordinarily generates the same sequence of random numbers every time a program is run.
27. What is meant by the term seed in the context of random numbers?
28. What suggestion does this chapter offer for debugging a program involving random numbers?
29. What functions are defined in the final version of the random.h interface? In what context would you use each function?
Exercises
1. If you did not do so the first time around, rewrite the Celsius-to-Fahrenheit program from exercise 1 in Chapter 1 so that it uses a function to perform the conversion.
2. Reimplement the distance-conversion program from exercise 2 in Chapter 1 so that it uses a function. In this case, the function must produce both the number of feet and the number of inches, which means that you need to use call by reference to return these values.
3. When a floating-point number is converted to an integer in C++, the value is truncated by throwing away any fraction. Thus, when 4.99999 is converted to an integer, the result is 4. In many cases, it would be useful to have the option of rounding a floating-point value to the nearest integer. Given a positive
floating-point number x, you can round it to the closest integer by adding 0.5 and then truncating the result to an integer. Because truncation always moves toward zero, rounding negative numbers requires you to subtract 0.5, rather than adding it.
Write a function roundToNearestInt(x) that rounds the floating-point number x to the nearest integer. Show that your function works by writing a suitable main program to test it.
4. If you are unfortunate enough to be outside in winter weather, you know that your perception of the cold is dependent on the wind speed as well as the temperature. The faster the wind blows, the colder you feel. To quantify the how wind affects temperature perception, the National Weather Service reports the wind chill, which is illustrated on their website as shown in Figure 2-15. At the bottom of the figure, you can see that the formula for wind chill is
35.74 + 0.6215t – 35.75v0.16 + 0.4275tv0.16
where t is the Fahrenheit temperature and v is the wind speed in miles per hour.