// specify the maximum number of circles the program is capable of handling
const int MaxCircles = 20;
struct Circle {
double x,y; // (x,y) coords for the centre of the circle
double rad; // radius of the circle (must be > 0)
};
// get the desired number of circles from the user, 1..max
int getNumCircs(int max);
// get a real number from the user, optionally restricted to positive numbers only
double getNumber(string promptInfo, bool mustBePositive = false);
// fill all the fields of the circle struct (uses getNum for each)
void fill(Circle& c);
// fill all the circles (using the fill function)
void fillAll(Circle circs[], int num);
// see if two circles overlap
bool overlap(Circle c1, Circle c2);
// print one circle's information as (x,y:r)
void print(Circle c);
// print a list of all overlapping circles
void printOverlaps(Circle circs[], int numCircs);
|
int main()
{
// array of maximum number of circles
Circle circles[MaxCircles];
// find out how many the user actually wants
int numberCircles = getNumCircs(MaxCircles);
// fill the circles
fillAll(circles, numberCircles);
// display all the overlaps
printOverlaps(circles, numberCircles);
}
|
| (Now that the programs are getting more complex and involve more data, a standardized batch of tests gets run on all student programs in addition to me reading your code. The test program provides fixed sets of test values in fixed orders, following the patterns in the code design below. If your program expects different information or in a different order then it won't work and will fail the testing.) |
// get the desired number of circles from the user, 1..max
int getNumCircs(int max)
{
// get the number of circles from the user
int numCs;
cout << "Please enter the desired number of circles, 1.." << max << ": ";
cin >> numCs;
// error check and recurse if needed
if (cin.fail()) {
cin.clear();
cin.ignore(LineLen, '\n');
cerr << "The value must be an integer, please try again" << endl;
numCs = getNumCircs(max);
} else if ((numCs < 1) || (numCs > max)) {
cerr << "The value must be in the range 1.. " << max << ", please try again" << endl;
numCs = getNumCircs(max);
}
// return the validated result
return numCs;
}
// get a real number from the user, optionally restricted to positive numbers only
double getNumber(string promptInfo, bool mustBePositive)
{
// prompt the user, adjusting for the must-be-positive restriction if needed
cout << "Please enter a number";
if (mustBePositive) {
cout << " greater than zero";
}
cout << " for the " << promptInfo << ": ";
// get the user's input
double num;
cin >> num;
// error check and recurse if needed
if (cin.fail()) {
cin.clear();
cin.ignore(LineLen, '\n');
cerr << "The value must be a number, please try again" << endl;
num = getNumber(promptInfo, mustBePositive);
} else if (mustBePositive && (num <= 0)) {
cerr << "The value must be greater than 0, please try again" << endl;
num = getNumber(promptInfo, mustBePositive);
}
// return the validated result
return num;
}
|
// fill all the fields of the circle struct (uses getNum for each)
void fill(Circle& c)
{
c.x = getNumber("x coord");
c.y = getNumber("y coord");
c.rad = getNumber("radius", true);
}
|
// fill all the circles (using the fill function)
void fillAll(Circle circs[], int num)
{
// for each of positions 0 through num-1,
// call fill on circs[c]
}
|
// see if two circles overlap
bool overlap(Circle c1, Circle c2)
{
// calculate the distance between the two centres
double xdist = c1.x - c2.x;
double ydist = c1.y - c2.y;
double distance = sqrt(xdist*xdist + ydist*ydist);
// if the distance is more than the combined radii then they do not overlap
if (distance > (c1.rad + c2.rad)) {
return false;
}
// otherwise they overlap (or at least touch)
return true;
}
// print one circle's information as (x,y:r)
void print(Circle c)
{
cout << "(" << c.x << "," << c.y << ":" << c.rad << ")";
}
// print a list of all overlapping circles
void printOverlaps(Circle circs[], int numCircs)
{
// we'll need a variable to track how many overlaps we've detected, initialized to 0
// we'll use nested for loops that compares each circle with every circle later in the list
// (to avoid printing overlapping pairs twice)
// for c1 is 0 to numCircs-2
// for c2 is c1+1 to numCircs-1
// call overlap on circs[c1] and circs[c2], and if it
// says they overlap then print the two of them
// (and increment our overlap counter)
}
|
Please enter the desired number of circles, 1..20: 3 Now filling circle number 0 Please enter a number for the x coord: 1 Please enter a number for the y coord: 1 Please enter a number greater than zero for the radius: 1 Now filling circle number 1 Please enter a number for the x coord: -1.5 Please enter a number for the y coord: 0.99 Please enter a number greater than zero for the radius: 0.85 Now filling circle number 2 Please enter a number for the x coord: 0 Please enter a number for the y coord: 0.1 Please enter a number greater than zero for the radius: 0.99 Detecting overlapping circles... Overlapping pair: (1,1:1) and (0,0.1:0.99) Overlapping pair: (-1.5,0.99:0.85) and (0,0.1:0.99) Number of overlaps detected: 2 |
// constants representing the valid package commands
const char Help = 'H'; // command for displaying help menu
const char Quit = 'Q'; // command for quitting the program
const char Insert = 'I'; // command to get package info from the user and insert into the queue
const char Remove = 'R'; // command to remove a package from the queue and display its info
const char Size = 'S'; // command to display the current number of packages in the queue
const char Print = 'P'; // command to print the information for all packages in the queue
// (starting from front of queue and continuing to the back)
const char Error = 'E'; // used to represent any invalid commands
// display the available processing commands
void commandHelp();
// get a valid package command from the user
// (repeats until a valid command is provided)
char getCommand();
// command to process a command, applying it to the given queue
void processCommand(char command, Queue &Q);
// ====================================================================================
// ========== main routine ==========================================================
// ====================================================================================
int main()
{
// set up a queue of packages
Queue pkgs;
initQ(pkgs);
// introduce the user to the program and display the instructions
cout << "\nWelcome to the package processor!\n";
commandHelp();
// keep processing commands until the user decides to quit
char command;
do {
command = getCommand();
processCommand(command, pkgs);
} while (command != Quit);
return 0;
}
|
// datatype describing a package for delivery
struct Package {
string sender; // name of sender
string recipient; // name of receiver
string content; // description of package contents
string address; // full address of receiver
float value; // estimated value of contents
};
// fill package p with user-supplied data
void fillPkg(Package &p);
// display package p's information
void printPkg(Package p);
|
// maximum number of packages we can be processing at once
const int MaxPackages = 4;
// datatype describing a queue of packages, implemented as a circular buffer
// (an array with tracked front and back positions, with the potential for front
// and back to 'wrap-around' as items are inserted and removed over time)
struct Queue {
Package pkgArray[MaxPackages]; // actual array of packages
int front; // position of front package in queue (-1 if empty)
int back; // position of back package in queue (-1 if empty)
int size; // number of elements currently in the queue (0 if empty)
};
// initialize a package queue (as empty)
void initQ(Queue &q);
// looks up and returns the number of elements currently in queue q
int getSizeQ(Queue q);
// adds new package to the back of queue q, copying its values from p
// returns true if successful, false otherwise
// (can fail if the queue is full)
bool insertQ(Package p, Queue &q);
// removes front package from queue q, copies data into p
// returns true if successful, false otherwise
// (can fail if the queue is empty)
bool removeQ(Package &p, Queue &q);
// displays the information about each package in the queue
void printQ(Queue q);
|
| The technique we're using is called a circular buffer, and is widely used for array-based queue implementations. The starter code for functions insertQ, removeQ, and printQ contains suggested algorithms that will handle the wrap around correctly (as well as the error checking for invalid inserts/removes). |
Welcome to the package processor! The available commands are: H to display this help menu Q to exit the program I to add a new package to the back of the queue R to remove and display the front queue package S to see the number of packages currently queued P to show each of the packages currently queued Enter a command (HQIRSP): S The current number of queued packages is 0 Enter a command (HQIRSP): P The queue is currently empty Enter a command (HQIRSP): R Error: attempt to remove package into from an empty queue Removal failure Enter a command (HQIRSP): I Enter sender name (one line): its me Enter receiver name (one line): them folks Enter destination address (one line): 1234 over therre Enter content description (one line): just some stuff, 1 or 2 things Enter content dollar value, e.g. 20.99: 99.23 Insertion successful Enter a command (HQIRSP): I Enter sender name (one line): them Enter receiver name (one line): me Enter destination address (one line): here Enter content description (one line): garbage Enter content dollar value, e.g. 20.99: 0.01 Insertion successful Enter a command (HQIRSP): I Enter sender name (one line): someone Enter receiver name (one line): someone else Enter destination address (one line): someplace, I dunno Enter content description (one line): whatever Enter content dollar value, e.g. 20.99: 1.23 Insertion successful Enter a command (HQIRSP): P The queue contents (front to back) are: To: its me Addr: 1234 over therre From: them folks Content: just some stuff, 1 or 2 things Value: 99.23 To: them Addr: here From: me Content: garbage Value: 0.01 To: someone Addr: someplace, I dunno From: someone else Content: whatever Value: 1.23 Enter a command (HQIRSP): R Successful removal of package: To: its me Addr: 1234 over therre From: them folks Content: just some stuff, 1 or 2 things Value: 99.23 Enter a command (HQIRSP): P The queue contents (front to back) are: To: them Addr: here From: me Content: garbage Value: 0.01 To: someone Addr: someplace, I dunno From: someone else Content: whatever Value: 1.23 Enter a command (HQIRSP): S The current number of queued packages is 2 Enter a command (HQIRSP): I Enter sender name (one line): them again Enter receiver name (one line): me again Enter destination address (one line): this place Enter content description (one line): more stuff Enter content dollar value, e.g. 20.99: 100 Insertion successful Enter a command (HQIRSP): I Enter sender name (one line): me2 Enter receiver name (one line): them2 Enter destination address (one line): there2 Enter content description (one line): stuff2 Enter content dollar value, e.g. 20.99: 1.234 Insertion successful Enter a command (HQIRSP): S The current number of queued packages is 4 Enter a command (HQIRSP): P The queue contents (front to back) are: To: them Addr: here From: me Content: garbage Value: 0.01 To: someone Addr: someplace, I dunno From: someone else Content: whatever Value: 1.23 To: them again Addr: this place From: me again Content: more stuff Value: 100 To: me2 Addr: there2 From: them2 Content: stuff2 Value: 1.234 Enter a command (HQIRSP): R Successful removal of package: To: them Addr: here From: me Content: garbage Value: 0.01 Enter a command (HQIRSP): R Successful removal of package: To: someone Addr: someplace, I dunno From: someone else Content: whatever Value: 1.23 Enter a command (HQIRSP): R Successful removal of package: To: them again Addr: this place From: me again Content: more stuff Value: 100 Enter a command (HQIRSP): R Successful removal of package: To: me2 Addr: there2 From: them2 Content: stuff2 Value: 1.234 Enter a command (HQIRSP): S The current number of queued packages is 0 Enter a command (HQIRSP): P The queue is currently empty Enter a command (HQIRSP): X Error: X is not a valid option, please try again Enter a command (HQIRSP): R Error: attempt to remove package into from an empty queue Removal failure Enter a command (HQIRSP): I Enter sender name (one line): 1 Enter receiver name (one line): 2 Enter destination address (one line): 3 Enter content description (one line): 4 Enter content dollar value, e.g. 20.99: foo Error: that was not a numeric value, please try again Enter content dollar value, e.g. 20.99: ick Error: that was not a numeric value, please try again Enter content dollar value, e.g. 20.99: -1 Error: the value cannot be negative, please try again Enter content dollar value, e.g. 20.99: 5 Insertion successful Enter a command (HQIRSP): P The queue contents (front to back) are: To: 1 Addr: 3 From: 2 Content: 4 Value: 5 Enter a command (HQIRSP): Q Bye! |