CS249-Projects/PA02-0913/StateUtilities.c
cdez 1169a2607e Complete PA02
+- PA02_Main
+- PA02_Main.c
+- StateUtilities.c
++ outRelease (precompiled for UNIX systems)
2023-09-12 23:06:01 -07:00

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