//
// CS 202 program 08_structures.cpp
// Written by D.C. Williams for 10/9/03 class
//
// Program to review the use of pointers and to introduce command line
// arguments amd simple structures in the process of computing the 3 angles of
// a triangle given the lengths of the sides.
//
// This algorithm uses law of cosines: c^2 = a^2 + b^2 - 2*a*b*cos(C), where
// C is the angle opposite side c. The trick is to calculate one angle,
// rotate the sides, and use the same expression to calculate the next angle.
// Three passes through the same loop calculates all three angles!
//
#include <iostream.h>
#include <math.h>
#include <iomanip.h> // this allows us to format the data output
float Angle_calc(float, float, float); // to calculate the angles
int Ttest(float&, float&, float&, char); // to test for valid data
const float RTD = float(45. / atan(1.)); // convert rad to degrees
struct Side_angle // declare a global structure of the type "Side_angle"
// global means we can create them in any function
{
float side; // this structure includes the length of a side
float angle; // and the measure of the angle opposite that side
// these are called "structure members" and can function
// just like any other variable.
// for those who remember classes, a structure is just
// like a class with all public members and no functions!
};
int main(int argc, char *argv[]) // argc, argv handle command line arguments
// argc = number of strings on command line
// argv = pointer array for those strings
{
char arg = '0'; // initialize in case there's no argument
if (argc > 1) // and change it to equal the first character
arg = *argv[1]; // of the argument if there is one
// (note the de-referenced pointer)
Side_angle a, b, c; // reserve storage for three structures: a, b, and c
// each holds the data for a side and the opposite angle
int flag = 1; // flag = 1 means keep running
cout << "\n\nProgram to calculate angles of a triangle given the sides.";
while (flag != 0) // flag = 0 will cause this loop to bail
{
cout << "\n\n\nInput three lengths separated by spaces (0 0 0 to quit): ";
cin >> a.side >> b.side >> c.side; // this is how we use our members
if (a.side == 0. && b.side == 0. && c.side == 0)
{
flag = 0; // time to bail!
break;
}
if (a.side <= 0. || b.side <= 0. || c.side <= 0)
cout << "\nInvalid input data! Try again!" << endl;
if(Ttest(a.side, b.side, c.side, arg)) // test validity
cout << "\nThat is NOT a valid triangle!" << endl;
else
{
cout << "\nThese lengths represent a valid triangle." << endl; // bogus triangles
a.angle = Angle_calc(b.side, c.side, a.side);
b.angle = Angle_calc(c.side, a.side, b.side);
c.angle = Angle_calc(a.side, b.side, c.side);
cout << setw(7) << setiosflags(ios::fixed) << setprecision(3)
<< "\n\nSide length: " << a.side
<< " , measure of angle opposite this side: "
<< a.angle * RTD << " degrees.";
cout << setw(7) << setiosflags(ios::fixed) << setprecision(3)
<< "\n\nSide length: " << b.side
<< " , measure of angle opposite this side: "
<< b.angle * RTD << " degrees.";
cout << setw(7) << setiosflags(ios::fixed) << setprecision(3)
<< "\n\nSide length: " << c.side
<< " , measure of angle opposite this side: "
<< c.angle * RTD << " degrees.";
}
}
return 0;
}
float Angle_calc(float a, float b, float c)
{
return float(acos((pow(c,2.) - pow(a,2.) - pow(b,2.)) / (-2. * a * b)));;
}
int Ttest(float& a, float& b, float& c, char arg)
{
//
// the algorithm: find the largest side and make sure that the sum
// of the other two sides is greater than that.
//
// this also places the three sides in order by length
//
// declare pointers to those variables
float *pmax = 0, *pmid = 0; // create a pointer to a float and set to 0
float *pmin = NULL; // create a pointer to a float and set to NULL
// (0 and null are the same)
// it's important to initialize pointers when
// they're declared even if we set them to
// zero and later reassign them
if (a > b) // start with 2 sides and put them in order
{
pmax = &a; // remember that & means "the address of"
pmin = &b;
}
else
{
pmax = &b;
pmin = &a;
}
if (c >= *pmax) // take the third side and find out where it
// goes WRT the first 2
{
pmid = pmax; // no * or & here - we're passing the address
// from pointer to pointer
pmax = &c;
}
else if (c >= *pmin)
pmid = &c;
else
{
pmid = pmin;
pmin = &c;
}
// a verbose output routine to illustrate how to de-reference pointers
//
// * = indirecton operator = dereference operator = print the value stored
// in the pointer's memory location . . . without it, the address is
// printed instead (that's what's stored as the value of a pointer variable)
//
if (arg == 'v') // only execute this code if we asked for verbose output
{
cout << "\n\nLength of longest side = " << *pmax
<< " , memory address of this value = " << pmax << endl;
cout << "Length of middle side = " << *pmid
<< " , memory address of this value = " << pmid << endl;
cout << "Length of shortest side = " << *pmin
<< " , memory address of this value = " << pmin << endl << endl;
} // end of verbose output routine
if (*pmax < (*pmid + *pmin)) // the actual test
return 0; // anything except 1 means we have a triangle
else
return 1; // but returning 1 means it's not
}
//
//
//