// header files #include "StringUtils.h" // global constants const int SUBSTRING_NOT_FOUND = 0; // list of utils: // string length // getStringLength // string copy // copyString // string concatenate // catString // string compare (<, >, =) // compareString // string substring get // getSubString // string substring find // findSubString // string set to lower // toLowerCase // string get to delimiter // stringDelimiter // string get to end of line // stringEOL // function implementations /* Name: catString Process: concatenates two strings Function input/parameters: c-style string (char *) Function output/parameters: c-style string (char *) Function output/returned: NONE Device input/---: NONE Device output/---: NONE Dependencies: malloc, free, getStringLength */ void catString(char *outString, const char *inString) { // initialize variables // set dest index int destIndex = getStringLength(outString); // set source str length int sourceStrLen = getStringLength(inString); // create temp string pointer char *tempString; int sourceIndex = 0; // copy source string in case of aliasing tempString = (char *)malloc(sizeof(char) * sourceStrLen); copyString(tempString, inString); // loop to end of source string while(tempString[sourceIndex] != NULL_CHAR) { // assign characters to end of destination string outString[destIndex] = inString[sourceIndex]; // update indices destIndex = destIndex + 1; sourceIndex = sourceIndex + 1; } // end loop to end of source string // set temporary end of destination string outString[destIndex] = NULL_CHAR; // release memory used for temp string free(tempString); // no return, void. } /* Name: compareString Process: compares two strings as follows: - if left string is alphabetically greater than the right string, returns value greater than zero - if left string is alphabetically less than the right string, returns value less than zero - if strings are alphabetically equal but one is longer, longer one is greater - otherwise, returns zero Function input/parameters: c-style strings (char *) [first and second/left&right] Function output/parameters: NONE Function output/returned: results as specfifed above (int) Device input/---: NONE Device output/---: NONE Dependencies: getStringLength */ int compareString(const char *firstString, const char *secondString) { // initialize variables int diff, index = 0; // loop to end of string (within bounds) while(firstString[index] != NULL_CHAR && secondString[index] != NULL_CHAR) { // get diff of characters diff = firstString[index] - secondString[index]; // check diff of characters if(diff != 0) { // return diff return diff; } // increment index index = index + 1; } // end loop to end of string // return difference in length of strings, if needed return getStringLength(firstString) - getStringLength(secondString); } /* Name: copyString Process: copies string into new string variable, overwrites destination. Function input/parameters: c-style string (char *) Function output/parameters: c-style string (char *) Function output/returned: NONE Device input/---: NONE Device output/---: NONE Dependencies: getStringLength */ void copyString(char *outString, const char *inString) { // initialize variables int index = 0; // check to see if outString is not the same as inString. if(outString != inString) { // loop to end of inString while(inString[index] != NULL_CHAR) { // assign characters to end of outString outString[index] = inString[index]; // increment index index = index + 1; } // end loop to end of inString // set end of the outString outString[index] = NULL_CHAR; } // no return, void. } /* Name: findSubString Process: linear search for given substring within another string Function input/parameters: c-style test string (char *), c-style source string (char *) Function output/parameters: NONE Function output/returned: index of found substring, or SUBSTRING_NOT_FOUND constant if string not found Device input/---: NONE Device output/---: NONE Dependencies: getStringLength */ int findSubString(const char *testStr, const char *searchSubStr) { // initialize variables // initialize test string length int testStrLength = getStringLength(testStr); // initialize master index (location of substring start point) int masterIndex = 0; int searchIndex, internalIndex; // loop across testStr while(masterIndex < testStrLength) { // set internal loop index to current test string index internalIndex = masterIndex; // set internal search index to zero searchIndex = 0; // loop to end of testStr // while testStr/searchSubStr characters are the same while(internalIndex <= testStrLength && testStr[internalIndex] == searchSubStr[searchIndex]) { // increment testStr and substring indices internalIndex = internalIndex + 1; searchIndex = searchIndex + 1; // check for end of substring (search complete) if(searchSubStr[searchIndex] == NULL_CHAR) { // return beginning location of substring return masterIndex; } } // end while testStr/searchSubStr characters are the same // increment current location starting index masterIndex = masterIndex + 1; } // end loop across testStr // return SUBSTRING_NOT_FOUND return SUBSTRING_NOT_FOUND; } /* Name: getStringConstrained Process: captures a string from the file stream with various constraints Function input/parameters: input stream (FILE *), clears leading non printable (bool), clears leading space (bool), stops at non printable (bool), stops at specified delimiter (char) will consume the delimiter. Function output/parameters: c-style string (char *) Function output/returned: success of operation (bool) Device input/---: NONE Device output/---: NONE Dependencies: fgetc */ bool getStringConstrained(FILE *inStream, bool clearLeadingNonPrintable, bool clearLeadingSpace, bool stopAtNonPrintable, char delimiter, char *capString) { // initialize variables int intChar = -1, index = 0; // initialize output string capString[index] = NULL_CHAR; // capture first value in stream using fgetc intChar = fgetc(inStream); // loop to clear non-printable or space if indicated while((((intChar != -1) && (clearLeadingNonPrintable && (intChar < (int)SPACE))) || (clearLeadingSpace && (intChar == (int)SPACE)))) { // get next character in stream using fgetc intChar = fgetc(inStream); } // end loop to clear non-printable or space if indicated // check for end of file found if(intChar == -1) { // return false (failed) return false; } // loop to get input from file stream while(((intChar != -1 && index < MAX_STR_LEN - 1) && (stopAtNonPrintable && intChar >= (int)SPACE)) || ((!stopAtNonPrintable) && (intChar != (char)delimiter))) { // [continues if not at end of file and max string len not reached ] // [AND continues if not printable flag set and characters printable ] // [OR continues if not printable flag not set ] // [AND continues if specified delimited is not found ] // place character in array element capString[index] = (char)intChar; // increment array index index = index + 1; // set next element to null character capString[index] = NULL_CHAR; // get next character as integer using fgetc intChar = fgetc(inStream); } // end loop to get input from file stream // return success return true; } /* Name: getStringLength Process: gets length of string from start to NULL_CHAR ('\0') Function input/parameters: c-style string (char *) Function output/parameters: NONE Function output/returned: length of string (int) Device input/---: NONE Device output/---: NONE Dependencies: included by standard libraries */ int getStringLength(const char *stringIn) { // define variables int stringLength = 0, currentCharacter = 0; // get user input (not needed) // do calculations while (currentCharacter < STD_STR_LEN && stringIn[currentCharacter] != NULL_CHAR) { // increment string length stringLength = stringLength + 1; // increment currentCharacter currentCharacter = currentCharacter + 1; } // display results (not needed) // return success return stringLength; } /* Name: getStringToDelimiter Process: captures a string from the input stream to a specified delimiter. will consume the delimiter. Function input/parameters: input stream (FILE *), stops at specified character Function output/parameters: c-style string (char *) Function output/returned: success of operation (bool) Device input/---: NONE Device output/---: NONE Dependencies: getStringConstrained */ bool getStringToDelimiter(FILE *inStream, char delimiter, char *capString) { // use getStringConstrained with delimiter to get string return getStringConstrained(inStream, true, true, true, delimiter, capString); } /* Name: getStringToLineEnd Process: captures a string from the input stream to the end of the line Function input/parameters: input file stream (FILE *) Function output/parameters: c-style string (char *) Function output/returned: success of operation (bool) Device input/---: NONE Device output/---: NONE Dependencies: getStringConstrained */ bool getStringToLineEnd(FILE *inStream, char *capString) { // use getStringConstrained with line end character to get string return getStringConstrained(inStream, true, true, true, '\n', capString); } /* Name: getSubString Process: captures sub string within larger string between two inclusive indices. returns empty string if either index is out of range, assumes enough memory in dest string Function input/parameters: c-style string (char *) start and end indices (int) Function output/parameters: c-style destination string (char *) Function output/returned: NONE Device input/---: NONE Device output/---: NONE Dependencies: getStringLength, malloc, copyString, free */ void getSubString(char *destStr, const char *sourceStr, int startIndex, int endIndex) { // initialize variables // set length of source string using getStringLength int sourceStrLen = getStringLength(sourceStr); // initialize the destination index to zero int destIndex = 0; // initialize source index to start index (parameter) int sourceIndex = startIndex; // create pointer for temp string char *tempStr; // check for indices within limits if(startIndex >= 0 && startIndex <= endIndex && endIndex < sourceStrLen) { // create temp string using malloc and copyString tempStr = (char *)malloc(sourceStrLen + 1); copyString(tempStr, sourceStr); // loop across requested substring indices while(sourceIndex <= endIndex) { // assign source character to destination element destStr[destIndex] = tempStr[sourceIndex]; // increment indices destIndex = destIndex + 1; sourceIndex = sourceIndex + 1; // set temporary end of destination string destStr[destIndex] = NULL_CHAR; } // end loop across requested substring indices // free temp string free(tempStr); } // no return, void. } /* Name: strToLowerCase Process: iterates through string, sets any uppercase letter to lowercase equivalent, does not affect any letter with an upper/lower diff. Function input/parameters: c-style source string (char *) Function output/parameters: c-style dest string (char *) Function output/returned: NONE Device input/---: NONE Device output/---: NONE Dependencies: toLowerCase */ void strToLowerCase(char *outString, const char *inString) { // initialize variables // get source string length int sourceStrLen = getStringLength(inString); // create temporary string pointer char *tempStr; int index = 0; // copy source string in case of aliasing using malloc and copyString tempStr = (char *)malloc((sizeof(sourceStrLen + 1))); copyString(tempStr, inString); // loop across source string while(tempStr[index] != NULL_CHAR && index < MAX_STR_LEN) { // set individual character to lowercase as needed, assigning back outString[index] = toLowerCase(tempStr[index]); // update index index = index + 1; // set temporary end of destination string outString[index] = NULL_CHAR; } // end loop across source string // free temporary string free(tempStr); // no return, void. } /* Name: toLowerCase Process: sets character to lowercase letter if uppercase letter, returns character Function input/parameters: character input (char) Function output/parameters: NONE Function output/returned: character output (char) Device input/---: NONE Device output/---: NONE Dependencies: none */ char toLowerCase(char testChar) { // check for uppercase letter if(testChar >= 'A' && testChar <= 'Z') { // return lowercase letter return testChar - 'A' + 'a'; } // otherwise, assume not uppercase letter, return unchanged return testChar; } /* Name: ??? Process: ??? Function input/parameters: ??? Function output/parameters: NONE Function output/returned: ??? Device input/---: NONE Device output/---: NONE Dependencies: included by standard libraries */