#include "StateUtilities_LogN.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 = 34; // all functions /* Name: addElementFromData Process: adds all individual data values to StateDataType array, must check for resize before adding new element Function input/parameters: pointer to data array type (StateArrayType *), state name (const char *), state population (int), state growth (double), state political majority (char) Function output/parameters: updated data array (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed, including strcpy */ void addElementFromData( StateArrayType *stateArr, const char *stateName, int statePop, double stateGrowth, char politicalMajority ) { // check to see if the size will go over the capacity checkForResize(stateArr); // put in the data to the array // stateArr->array[stateArr.size] = parameter stateArr->array[stateArr->size].population = statePop; stateArr->array[stateArr->size].growth = stateGrowth; stateArr->array[stateArr->size].majority = politicalMajority; // use strcpy(stateArr->array[stateArr.size].name, stateName) strcpy(stateArr->array[stateArr->size].name, stateName); // increment size (stateArr.size = stateArr.size + 1) stateArr->size = stateArr->size + 1; // no return, void } /* Name: addElementFromElement Process: adds data from element to StateDataType array, uses supporting function Function input/parameters: data array type (StateArrayType *) source element (const StateDataType) Function output/parameters: updated data array (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: addElementFromData - function uses one code statement */ void addElementFromElement( StateArrayType *stateArr, const StateDataType state ) { addElementFromData(stateArr, state.name, state.population, state.growth, state.majority); // no return, void } /* Name: checkForResize Process: checks if array needs to be resized, resizes (increases capacity of) array to double capacity and moves data from previous array into new one Function input/parameters: pointer to state array type (StateArrayType *) Function output/parameters: updated pointer to state array type (StateArrayType *) if resize has taken place, otherwise ADT is unchanged Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed, including malloc, free, keyword sizeof */ void checkForResize( StateArrayType *stateArray ) { StateArrayType *biggerStateArray; // do a similiar check to the one that was done in PA02 for size < capacity if(stateArray->size + 1 > stateArray->capacity) { // create bigger array, use createStateArrayType(2x old capacity) biggerStateArray = createStateArrayType(stateArray->capacity * 2); // copy the old array stuff into the new array, use copyArrayType copyArrayType(biggerStateArray, *stateArray); // copy the new array stuff into the old space copyArrayType(stateArray, *biggerStateArray); } // no return, void } /* Name: clearStateArrayType Process: deallocates dynamically allocated array from memory, deallocates dynamically allocated state data type, returns NULL 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 */ StateArrayType *clearStateArrayType( StateArrayType *stateArray ) { // free the array from memory free(&stateArray->array); // free the struct from memory free(stateArray); // return NULL once complete return NULL; } /* Name: copyArrayType Process: copies state data array type from one array type to another Function input/parameters: source array (const StateArrayType) Function output/parameters: pointer to destination array (StateDataType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void copyArrayType( StateArrayType *dest, const StateArrayType src ) { int currentSize; // use a for loop to iterate through source array // (start at zero, go to srcSize) for(currentSize = 0; currentSize < src.size; currentSize++) { // copy each element from the array to the new array. // uses deepCopy to do this. deepCopy(&dest->array[currentSize], src.array[currentSize]); } dest->size = src.size; dest->capacity = src.capacity; // no return, void } /* Name: createStateArrayType Process: dynamically allocates memory for array type, dynamically allocates memory for array, initializes size and capacity Function input/parameters: initial capacity (int) Function output/parameters: none Function output/returned: pointer to newly created array type (StateArrayType *) Device input/---: none Device output/---: none Dependencies: as needed, including function malloc and keyword sizeof */ StateArrayType *createStateArrayType( int initialCapacity ) { StateArrayType *stateArrayCreation; // initialize array type stateArrayCreation = malloc(sizeof(StateArrayType)); stateArrayCreation->size = 0; stateArrayCreation->capacity = initialCapacity; // initialize array stateArrayCreation->array = malloc(sizeof(StateDataType) * initialCapacity); // return stateArrayCreation return stateArrayCreation; } /* 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 type 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 type (const StateArrayType *), 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 StateArrayType arrayType, const char *subTitle ) { int countStates; // iterate through array to size, check if zero. if(arrayType.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 < arrayType.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(arrayType.array[countStates].name, NAME_BLOCK_SIZE, "LEFT"); // print PIPE character printCharacter(PIPE); // print population justified right printIntegerJustified(arrayType.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(arrayType.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(arrayType.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: reverseArray Process: reverses values in array Function input/parameters: pointer to state array type (StateArrayType *) Function output/parameters: none Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void reverseArray( StateArrayType *stateArray ) { // reverse in place? could use swap elements to make this happen. // use a for loop? // no return, void } /* Name: runMerge Process: merges StateArrayType ADT subsets brought in between a low, middle, and high index segment of the StateArrayType ADT, must dynamically create (and release) one internal array must use three array transfer loops Function input/parameters: pointer to state array type (StateArrayType *), low index, middle index, high index (int) Function output/parameters: pointer to updated state array type (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void runMerge( StateArrayType *stateArray, int lowIndex, int middleIndex, int highIndex ) { // no return, void } /* Name: runMergeSortByName Process: sorts StateArrayType ADT using merge sort algorithm, calls helper function with appropriate indices Function input/parameters: pointer to state array type (StateArrayType *) Function output/parameters: pointer to updated state array type (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void runMergeSortByName( StateArrayType *stateArray ) { // no return, void } /* Name: runMergeSortHelper Process: recursively breaks given StateArrayType ADT segments down to smaller segments between lowIndex and highIndex (inclusive), then sorts data using merge operation for segments created Function input/parameters: pointer to state array type (StateArrayType *), low & high inclusive indices (int) Function output/parameters: pointer to updated state array type (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void runMergeSortHelper( StateArrayType *stateArray, int lowIndex, int highIndex ) { // no return, void } /* Name: runPartition Process: partitions StateArrayType ADT must use the first value as the partition value; when this function is complete the partition value is in the correct location in the array; main loop must iterate from left to right Function input/parameters: pointer to state array type (StateArrayType *) Function output/parameters: pointer to updated state array type (StateArrayType *) Function output/returned: partition value index within array Device input/---: none Device output/---: none Dependencies: as needed */ int runPartition( StateArrayType *stateArray, int lowIndex, int highIndex ) { // return zero (temporarily) return 0; } /* Name: runQuickSortByPopulation Process: sorts StateArrayType ADT using quick sort algorithm, calls helper with appropriate indices to implement sort Function input/parameters: pointer to state array type (StateArrayType *) Function output/parameters: pointer to updated state array type (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void runQuickSortByPopulation( StateArrayType *stateArray ) { // no return, void } /* Name: runQuickSortHelper Process: helper function run with parameters that partition arrays on a given (first) element of an array segment, then recursively sort left and right sides of given partition value Function input/parameters: pointer to state array type (StateArrayType *) low & high inclusive indices (int) Function output/parameters: pointer to updated state array type (StateArrayType *) Function output/returned: none Device input/---: none Device output/---: none Dependencies: as needed */ void runQuickSortHelper( StateArrayType *stateArray, int lowIndex, int highIndex ) { // 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 "" element->name[0] = NULL_CHAR; // 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 Log N 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 Log N Sorting"); // print endline printEndline(); // use console io utilities to display 34 '=' 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 true if upload successful, false otherwise Function input/parameters: file name (const char *) Function output/parameters: updated array with uploaded values (StateDataType *) Function output/returned: Boolean result of upload operation Device input/HD: data uploaded from text file as specified Device output/---: none Dependencies: as needed */ bool uploadStateData( StateArrayType *arrayType, const char *fileName ) { // setup a temporary state and other variables StateDataType stateUpload; char currentString[STD_STR_LEN]; // int populationUpload; // double growthUpload; // char majorityUpload; // open file //setEmptyElementData(&stateUpload); if(openInputFile(fileName)) { // 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(arrayType, stateUpload); // do until end of the file is reached. } // return true when completely finished, close file before completion closeInputFile(); return true; } // return false return false; }