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);

}