507 lines
No EOL
17 KiB
C
507 lines
No EOL
17 KiB
C
// header files
|
|
#include "LLDataEngine.h"
|
|
|
|
/* Data Structures
|
|
typedef struct StateDataStruct
|
|
{
|
|
char name[ STD_STR_LEN ];
|
|
int population;
|
|
double growth;
|
|
char majority;
|
|
struct StateDataStruct *nextPtr;
|
|
} StateDataType;
|
|
|
|
typedef struct StateLLStruct
|
|
{
|
|
StateDataType *headPtr;
|
|
} StateLLType;
|
|
Data Structures */
|
|
|
|
// function implementations
|
|
|
|
/*
|
|
Name: clearDataStructure
|
|
Process: deallocates memory for the linked list data structure
|
|
and encapsulated state data using helper function,
|
|
returns NULL to calling function
|
|
Function input/parameters: pointer to state linked list array (StateLLType *)
|
|
Function output/parameters: none
|
|
Function output/returned: NULL
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: free, clearDataStructureHelper
|
|
*/
|
|
StateLLType *clearDataStructure( StateLLType *llPtr )
|
|
{
|
|
// call clearDataStructureHelper with headPtr
|
|
privateClearDataStructureHelper(llPtr->headPtr);
|
|
// free the headPtr
|
|
free(llPtr);
|
|
// return NULL
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
Name: copyDataList
|
|
Process: deallocates destination linked list nodes if it is not empty,
|
|
then if source list is not empty,
|
|
copies all nodes from source list to destination list,
|
|
if source list is empty, copied list will also be configured as empty
|
|
Function input/parameters: pointer to source state data linked list type
|
|
(const StateDataType *)
|
|
Function output/parameters: pointer to destination state data array type
|
|
(StateLLType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: clearDataStructureHelper, privateCreateNodeFromNode
|
|
*/
|
|
void copyDataList( StateLLType *dest, const StateLLType *src )
|
|
{
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: createDataStructure
|
|
Process: dynamically creates instance of state linked list type
|
|
along with initializing the linked list within
|
|
Function input/parameters: none
|
|
Function output/parameters: none
|
|
Function output/returned: pointer to state linked list type (StateLLType *)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: malloc, sizeof (C keyword)
|
|
*/
|
|
StateLLType *createDataStructure()
|
|
{
|
|
// allocate and create StateLLType using malloc and size of
|
|
StateLLType *dataStruct;
|
|
dataStruct = malloc(sizeof(StateLLType));
|
|
// set the head pointer to null
|
|
dataStruct->headPtr = NULL;
|
|
// return StateLLType
|
|
return dataStruct;
|
|
}
|
|
|
|
/*
|
|
Name: deepCopyData
|
|
Process: copies all members of a StateDataType node into another one
|
|
Function input/parameters: state data type item (const StateDataType *)
|
|
Function output/parameters: pointer to state data item (StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Dependencies: privateCopyString
|
|
Device output/---: none
|
|
*/
|
|
void deepCopyData( StateDataType *dest, const StateDataType *src )
|
|
{
|
|
// *dest.population = src.population (for each piece)
|
|
dest->population = src->population;
|
|
dest->growth = src->growth;
|
|
dest->majority = src->majority;
|
|
// privateCopyString for the string
|
|
// privateCopyString(*dest.name, src.name)
|
|
privateCopyString(dest->name, src->name);
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: displayData
|
|
Process: displays comma-delimited data items in linked list
|
|
if linked list is not empty,
|
|
otherwise displays "Data not found - Display aborted",
|
|
allows for subtitle to be added to "Display Data - "
|
|
Function input/parameters: state linked list type (const StateLLType),
|
|
subtitle (const char *)
|
|
Function output/parameters: none
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/monitor: data displayed as specified
|
|
Dependencies: printf, listIsEmpty
|
|
*/
|
|
void displayData( const StateLLType stateData, const char *subTitle )
|
|
{
|
|
// create a working pointer
|
|
StateDataType *currentPtr = stateData.headPtr;
|
|
// check to see if the list is not empty
|
|
if(!listIsEmpty(stateData))
|
|
{
|
|
printf("Display Data - ");
|
|
printf("%s\n", subTitle);
|
|
// while through the linked list
|
|
// get the data out of the first node
|
|
printf("%s, ", currentPtr->name);
|
|
printf("%d, ", currentPtr->population);
|
|
printf("%f, ", currentPtr->growth);
|
|
printf("%c\n", currentPtr->majority);
|
|
while(currentPtr != NULL)
|
|
{
|
|
// move the pointer
|
|
currentPtr = currentPtr->nextPtr;
|
|
// get the data out of the current node
|
|
printf("%s, ", currentPtr->name);
|
|
printf("%d, ", currentPtr->population);
|
|
printf("%f, ", currentPtr->growth);
|
|
printf("%c\n", currentPtr->majority);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// otherwise, display:
|
|
// print Data Not Found
|
|
printf("Data not found - Display aborted\n");
|
|
}
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: getItemAtIndex
|
|
Process: checks for index within bounds,
|
|
acquires and returns the value as a parameter,
|
|
and returns true,
|
|
otherwise sets data in parameter to empty and returns false
|
|
Function input/parameters: state array type (const StateLLType),
|
|
list index (int)
|
|
Function output/parameters: value if found,
|
|
otherwise, value set to empty (StateDataType *)
|
|
Function output/returned: Boolean result of operation (bool)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: deepCopyData, setItemToEmpty
|
|
*/
|
|
bool getItemAtIndex( StateDataType *returnVal,
|
|
const StateLLType stateData, int listIndex )
|
|
{
|
|
int llIncrementer = 0;
|
|
StateDataType *currentPtr = stateData.headPtr;
|
|
// while through linked list
|
|
while(!listIsEmpty(stateData) && currentPtr != NULL)
|
|
{
|
|
// look for listIndex
|
|
if(listIndex == llIncrementer)
|
|
{
|
|
// if found, return true, copy data into return
|
|
deepCopyData(returnVal, currentPtr);
|
|
return true;
|
|
}
|
|
llIncrementer = llIncrementer + 1;
|
|
}
|
|
// since not found, return empty value in returnVal.
|
|
setItemToEmpty(returnVal);
|
|
// return false since not found, or not within bounds.
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: getListSize
|
|
Process: calculates the linked list size
|
|
Function input/parameters: state array type (const StateLLType)
|
|
Function output/parameters: none
|
|
Function output/returned: size of the list (int)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: none
|
|
*/
|
|
int getListSize( const StateLLType stateData )
|
|
{
|
|
int listCounter = 0;
|
|
StateDataType *currentPtr = stateData.headPtr;
|
|
// check to see if the headPtr
|
|
// while through the linked list. count up if next not null.
|
|
while(currentPtr != NULL)
|
|
{
|
|
// listCounter increment
|
|
listCounter = listCounter + 1;
|
|
// move the pointer
|
|
currentPtr = currentPtr->nextPtr;
|
|
}
|
|
// return listCounter
|
|
return listCounter;
|
|
}
|
|
|
|
/*
|
|
Name: insertItemAtIndex
|
|
Process: checks for index in bounds, inserts item at index, returns true,
|
|
if index not in bounds, returns false,
|
|
must also insert item at index = size to all for appending data
|
|
Function input/parameters: pointer to state array type (StateLLType *),
|
|
StateDataType item to insert (const StateDataType),
|
|
index for insertion (int)
|
|
Function output/parameters: updated pointer to state array type
|
|
(StateLLType *)
|
|
Function output/returned: Boolean result of specified process (bool)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: privateCreateNodeFromNode
|
|
*/
|
|
bool insertItemAtIndex( StateLLType *stateData,
|
|
StateDataType toBeInserted, int insertIndex )
|
|
{
|
|
int llIncrementer = 0;
|
|
StateDataType *currentPtr = stateData->headPtr;
|
|
StateDataType *insertedNode;
|
|
// while through linked list
|
|
while(!listIsEmpty(*stateData) && currentPtr != NULL)
|
|
{
|
|
// checks within middle of list
|
|
if(insertIndex == llIncrementer)
|
|
{
|
|
// if found, return true, insert data
|
|
// create node given toBeInserted
|
|
insertedNode = privateCreateNodeFromNode(toBeInserted);
|
|
// move the node's nextPtr to currentPtr->nextPtr
|
|
currentPtr->nextPtr = insertedNode->nextPtr;
|
|
// move the currentPtr's nextPtr to the node
|
|
currentPtr = insertedNode;
|
|
return true;
|
|
}
|
|
llIncrementer = llIncrementer + 1;
|
|
}
|
|
// need a check for beginning of list
|
|
if(insertIndex == 0)
|
|
{
|
|
if(stateData->headPtr == NULL)
|
|
{
|
|
// if at beginning of list, but no more data
|
|
// create node given toBeInserted
|
|
insertedNode = privateCreateNodeFromNode(toBeInserted);
|
|
// move the headPtr to node
|
|
stateData->headPtr = insertedNode;
|
|
return true;
|
|
}
|
|
// if at beginning of list, if more data in list
|
|
// create node given toBeInserted
|
|
insertedNode = privateCreateNodeFromNode(toBeInserted);
|
|
// need to point the headPtr->nextPtr to the node's nextPtr
|
|
stateData->headPtr->nextPtr = insertedNode->nextPtr;
|
|
// move the headPtr to node
|
|
stateData->headPtr = insertedNode;
|
|
return true;
|
|
}
|
|
// put the end of list check out here?
|
|
if(insertIndex == getListSize(*stateData))
|
|
{
|
|
// if found, return true, append data
|
|
// create node given toBeInserted
|
|
insertedNode = privateCreateNodeFromNode(toBeInserted);
|
|
// move the node's nextPtr to NULL
|
|
insertedNode->nextPtr = NULL;
|
|
// move the currentPtr's nextPtr to the node
|
|
currentPtr = insertedNode;
|
|
return true;
|
|
}
|
|
// return false since not inserted, or not within bounds.
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: listIsEmpty
|
|
Process: returns true if list is empty, false otherwise
|
|
Function input/parameters: state linked list type (const StateLLType)
|
|
Function output/parameters: none
|
|
Function output/returned: Boolean result of test as specified (bool)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: none
|
|
*/
|
|
bool listIsEmpty( const StateLLType array )
|
|
{
|
|
// return the check of headPtr == null
|
|
return array.headPtr == NULL;
|
|
}
|
|
|
|
/*
|
|
Name: privateClearDataStructureHelper
|
|
Process: recursively iterates through linked list,
|
|
removing nodes from bottom to top
|
|
Function input/parameters: pointer to state data linked list (StateDataType *)
|
|
Function output/parameters: none
|
|
Function output/returned: NULL
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: free, clearDataStructureHelper (recursively)
|
|
*/
|
|
StateDataType *privateClearDataStructureHelper( StateDataType *nodePtr )
|
|
{
|
|
// check if node's nextPtr not null
|
|
if(nodePtr->nextPtr != NULL)
|
|
{
|
|
// if it is not null, call the next recursion.
|
|
nodePtr->nextPtr = privateClearDataStructureHelper(nodePtr->nextPtr);
|
|
}
|
|
// free the node using free
|
|
free(nodePtr);
|
|
// return NULL
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
Name: privateCreateNodeFromData
|
|
Process: creates linked list node provided member data
|
|
Function input/parameters: name (const char *), population (int),
|
|
growth (double), majority (char)
|
|
Function output/parameters: none
|
|
Function output/returned: pointer to created node (StateDataType *)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: malloc, privateCopyString, keyword sizeof
|
|
*/
|
|
StateDataType *privateCreateNodeFromData( const char *inName,
|
|
int inPop, double inGrowth,
|
|
char inMajority )
|
|
{
|
|
// allocate node memory using malloc and size of
|
|
StateDataType *workingNode;
|
|
workingNode = malloc(sizeof(StateDataType));
|
|
// copy string into node
|
|
privateCopyString(workingNode->name, inName);
|
|
// copy other data pieces into node
|
|
workingNode->population = inPop;
|
|
workingNode->growth = inGrowth;
|
|
workingNode->majority = inMajority;
|
|
// set nextPtr to null
|
|
workingNode->nextPtr = NULL;
|
|
// return node
|
|
return workingNode;
|
|
}
|
|
|
|
/*
|
|
Name: privateCreateNodeFromNode
|
|
Process: creates linked list node provided another node
|
|
Function input/parameters: other node (const StateDataType)
|
|
Function output/parameters: none
|
|
Function output/returned: pointer to created node (StateDataType *)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: one line of code - privateCreateNodeFromData
|
|
*/
|
|
StateDataType *privateCreateNodeFromNode( const StateDataType source )
|
|
{
|
|
// return the node
|
|
return privateCreateNodeFromData(source.name, source.population,
|
|
source.growth, source.majority);
|
|
}
|
|
|
|
/*
|
|
Name: privateCopyString
|
|
Process: copies string character for character up to NULL_CHAR of source string
|
|
Function input/parameters: source string to be copied (const char *)
|
|
Function output/parameters: destination string (char *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: none
|
|
*/
|
|
void privateCopyString( char *dest, const char *src )
|
|
{
|
|
int characterCount = 0;
|
|
// use a while loop, check for !NULL_CHAR
|
|
while(src[characterCount] != NULL_CHAR)
|
|
{
|
|
// copy the character accessed into dest string
|
|
dest[characterCount] = src[characterCount];
|
|
// iterate the number of characters
|
|
characterCount = characterCount + 1;
|
|
}
|
|
// add a NULL_CHAR once done, characterCount is in the right place for \0
|
|
dest[characterCount] = NULL_CHAR;
|
|
// no return, void
|
|
}
|
|
|
|
/*
|
|
Name: removeItemAtIndex
|
|
Process: removes node from linked list at index,
|
|
returns true if found, false otherwise
|
|
Function input/parameters: pointer to state linked list type (StateLLType *),
|
|
index to remove (int)
|
|
Function output/parameters: pointer to updated state linked list type
|
|
(StateLLType *),
|
|
pointer to removed item (StateDataType *)
|
|
Function output/returned: Boolean result of removal operation (bool)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: deepCopyData, free, setItemToEmpty
|
|
*/
|
|
bool removeItemAtIndex( StateLLType *stateData,
|
|
StateDataType *removedItem, int removeIndex )
|
|
{
|
|
int llIncrementer = 0;
|
|
StateDataType *currentPtr = stateData->headPtr;
|
|
// while through linked list
|
|
while(!listIsEmpty(*stateData) && currentPtr != NULL)
|
|
{
|
|
// checks within middle of list
|
|
if(removeIndex == llIncrementer)
|
|
{
|
|
// if found, return true, insert data
|
|
// copy data out of the list
|
|
deepCopyData(removedItem, currentPtr);
|
|
// move the pointer of currentPtr to the next item
|
|
currentPtr->nextPtr = currentPtr->nextPtr->nextPtr;
|
|
// free the memory of the removed item.
|
|
free(currentPtr->nextPtr);
|
|
return true;
|
|
}
|
|
llIncrementer = llIncrementer + 1;
|
|
}
|
|
// need a check for beginning of list
|
|
if(removeIndex == 0)
|
|
{
|
|
if(stateData->headPtr == NULL)
|
|
{
|
|
// if at beginning of list, but no more data
|
|
// copy data out of the list
|
|
deepCopyData(removedItem, currentPtr);
|
|
// free the memory of the removed item.
|
|
free(currentPtr->nextPtr);
|
|
return true;
|
|
}
|
|
// if at beginning of list, if more data in list
|
|
// copy data out of the list
|
|
deepCopyData(removedItem, currentPtr);
|
|
// move the pointer of currentPtr to the next item
|
|
currentPtr->nextPtr = currentPtr->nextPtr->nextPtr;
|
|
// free the memory of the removed item.
|
|
free(currentPtr->nextPtr);
|
|
return true;
|
|
}
|
|
// put the end of list check out here?
|
|
if(removeIndex == getListSize(*stateData))
|
|
{
|
|
// if found, return true, append data
|
|
// copy data out of the list
|
|
deepCopyData(removedItem, currentPtr);
|
|
// move the pointer of currentPtr to the next item
|
|
currentPtr->nextPtr = currentPtr->nextPtr->nextPtr;
|
|
// free the memory of the removed item.
|
|
free(currentPtr->nextPtr);
|
|
return true;
|
|
}
|
|
setItemToEmpty(removedItem);
|
|
// return false since not inserted, or not within bounds.
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: setItemToEmpty
|
|
Process: sets state data type struct to empty or default values,
|
|
including empty string and majority 'x'
|
|
Function input/parameters: pointer to state data value (StateDataType *)
|
|
Function output/parameters: pointer to updated state data value
|
|
(StateDataType *)
|
|
Function output/returned: none
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: none
|
|
*/
|
|
void setItemToEmpty( StateDataType *data )
|
|
{
|
|
// set the data's name to ""
|
|
data->name[0] = NULL_CHAR;
|
|
// set the data's population and growth to 0
|
|
data->population = 0;
|
|
data->growth = 0.0;
|
|
// set the data's majority to 'x'
|
|
data->majority = 'x';
|
|
// no return, void
|
|
} |