hw7_fncts.cpp
/* Programmer: Jennifer Leopold Date: October 17, 2015
File: hw7_functs.cpp
Purpose: Function definitions used for building a database
of cars, and querying the database by license plate
number and car color.
*/
#include <iostream>
#include "hw7_functs.h"
using namespace std;
char getYNInput(const string prompt)
{
char input;
bool invalidInput;
do
{
cout << prompt;
cin >> input;
input = toupper(input);
invalidInput = (input != 'Y') && (input != 'N');
if (invalidInput)
cout << "Invalid input: you must enter 'Y' or 'N'!\n";
} while (invalidInput);
return(input);
}
void buildCarDatabase(carInfo cars[], const short n)
{
for (short i = 0; i < n; i++)
{
// Generate a distinct (i.e., not previously assigned)
// license plate for this car
do
{
// Randomly assign chars 0-2 of license plate
// a char from 'A', 'B', 'C'
for (int j = 0; j < 3; j++)
cars[i].license[j] =
static_cast<char>((rand() % 3) + ASCII_A);
// Randomly assign chars 3-5 of license plate
// a char from '0'..'9'
for (int j = 3; j < LICENSE_PLATE_LENGTH; j++)
cars[i].license[j] =
static_cast<char>((rand() % 10) + ASCII_0);
cars[i].license[LICENSE_PLATE_LENGTH] = '\0';
} while (findCarByLicense(cars, i, cars[i].license));
// Randomly assign this car a color from CAR_COLORS
cars[i].color = CAR_COLORS[rand() % NUM_COLORS];
// Randomly assign this car an owner from OWNER_NAMES
cars[i].owner = OWNER_NAMES[rand() % NUM_NAMES];
}
return;
}
void printCarDatabase(const carInfo cars[],
const short start,
const short stop)
{
// Output header
cout << "Car Database:\n";
cout << "License\tColor\t\tOwner\n";
cout << "-------------------------------------------"
<< "--------\n";
// Output info about each car
for (short i = start; i < stop; i++)
printCar(cars[i]);
cout << endl;
return;
}
void printCar(const carInfo car)
{
cout << car.license << "\t" << car.color << "\t";
if (car.color.length() < TAB_SPACES)
cout << "\t";
cout << car.owner << endl;
return;
}
void queryCarDatabase(const carInfo cars[],
const short n)
{
char license[LICENSE_PLATE_LENGTH+1];
string color;
short scores[NUM_CARS];
short minScore, highestScore = 0;
// Get user input for license plate pattern, car color, and
// minimum score for matches to report
getLicenseInput(license);
getColorInput(color);
getMinimumScoreForReporting(minScore);
// Score each car and also note highest match score
for (short i = 0; i < n; i++)
{
scores[i] = colorScore(color, cars[i].color) +
licenseScore(license, cars[i].license);
if (scores[i] > highestScore)
highestScore = scores[i];
}
// Output info about each car that met or exceeded minScore,
// in descending order of score (grouped by score)
if (highestScore < minScore)
cout << "\nThere are no cars that meet your "
<< "query criteria.\n";
else
{
for (short j = highestScore; j >= minScore; j--)
{
cout << "\nScore " << j << ":\n";
for (short i = 0; i < n; i++)
if (scores[i] == j) printCar(cars[i]);
}
}
cout << endl;
return;
}
short licenseScore(const char pattern[], const char license[])
{
short score = 0;
// Each exact char match earns 2 pts., wildcard match '*'
// earns 1 pt.
for (int i = 0; i < LICENSE_PLATE_LENGTH; i++)
if (pattern[i] == license[i])
score += 2;
else if ((pattern[i] != license[i]) &&
(pattern[i] == WILDCARD_MATCH))
score +=1;
return(score);
}
short colorScore(const string color1, const string color2)
{
short c1 = colorCode(color1);
short c2 = colorCode(color2);
short difference, score;
difference = abs(c1-c2);
// A difference of 0 earns 2 pts., a difference of 1
// earns 1 pt., and any other difference earns 0 pts.
if (difference == 0)
score = 2;
else if (difference == 1)
score = 1;
else score = 0;
return(score);
}
short colorCode(const string color)
{
short i = 0;
bool found = false;
// The code associated with a color is its index in the
// CAR_COLORS array
while (!found && (i < NUM_COLORS))
if (color == CAR_COLORS[i])
found = true;
else i++;
return(i);
}
void getMinimumScoreForReporting(short& minScore)
{
bool validInput;
do
{
cout << "\nEnter minimum match score for reporting: ";
cin >> minScore;
validInput = minScore >= 0;
if (!validInput)
cout << "Invalid input!\n";
} while (!validInput);
return;
}
void getColorInput(string& color)
{
bool validInput;
short i;
do
{
cout << "\nEnter color of car: ";
getline(cin, color, '\n');
// Must be a color in the CAR_COLORS array
validInput = false; i = 0;
while (!validInput && (i < NUM_COLORS))
if (color == CAR_COLORS[i])
validInput = true;
else i++;
if (!validInput)
cout << "Invalid color entered!\n";
} while (!validInput);
return;
}
void getLicenseInput(char license[])
{
bool validInput;
do
{
cout << "\nEnter license of car "
<< "(* for each unknown character): ";
cin >> license;
cin.ignore(NUM_CHARS_TO_IGNORE_UNTIL_NEWLINE, '\n');
validInput = true;
// 1st 3 chars must be uppercase alphabetic chars or '*'
for (int i = 0; i < 3; i++)
if (((!isalpha(license[i])) || (!isupper(license[i]))) &&
(license[i] != WILDCARD_MATCH))
validInput = false;
// Last 3 chars must be digits or '*'
for (int i = 3; i < LICENSE_PLATE_LENGTH; i++)
if ((!isdigit(license[i])) &&
(license[i] != WILDCARD_MATCH))
validInput = false;
if (!validInput)
cout << "Invalid license entered!\n";
} while (!validInput);
return;
}
bool findCarByLicense(const carInfo cars[],
const short n,
const char license[])
{
bool found = false;
short i = 0;
while (!found && (i < n))
if (strcmp(license, cars[i].license) == 0)
found = true;
else i++;
return(found);
}