Another Example of Using Functions with Structures

Much of what you learn about functions and C++ structures carries over to C++ classes, so it’s worth looking at a second example. This time let’s deal with space instead of time. In particular, this example defines two structures representing two different ways of describing positions and then develops functions to convert one form to the other and show the result. This example is a bit more mathematical than the last, but you don’t have to follow the mathematics to follow the C++.

Suppose you want to describe the position of a point on the screen or a location on a map relative to some origin. One way is to state the horizontal offset and the vertical offset of the point from the origin. Traditionally, mathematicians use the symbol x to represent the horizontal offset and y to represent the vertical offset (see Figure 7.6). Together, x and y constitute rectangular coordinates. You can define a structure consisting of two coordinates to represent a position:

Figure 7.6. Rectangular coordinates.

Image

struct rect
{
      double x;           // horizontal distance from origin
      double y;           // vertical distance from origin
};

A second way to describe the position of a point is to state how far it is from the origin and in what direction it is (for example, 40 degrees north of east). Traditionally, mathematicians have measured the angle counterclockwise from the positive horizontal axis (see Figure 7.7). The distance and angle together constitute polar coordinates. You can define a second structure to represent this view of a position:

struct polar
{
       double distance;   // distance from origin
       double angle;      // direction from origin
};

Figure 7.7. Polar coordinates.

Image

Let’s construct a function that displays the contents of a type polar structure. The math functions in the C++ library (borrowed from C) assume that angles are in radians, so you need to measure angles in that unit. But for display purposes, you can convert radian measure to degrees. This means multiplying by 180/π, which is approximately 57.29577951. Here’s the function:

// show polar coordinates, converting angle to degrees
void show_polar (polar dapos)
{
    using namespace std;
    const double Rad_to_deg = 57.29577951;

    cout << "distance = " << dapos.distance;
    cout << ", angle = " << dapos.angle * Rad_to_deg;
    cout << " degrees ";
}

Notice that the formal variable is type polar. When you pass a polar structure to this function, the structure contents are copied into the dapos structure, and the function then uses that copy in its work. Because dapos is a structure, the function uses the membership (dot) operator (see Chapter 4) to identify structure members.

Next, let’s try something more ambitious and write a function that converts rectangular coordinates to polar coordinates. We’ll have the function accept a rect structure as its argument and return a polar structure to the calling function. This involves using functions from the math library, so the program has to include the cmath header file (math.h on older systems). Also on some systems you have to tell the compiler to load the math library (see Chapter 1, “Getting Started with C++”). You can use the Pythagorean theorem to get the distance from the horizontal and vertical components:

distance = sqrt( x * x + y * y)

The atan2() function from the math library calculates the angle from the x and y values:

angle = atan2(y, x)

(There’s also an atan() function, but it doesn’t distinguish between angles 180 degrees apart. That uncertainty is no more desirable in a math function than it is in a wilderness guide.)

Given these formulas, you can write the function as follows:

// convert rectangular to polar coordinates
polar rect_to_polar(rect xypos)   // type polar
{
    polar answer;

    answer.distance =
        sqrt( xypos.x * xypos.x + xypos.y * xypos.y);
    answer.angle = atan2(xypos.y, xypos.x);
    return answer;      // returns a polar structure
}

Now that the functions are ready, writing the rest of the program is straightforward. Listing 7.12 presents the result.

Listing 7.12. strctfun.cpp


// strctfun.cpp -- functions with a structure argument
#include <iostream>
#include <cmath>

// structure declarations
struct polar
{
    double distance;      // distance from origin
    double angle;         // direction from origin
};
struct rect
{
    double x;             // horizontal distance from origin
    double y;             // vertical distance from origin
};

// prototypes
polar rect_to_polar(rect xypos);
void show_polar(polar dapos);

int main()
{
    using namespace std;
    rect rplace;
    polar pplace;

    cout << "Enter the x and y values: ";
    while (cin >> rplace.x >> rplace.y)  // slick use of cin
    {
        pplace = rect_to_polar(rplace);
        show_polar(pplace);
        cout << "Next two numbers (q to quit): ";
    }
    cout << "Done. ";
    return 0;
}

// convert rectangular to polar coordinates
polar rect_to_polar(rect xypos)
{
    using namespace std;
    polar answer;

    answer.distance =
        sqrt( xypos.x * xypos.x + xypos.y * xypos.y);
    answer.angle = atan2(xypos.y, xypos.x);
    return answer;      // returns a polar structure
}

// show polar coordinates, converting angle to degrees
void show_polar (polar dapos)
{
    using namespace std;
    const double Rad_to_deg = 57.29577951;

    cout << "distance = " << dapos.distance;
    cout << ", angle = " << dapos.angle * Rad_to_deg;
    cout << " degrees ";
}



Note

Some compilers require explicit instructions to search the math library. For example, older versions of g++ uses this command line:

g++ structfun.C -lm


Here is a sample run of the program in Listing 7.12:

Enter the x and y values: 30 40
distance = 50, angle = 53.1301 degrees
Next two numbers (q to quit): -100 100
distance = 141.421, angle = 135 degrees
Next two numbers (q to quit): q

Program Notes

We’ve already discussed the two functions in Listing 7.12, so let’s review how the program uses cin to control a while loop:

while (cin >> rplace.x >> rplace.y)

Recall that cin is an object of the istream class. The extraction operator (>>) is designed in such a way that cin >> rplace.x also is an object of that type. As you’ll see in Chapter 11, “Working with Classes,” class operators are implemented with functions. What really happens when you use cin >> rplace.x is that the program calls a function that returns a type istream value. If you apply the extraction operator to the cin >> rplace.x object (as in cin >> rplace.x >> rplace.y), you again get an object of the istream class. Thus, the entire while loop test expression eventually evaluates to cin, which, as you may recall, when used in the context of a test expression, is converted to a bool value of true or false, depending on whether input succeeded. In the loop in Listing 7.12, for example, cin expects the user to enter two numbers. If, instead, the user enters q, as shown in the sample output, cin >> recognizes that q is not a number. It leaves the q in the input queue and returns a value that’s converted to false, terminating the loop.

Compare that approach for reading numbers to this simpler one:

for (int i = 0; i < limit; i++)
{
    cout << "Enter value #" << (i + 1) << ": ";
    cin >> temp;
    if (temp < 0)
        break;
    ar[i] = temp;
}

To terminate this loop early, you enter a negative number. This restricts input to non-negative values. This restriction fits the needs of some programs, but more typically you would want a means of terminating a loop that doesn’t exclude certain numeric values. Using cin >> as the test condition eliminates such restrictions because it accepts all valid numeric input. You should keep this trick in mind when you need an input loop for numbers. Also, you should keep in mind that non-numeric input sets an error condition that prevents the reading of any more input. If a program needs input subsequent to the input loop, you must use cin.clear() to reset input, and you might then need to get rid of the offending input by reading it. Listing 7.7 illustrates those techniques.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.151.164