+- PA02_Main +- PA02_Main.c +- StateUtilities.c ++ outRelease (precompiled for UNIX systems)
627 lines
No EOL
23 KiB
C
627 lines
No EOL
23 KiB
C
#include "StateUtilities.h"
|
|
|
|
// local constants
|
|
const int NAME_BLOCK_SIZE = 16;
|
|
const int POPULATION_BLOCK_SIZE = 12;
|
|
const int GROWTH_BLOCK_SIZE = 10;
|
|
// missing constants from assignment file
|
|
const int ITEM_BLOCK_SIZE = 6;
|
|
const int MAJORITY_BLOCK_SIZE = 10;
|
|
const char EQUALS = '=';
|
|
const char PLUS = '+';
|
|
const int TITLE_LENGTH = 38;
|
|
|
|
// functions
|
|
|
|
/*
|
|
Name: addElementFromData
|
|
Process: adds all individual data values to StateDataType array
|
|
if capacity has not been exceeded,
|
|
returns true upon success, false otherwise
|
|
Function input/parameters: data array (StateDataType *),
|
|
size (int), capacity (int),
|
|
state name (const char *),
|
|
state population (int),
|
|
state growth (double),
|
|
state political majority (char)
|
|
Function output/parameters: updated data array (StateDataType *),
|
|
updated size (int *)
|
|
Function output/returned: Boolean result of operation as specified
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed, including strcpy
|
|
*/
|
|
bool addElementFromData( StateDataType *stateArr, int *size, int capacity,
|
|
const char *stateName, int statePop,
|
|
double stateGrowth, char politicalMajority )
|
|
{
|
|
// check to see if the size will go over the capacity
|
|
if(*size < capacity)
|
|
{
|
|
// put in the data to the array
|
|
// array[*size] = parameter
|
|
stateArr[*size].population = statePop;
|
|
stateArr[*size].growth = stateGrowth;
|
|
stateArr[*size].majority = politicalMajority;
|
|
// string is a little different.
|
|
// use strcpy(array[*size].name, stateName)
|
|
strcpy(stateArr[*size].name, stateName);
|
|
// increment size (*size = *size + 1)
|
|
*size = *size + 1;
|
|
// return true
|
|
return true;
|
|
}
|
|
// otherwise, return false.
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: addElementFromElement
|
|
Process: adds data from element to StateDataType array,
|
|
uses supporting function
|
|
Function input/parameters: data array (StateDataType *),
|
|
size and capacity (int),
|
|
source element (const StateDataType)
|
|
Function output/parameters: updated data array (StateDataType *),
|
|
updated size (int *)
|
|
Function output/returned: Boolean result of operation as specified
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: addElementFromData - function uses one code statement
|
|
*/
|
|
bool addElementFromElement( StateDataType *stateArr, int *size, int capacity,
|
|
const StateDataType state )
|
|
{
|
|
return addElementFromData(stateArr, size, capacity, state.name,
|
|
state.population, state.growth, state.majority);
|
|
}
|
|
|
|
/*
|
|
Name: clearStateArray
|
|
Process: deallocates dynamically allocated array from memory
|
|
Function input/parameters: data array (StateDataType *)
|
|
Function output/parameters: none
|
|
Function output/returned: NULL
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed, including free
|
|
*/
|
|
StateDataType *clearStateArray( StateDataType *array )
|
|
{
|
|
// use free to deallocate the array
|
|
free(array);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
Name: copyArray
|
|
Process: copies state data elements from one array to another
|
|
Function input/parameters: source array (const StateDataType *), size (int)
|
|
Function output/parameters: pointer to destination array (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
void copyArray( StateDataType *dest, const StateDataType *src, int srcSize )
|
|
{
|
|
int currentSize;
|
|
// use a for loop to iterate through source array
|
|
// (start at zero, go to srcSize)
|
|
for(currentSize = 0; currentSize < srcSize; currentSize++)
|
|
{
|
|
// copy each element from the array to the new array.
|
|
// uses deepCopy to do this.
|
|
deepCopy(&dest[currentSize], src[currentSize]);
|
|
}
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: createStateArray
|
|
Process: dynamically allocates array memory
|
|
Function input/parameters: initial capacity (int)
|
|
Function output/parameters: none
|
|
Function output/returned: pointer to newly created array (StateDataType *)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed, including function malloc and keyword sizeof
|
|
*/
|
|
StateDataType *createStateArray( int initialCapacity )
|
|
{
|
|
// define variables (integer, StateDataType)
|
|
StateDataType *stateArray;
|
|
// use malloc to dynamically allocate the array,
|
|
// use the initialCapacity as the size to multiply by.
|
|
stateArray = malloc(sizeof(StateDataType) * initialCapacity);
|
|
// return the pointer to the array.
|
|
return stateArray;
|
|
}
|
|
|
|
/*
|
|
Name: deepCopy
|
|
Process: copies all individual values from StateDataType source
|
|
to StateDataType destination
|
|
Function input/parameters: source element (const StateDataType)
|
|
Function output/parameters: pointer to destination value (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed, including strcpy
|
|
*/
|
|
void deepCopy( StateDataType *dest, const StateDataType src )
|
|
{
|
|
// *dest.population = src.population (for each piece)
|
|
dest->population = src.population;
|
|
dest->growth = src.growth;
|
|
dest->majority = src.majority;
|
|
// strcpy for the string
|
|
// strcpy(*dest.name, src.name)
|
|
strcpy(dest->name, src.name);
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: displayData
|
|
Process: displays element data in array as table if array is not empty,
|
|
otherwise displays "Data not found - Display aborted",
|
|
allows for subtitle to be added to "Display Data - "
|
|
Function input/parameters: state data array (const StateDataType *),
|
|
size (int), subtitle (const char *)
|
|
Function output/parameters: none
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/monitor: data displayed as specified
|
|
Dependencies: as needed
|
|
*/
|
|
void displayData( const StateDataType *array, int size, const char *subTitle )
|
|
{
|
|
int countStates;
|
|
// iterate through array to size, check if zero.
|
|
if(size != 0)
|
|
{
|
|
printEndline();
|
|
printString("Display Data - ");
|
|
printString(subTitle);
|
|
printEndline();
|
|
printEndline();
|
|
// create a table
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print ITEM justified center
|
|
printStringJustified("Item", ITEM_BLOCK_SIZE, "CENTER");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print STATE NAME justified center
|
|
printStringJustified("State Name", NAME_BLOCK_SIZE, "CENTER");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print POPULATION justified center
|
|
printStringJustified("Population", POPULATION_BLOCK_SIZE, "CENTER");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print GROWTH justified center
|
|
printStringJustified("Growth", GROWTH_BLOCK_SIZE, "CENTER");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print MAJORITY justified center
|
|
printStringJustified("Majority", MAJORITY_BLOCK_SIZE, "CENTER");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print new line
|
|
printEndline();
|
|
// printing the top border piece
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print amount of = for ITEM
|
|
printCharacters(ITEM_BLOCK_SIZE, EQUALS);
|
|
// print PLUS (needs constant) character
|
|
printCharacter(PLUS);
|
|
// print amount of = for STATE NAME
|
|
printCharacters(NAME_BLOCK_SIZE, EQUALS);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of = for POPULATION
|
|
printCharacters(POPULATION_BLOCK_SIZE, EQUALS);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of = for GROWTH
|
|
printCharacters(GROWTH_BLOCK_SIZE, EQUALS);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of = for MAJORITY
|
|
printCharacters(MAJORITY_BLOCK_SIZE, EQUALS);
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print new line
|
|
printEndline();
|
|
for(countStates = 0; countStates < size; countStates++)
|
|
{
|
|
// use the constants to format the table
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print item justified right (size)
|
|
printIntegerJustified(countStates + 1, ITEM_BLOCK_SIZE, "RIGHT");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print state name justified left
|
|
printStringJustified(array[countStates].name,
|
|
NAME_BLOCK_SIZE, "LEFT");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print population justified right
|
|
printIntegerJustified(array[countStates].population,
|
|
POPULATION_BLOCK_SIZE, "RIGHT");
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print growth justified right, need a % sign too.
|
|
//(requires some math trickery to make work)
|
|
printDoubleJustified(array[countStates].growth * 100.00,
|
|
PRECISION_2, GROWTH_BLOCK_SIZE - 2, "RIGHT");
|
|
printCharacter('%');
|
|
printCharacter(SPACE);
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print majority justified center,
|
|
// also requires some math trickery to make work
|
|
printCharacters((MAJORITY_BLOCK_SIZE - 1) / 2, SPACE);
|
|
printCharacter(SPACE);
|
|
printCharacter(array[countStates].majority);
|
|
printCharacters((MAJORITY_BLOCK_SIZE - 1) / 2, SPACE);
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print endline
|
|
printEndline();
|
|
// printing for the spacer lines
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print amount of DASH for item
|
|
printCharacters(ITEM_BLOCK_SIZE, DASH);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of DASH for state name
|
|
printCharacters(NAME_BLOCK_SIZE, DASH);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of DASH for population
|
|
printCharacters(POPULATION_BLOCK_SIZE, DASH);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of DASH for growth
|
|
printCharacters(GROWTH_BLOCK_SIZE, DASH);
|
|
// print PLUS character
|
|
printCharacter(PLUS);
|
|
// print amount of DASH for majority
|
|
printCharacters(MAJORITY_BLOCK_SIZE, DASH);
|
|
// print PIPE character
|
|
printCharacter(PIPE);
|
|
// print endline
|
|
printEndline();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//print out "Data not found - Display aborted".
|
|
printString("Data not found - Display aborted");
|
|
printEndline();
|
|
}
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: findStateByName
|
|
Process: finds element value in array by state name if it exists in the array,
|
|
saves data in return parameter and returns true,
|
|
otherwise sets data in return parameter to empty and returns false
|
|
Function input/parameters: state data array (const StateDataType *),
|
|
size (int), search value (const StateDataType)
|
|
Function output/parameters: value if found as return parameter,
|
|
otherwise, return parameter set to empty
|
|
(StateDataType *)
|
|
Function output/returned: Boolean result of operation
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
bool findStateByName( StateDataType *foundElement,
|
|
const StateDataType *array, int size, const StateDataType searchValue )
|
|
{
|
|
int nameCount;
|
|
// iterate through array
|
|
for(nameCount = 0; nameCount < size; nameCount++)
|
|
{
|
|
// check to see if the state name is found (use searchValue)
|
|
if(strcmp(array[nameCount].name, searchValue.name) == 0)
|
|
{
|
|
// copy the element out of the array, put in foundElement
|
|
deepCopy(foundElement, array[nameCount]);
|
|
// return true
|
|
return true;
|
|
}
|
|
}
|
|
// otherwise, return false
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: removeStateByName
|
|
Process: searches for element, if found, sets data into return parameter,
|
|
shifts all remaining data down, and returns true,
|
|
otherwise sets data in return parameter to empty and returns false
|
|
Function input/parameters: state data array (StateDataType *),
|
|
size (int), search value (const StateDataType)
|
|
Function output/parameters: updated state data array (StateDataType *),
|
|
value if found and removed,
|
|
otherwise, value set to empty (StateDataType *),
|
|
updated size (int *)
|
|
Function output/returned: Boolean result of operation as specified
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
bool removeStateByName( StateDataType *removedElement,
|
|
StateDataType *array, int *size, const StateDataType searchVal )
|
|
{
|
|
int removeCount;
|
|
bool stateNameFoundFlag = false;
|
|
// iterate through array
|
|
if(findStateByName(removedElement, array, *size, searchVal))
|
|
{
|
|
//
|
|
for(removeCount = 0; removeCount < *size; removeCount++)
|
|
{
|
|
if(strcmp(array[removeCount].name, removedElement->name) == 0 ||
|
|
stateNameFoundFlag)
|
|
{
|
|
// set the flag to signify found value
|
|
stateNameFoundFlag = true;
|
|
// remove the element by copying
|
|
// the next element into last slot until end
|
|
deepCopy(&array[removeCount], array[removeCount + 1]);
|
|
}
|
|
}
|
|
// reduce the size by one
|
|
*size = *size - 1;
|
|
// return true
|
|
return true;
|
|
}
|
|
// otherwise, return false
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: runBubbleSortByName
|
|
Process: sorts state data by name using bubble sort algorithm
|
|
Function input/parameters: state data array (StateDataType *), size (int)
|
|
Function output/parameters: updated state data array (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
void runBubbleSortByName( StateDataType *array, int size )
|
|
{
|
|
int bubbleCount;
|
|
int arrayCount;
|
|
// use two for loops to iterate through array
|
|
for(bubbleCount = 0; bubbleCount < size - 1; bubbleCount++)
|
|
{
|
|
for(arrayCount = 0; arrayCount < size - bubbleCount - 1; arrayCount++)
|
|
{
|
|
// check the current index vs the next one.
|
|
if(strcmp(array[arrayCount].name, array[arrayCount + 1].name) > 0)
|
|
{
|
|
// if current > next, swap. AKA: strcmp(current, next) > 0
|
|
swapElements(array, arrayCount, arrayCount + 1);
|
|
}
|
|
}
|
|
}
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: runInsertionSortByPopulation
|
|
Process: sorts state data by population using insertion sort algorithm
|
|
Function input/parameters: state data array (StateDataType *), size (int)
|
|
Function output/parameters: updated state data array (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed, swap may not be used
|
|
*/
|
|
void runInsertionSortByPopulation( StateDataType *array, int size )
|
|
{
|
|
// define variables
|
|
int insertCount, insertIterator;
|
|
StateDataType insertStoreState;
|
|
// use a for loop to move through the array
|
|
for(insertCount = 0; insertCount < size; insertCount++)
|
|
{
|
|
// start the iterator at the same place where insertCount starts
|
|
insertIterator = insertCount;
|
|
// use a while loop to do the insert sort
|
|
while(insertIterator > 0 && (array[insertIterator - 1].population >=
|
|
array[insertIterator].population))
|
|
{
|
|
// store the element
|
|
deepCopy(&insertStoreState, array[insertIterator - 1]);
|
|
// move the next element to the last location
|
|
deepCopy(&array[insertIterator - 1], array[insertIterator]);
|
|
// put the element into the array
|
|
deepCopy(&array[insertIterator], insertStoreState);
|
|
// move the iterator to the previous index
|
|
insertIterator = insertIterator - 1;
|
|
}
|
|
}
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: runSelectionSortByGrowth
|
|
Process: sorts state data by growth using selection sort algorithm
|
|
Function input/parameters: state data array (StateDataType *), size (int)
|
|
Function output/parameters: updated state data array (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
void runSelectionSortByGrowth( StateDataType *array, int size )
|
|
{
|
|
int selectCount, selectIterator, smallestGrowth;
|
|
// use for loop to run through the whole array
|
|
for(selectCount = 0; selectCount < size; selectCount++)
|
|
{
|
|
// start at the not sorted part of the array
|
|
smallestGrowth = selectCount;
|
|
// use another for loop to find what the smallest growth is
|
|
for(selectIterator = selectCount + 1; selectIterator < size; selectIterator++)
|
|
{
|
|
// select the smallest growth
|
|
if(array[selectIterator].growth < array[smallestGrowth].growth)
|
|
{
|
|
// find the smallest growth of the array.
|
|
smallestGrowth = selectIterator;
|
|
}
|
|
}
|
|
// swap the elements of the array
|
|
swapElements(array, selectCount, smallestGrowth);
|
|
}
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: setEmptyElementData
|
|
Process: sets state data type to empty or default values,
|
|
name to empty string, population and growth to zero,
|
|
and majority to 'x'
|
|
Function input/parameters: none
|
|
Function output/parameters: state data value (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: none
|
|
*/
|
|
void setEmptyElementData( StateDataType *element )
|
|
{
|
|
// set the element's name to ""
|
|
strcpy(element->name, "");
|
|
// set the element's population and growth to 0
|
|
element->population = 0;
|
|
element->growth = 0.0;
|
|
// set the element's majority to 'x'
|
|
element->majority = 'x';
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: showTitle
|
|
Process: displays program title with thick underline,
|
|
"Data Management with N-Squared Sorting"
|
|
Function input/parameters: none
|
|
Function output/parameters: none
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/monitor: displays title as specified
|
|
Dependencies: as needed
|
|
*/
|
|
void showTitle()
|
|
{
|
|
// use console io utilities to display the string
|
|
printString("Data Management with N-Squared Sorting");
|
|
// print endline
|
|
printEndline();
|
|
// use console io utilities to display 38 '='
|
|
printCharacters(TITLE_LENGTH, EQUALS);
|
|
// print an endline
|
|
printEndline();
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: swapElements
|
|
Process: swaps state data elements within an array
|
|
Function input/parameters: given array (StateDataType *),
|
|
left and right indices to be swapped (int)
|
|
Function output/parameters: updated array with swapped values (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
void swapElements( StateDataType *array, int leftIndex, int rightIndex )
|
|
{
|
|
// create StateDataType temp to store swapped element
|
|
StateDataType storeElement;
|
|
// use deepCopy to copy out swapped element
|
|
deepCopy(&storeElement, array[leftIndex]);
|
|
// use deepCopy to move the other element,
|
|
deepCopy(&array[leftIndex], array[rightIndex]);
|
|
// use deepCopy to copy the temp element to the other element
|
|
deepCopy(&array[rightIndex], storeElement);
|
|
// updated the array
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: uploadStateData
|
|
Process: uploads data from given file to state data array,
|
|
ignores first (title) line in .csv file,
|
|
then captures comma-delimited state name, population, growth,
|
|
and political majority data on each row,
|
|
returns number of items found;
|
|
stops uploading process if array is full
|
|
Function input/parameters: capacity (int) and file name (const char *)
|
|
Function output/parameters: updated array with uploaded values (StateDataType *)
|
|
Function output/returned: number of items uploaded (int)
|
|
Device input/HD: data uploaded from text file as specified
|
|
Device output/---: none
|
|
Dependencies: as needed
|
|
*/
|
|
int uploadStateData( StateDataType *StateDataArray,
|
|
int capacity, const char *fileName )
|
|
{
|
|
// setup a counter and other variables
|
|
int stateCount = 0;
|
|
StateDataType stateUpload;
|
|
bool fileOpenCheck;
|
|
char currentString[STD_STR_LEN];
|
|
// int populationUpload;
|
|
// double growthUpload;
|
|
// char majorityUpload;
|
|
setEmptyElementData(&stateUpload);
|
|
// open file
|
|
fileOpenCheck = openInputFile(fileName);
|
|
if(fileOpenCheck)
|
|
{
|
|
// read in the four strings/starting line
|
|
// (use readStringToLineEndFromFile)
|
|
readStringToLineEndFromFile(currentString);
|
|
while(!checkForEndOfInputFile())
|
|
{
|
|
// repeat these steps: (use readStringToDelimiterFromFile)
|
|
// read in the state name, store
|
|
readStringToDelimiterFromFile(COMMA, currentString);
|
|
strcpy(stateUpload.name, currentString);
|
|
// read in the population, store (cast from string to int)
|
|
stateUpload.population = readIntegerFromFile();
|
|
readCharacterFromFile();
|
|
// read in the growth, store (cast from string to double)
|
|
stateUpload.growth = readDoubleFromFile();
|
|
// read in the majority, store
|
|
readCharacterFromFile();
|
|
stateUpload.majority = readCharacterFromFile();
|
|
// use the addElementFromElement function to add the data to array
|
|
addElementFromElement(StateDataArray, &stateCount,
|
|
capacity, stateUpload);
|
|
// do until end of the file is reached.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// error out
|
|
printf("\nThe file you referenced does not exist.\n");
|
|
}
|
|
// return counter
|
|
return stateCount;
|
|
} |