#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "Strings.h"
Strings::Strings()
{
theString = new char [1];
theString [0] = '\0';
}
Strings::Strings (char character)
{
theString = new char [2];
theString [0] = character;
theString [1] = '\0';
}
Strings::Strings (const char* string)
{
if (string != (char*)0)
{
theString = new char [strlen (string) + 1];
strcpy (theString, string);
}
else
{
theString = new char [1];
theString [0] = '\0';
}
}
Strings::Strings (const Strings& string)
{
theString = new char [strlen (string.theString) + 1];
strcpy (theString, string.theString);
}
Strings::~Strings()
{
delete [] theString;
}
int Strings::beginsWith (const char* string) const
{
int result;
if (string == (char*)0)
result = 0;
else
result = !(strncmp (theString, string, strlen(string)));
return result;
}
int Strings::checkMatch (char* text, char* pattern) const
{
// the following code was originally developed by Rich Salz.
// the following code was modified by Lars Mathiesen.
// the following code was modified by D J Supel
int last, matched, reverses;
char *t, *p;
t = text;
p = pattern;
for ( ; *p; t++, p++)
{
if (*t == '\0' && *p != '*')
return 0;
switch (*p)
{
case '\\':
/* Literal match with following character. */
p++;
/* FALLTHROUGH */
default:
if (*t != *p)
return 0;
continue;
case '?':
/* Match anything. */
continue;
case '*':
while (*++p == '*')
/* Consecutive stars act just like one. */
continue;
if (*p == '\0')
/* Trailing star matches everything. */
return 1;
while (*t)
if ((matched = checkMatch(t++, p)) != 0)
return matched;
return 0;
case '[':
reverses = p[1] == 1 ? 1 : 0;
if (reverses)
/* Inverted character class. */
p++;
for (last = 0400, matched = 0; *++p && *p != ']'; last = *p)
if (*p == '-' ? *t <= *++p && *t >= last : *t == *p)
matched = 1;
if (matched == reverses)
return 0;
continue;
}
}
return *t == '\0';
}
int Strings::contains (const char c) const
{
for (unsigned int i=0; i<=strlen (theString); i++)
{
if (theString[i] == c)
return 1;
}
return 0;
}
int Strings::contains (const char* string) const
{
return (strstr (theString, string) != 0);
}
int Strings::contains (const Strings& string) const
{
return (strstr (theString, string.theString) != 0);
}
unsigned int Strings::count (const char c) const
{
unsigned int theCount = 0;
for (unsigned int i=0; i<=strlen (theString); i++)
{
if (theString[i] == c)
theCount++;
}
return theCount;
}
int Strings::endsWith (const char* string) const
{
int result;
Strings thisString = *this;
Strings clientString = string;
if (string == (char*)0)
result = 0;
else
{
thisString.reverse();
clientString.reverse();
result = thisString.beginsWith (clientString);
}
return result;
}
int Strings::empty() const
{
Strings emptyString;
return (*this == emptyString);
}
int Strings::isAlphabetic() const
{
if (empty())
return 0;
for (unsigned int i = 0; i<length(); i++)
{
if (isalpha ((int)theString[i]) || isspace ((int)theString[i]))
;
else
return 0;
}
return 1;
}
int Strings::isAlphanumeric() const
{
if (empty())
return 0;
for (unsigned int i = 0; i<length(); i++)
{
if (isalnum ((int)theString[i]) || isspace ((int)theString[i]))
;
else
return 0;
}
return 1;
}
int Strings::isLowercase() const
{
if (empty())
return 0;
for (unsigned int i = 0; i<length(); i++)
{
if (islower ((int)theString[i]) || isspace ((int)theString[i]))
;
else
return 0;
}
return 1;
}
int Strings::isNumeric() const
{
if (empty())
return 0;
for (unsigned int i = 0; i<length(); i++)
{
if (isdigit ((int)theString[i]))
;
else
return 0;
}
return 1;
}
int Strings::isUppercase() const
{
if (empty())
return 0;
for (unsigned int i = 0; i<length(); i++)
{
if (isupper ((int)theString[i]) || isspace ((int)theString[i]))
;
else
return 0;
}
return 1;
}
unsigned int Strings::length() const
{
return strlen (theString);
}
Strings Strings::lowercaseOf() const
{
Strings string (theString);
string.lowercase();
return string;
}
int Strings::matches (const char* pattern) const
{
Strings thePattern = pattern;
return matches (thePattern);
}
int Strings::matches (const Strings& pattern) const
{
// validity check
//
if (pattern.empty())
return 0;
if (pattern.count ('[') != pattern.count (']'))
return 0;
if (pattern.theString[0] == '*' && pattern.theString[1] == '\0')
return 1;
return checkMatch (theString, pattern.theString);
}
int Strings::soundsLike (const char* string) const
{
Strings leftResult, rightResult;
if (string == (char*)0)
return 0;
else
{
leftResult = soundexCodeOf (theString);
rightResult = soundexCodeOf (string);
//cerr << theString << " " << left << " "
// << string << " " << right << endl;
// determine if the soundex code could be determined by checking
// for the empty string
//
if (leftResult.empty() || rightResult.empty())
return 0;
else
return (leftResult == rightResult);
}
}
int Strings::soundsLike (const Strings& string) const
{
return (soundsLike (string.theString));
}
double Strings::toDouble() const
{
return atof (theString);
}
int Strings::toInt() const
{
return atoi (theString);
}
long Strings::toLong() const
{
return atol (theString);
}
Strings Strings::sliceOf (const char delimitor) const
{
char *headMarker;
char *tailMarker;
Strings theToken;
headMarker = theString;
tailMarker = headMarker;
while (tailMarker[0] && (tailMarker[0] != delimitor))
tailMarker++;
// move the token to the return strings
//
while (headMarker != tailMarker)
{
theToken.append (headMarker[0]);
headMarker++;
}
return theToken;
}
Strings Strings::token () const
{
char *headMarker;
char *tailMarker;
Strings theToken;
headMarker = theString;
// skip over the preceeding spaces and set a pointer
//
while (headMarker[0] && isspace (headMarker[0]))
headMarker++;
// skip over non-blank characters and set another pointer
//
tailMarker = headMarker;
while (tailMarker[0] && !isspace (tailMarker[0]))
tailMarker++;
// move the token to the return strings
//
while (headMarker != tailMarker)
{
theToken.append (headMarker[0]);
headMarker++;
}
return theToken;
}
Strings Strings::token (const char delimitor) const
{
char *headMarker;
char *tailMarker;
Strings theToken;
headMarker = theString;
// skip over the preceeding spaces
//
while (headMarker[0] && isspace (headMarker[0]))
headMarker++;
// skip over non-delimitor characters and set another pointer
//
tailMarker = headMarker;
while (tailMarker[0] && (tailMarker[0] != delimitor))
tailMarker++;
// move the token to the return strings
//
while (headMarker != tailMarker)
{
theToken.append (headMarker[0]);
headMarker++;
}
return theToken;
}
Strings Strings::uppercaseOf() const
{
Strings string (theString);
string.uppercase();
return string;
}
void Strings::append (char character)
{
char *ctemp;
char *temp;
temp = new char [strlen (theString) + 1];
strcpy (temp, theString);
ctemp = new char [2];
ctemp [0] = character;
ctemp [1] = '\0';
delete [] theString;
theString = new char [strlen (temp) + strlen (ctemp) + 1];
strcpy (theString, temp);
strcat (theString, ctemp);
delete [] ctemp;
delete [] temp;
}
void Strings::append (const char* string)
{
if (string != (char*)0)
{
char* temp;
temp = new char [strlen (theString) + 1];
strcpy (temp, theString);
delete [] theString;
theString = new char [strlen (temp) + strlen (string) + 1];
strcpy (theString, temp);
strcat (theString, string);
delete [] temp;
}
}
void Strings::append (const Strings& string)
{
char* temp;
temp = new char [strlen (theString) + 1];
strcpy (temp, theString);
if (this != &string)
{
delete [] theString;
theString = new char [strlen (temp) + strlen (string.theString) + 1];
strcpy (theString, temp);
strcat (theString, string.theString);
}
else
append (temp);
delete [] temp;
}
void Strings::append (const int integer)
{
char number[20];
sprintf (number, "%d", integer);
append (number);
}
void Strings::clear()
{
delete [] theString;
theString = new char [1];
theString [0] = '\0';
}
void Strings::erase()
{
clear();
}
void Strings::lowercase()
{
for (unsigned int i=0; i<=strlen (theString); i++)
theString[i] = tolower ((theString[i]));
}
void Strings::prepend (char character)
{
char *ctemp;
char *temp;
temp = new char [strlen (theString) + 1];
strcpy (temp, theString);
ctemp = new char [2];
ctemp [0] = character;
ctemp [1] = '\0';
delete [] theString;
theString = new char [strlen (temp) + strlen (ctemp) + 1];
strcpy (theString, ctemp);
strcat (theString, temp);
delete [] ctemp;
delete [] temp;
}
void Strings::prepend (const char* string)
{
if (string != (char*)0)
{
char* temp;
temp = new char [strlen (theString) + 1];
strcpy (temp, theString);
delete [] theString;
theString = new char [strlen (temp) + strlen (string) + 1];
strcpy (theString, string);
strcat (theString, temp);
delete [] temp;
}
}
void Strings::prepend (const Strings& string)
{
char* temp;
temp = new char [strlen (theString) + 1];
strcpy (temp, theString);
if (this != &string)
{
delete [] theString;
theString = new char [strlen (temp) + strlen (string.theString) + 1];
strcpy (theString, string.theString);
strcat (theString, temp);
}
else
prepend (temp);
delete [] temp;
}
void Strings::prepend (const int integer)
{
char number[20];
sprintf (number, "%d", integer);
prepend (number);
}
void Strings::remove (const char c)
{
char *newString;
char *ptr = theString;
newString = new char [strlen (theString) + 1];
newString[0] = '\0';
for (unsigned int i=0; i<(strlen(theString)); i++)
{
if (theString[i] != c)
strncat (newString, ptr, 1);
ptr++;
}
delete[] theString;
theString = newString;
}
void Strings::replace (const char oldChar, const char newChar)
{
for (unsigned int i=0; i<=strlen (theString); i++)
{
if (theString[i] == oldChar)
theString[i] = newChar;
}
}
void Strings::replace (const char c, const char* string)
{
Strings result, token;
if (contains (c)) // dont do anything if you dont have to
{
while (!empty())
{
if (contains (c))
{
slice (token, c, 1);
result.append (token);
result.append (string);
}
else
{
slice (token, c, 1);
result.append (token);
}
}
*this = result;
}
}
void Strings::replace (const char c, const Strings& string)
{
replace (c, string.theString);
}
void Strings::reverse()
{
char c;
for (unsigned int i=0, j=length()-1; i<length()/2; i++, j--)
{
c = theString[i];
theString[i] = theString[j];
theString[j] = c;
}
}
void Strings::slice (unsigned int num, const Directions direction)
{
switch (direction)
{
case left:
sliceLeft (num);
break;
case right:
sliceRight (num);
break;
case leftAndRight:
sliceLeft (num);
sliceRight (num);
break;
default:
break;
}
}
void Strings::slice (
Strings& string, const char delimitor, int removeDelimitor)
{
string = sliceOf (delimitor);
sliceLeft (string.length());
if (removeDelimitor)
sliceLeft (1);
}
void Strings::sliceLeft (Strings& string, unsigned int num)
{
char *newString;
unsigned int i;
newString = new char [strlen (theString) + 1];
strcpy (newString, theString);
for (i=0; newString[i] && i!=num; i++)
;
newString[i] = '\0';
delete[] string.theString;
string.theString = newString;
sliceLeft (num);
}
void Strings::sliceLeft (unsigned int num)
{
char *marker;
marker = theString;
for (unsigned int i = 0; i < num; i++)
{
if (theString[i] == '\0')
{
clear();
return;
}
marker++;
}
if (marker != theString)
{
char *newString;
newString = new char [strlen (marker) + 1];
strcpy (newString, marker);
delete [] theString;
theString = newString;
}
}
void Strings::sliceRight (unsigned int num)
{
int i = 0;
unsigned int j = 0;
i = strlen (theString) - 1;
if (i > 0)
while ((i >= 0) && num != j++)
theString[i--] = '\0';
}
void Strings::sliceToken (const unsigned int tokensToSlice)
{
Strings token;
for (unsigned int i=0; i<tokensToSlice; i++)
sliceToken (token);
}
void Strings::sliceToken (const char delimitor, int removeDelimitor)
{
Strings token;
sliceToken (token, delimitor, removeDelimitor);
}
void Strings::sliceToken (Strings& theToken)
{
trimLeft();
theToken = token();
sliceLeft (theToken.length());
trimLeft();
}
void Strings::sliceToken (
Strings& theToken, const char delimitor, int removeDelimitor)
{
trimLeft();
theToken = token (delimitor);
sliceLeft (theToken.length());
theToken.trimRight();
if (removeDelimitor)
{
sliceLeft (1);
trimLeft();
}
}
Strings Strings::soundexCodeOf (const char* string) const
{
// The Soundex code is an indexing system which translates names into
// a 4 digit code consisting of 1 letter and 3 numbers. The advantage
// of Soundex is its ability to group names by sound rather than the
// exact spelling.
//
// Soundex Rules
//
// 1. All Soundex codes have 4 alphanumeric characters [no more, no less]
// o 1 Letter
// o 3 Digits
// 2. The Letter of the name is the first character of the Soundex code.
// 3. The 3 digits are defined sequentially from the name using the Soundex
// Key below.
// o Adjacent letters in the name which belong to the same Soundex Key
// code number are assigned a single digit.
// o If the end of the name is reached prior to filling 3 digits, use
// zeroes to complete the code.
// o All codes have only 4 characters, even if the name is long enough
// to yield more.
//
int value, previous;
Strings code;
// error checking for null pointers and strings of length zero
//
if (string == (char*)0)
return code;
if (!isalpha (string[0]))
return code;
code.append (string[0]);
code.uppercase();
value = 0;
for (unsigned int i = 1; string[i]!= '\0' && (code.length() < 4); i++)
{
previous = value;
value = soundexNumericOf (string[i]);
if ((value != 0) && (value != previous))
code.append (value);
}
while (code.length() < 4)
code.append ('0');
return code;
}
int Strings::soundexNumericOf (const char c) const
{
// The Soundex Key
//
// 1 B P F V
// 2 C S K G J Q X Z
// 3 D T
// 4 L
// 5 M N
// 6 R
// no code A E H I O U Y W
//
int result = 0;
char temp = toupper (c);
switch (temp)
{
case 'B':
case 'P':
case 'F':
case 'V':
result = 1;
break;
case 'C':
case 'S':
case 'K':
case 'G':
case 'J':
case 'Q':
case 'X':
case 'Z':
result = 2;
break;
case 'D':
case 'T':
result = 3;
break;
case 'L':
result = 4;
break;
case 'M':
case 'N':
result = 5;
break;
case 'R':
result = 6;
break;
default:
break;
}
return result;
}
void Strings::swap (Strings& string)
{
Strings temp;
temp = *this;
*this = string;
string = temp;
}
void Strings::trim (const Directions direction)
{
switch (direction)
{
case left:
trimLeft();
break;
case right:
trimRight();
break;
case leftAndRight:
trimLeft();
trimRight();
break;
default:
break;
}
}
void Strings::trimLeft()
{
char *marker;
marker = theString;
while (isspace (marker[0]))
marker++;
if (marker != theString)
{
char *newString;
newString = new char [strlen (marker) + 1];
strcpy (newString, marker);
delete [] theString;
theString = newString;
}
}
void Strings::trimRight()
{
int i;
i = strlen (theString) - 1;
if (i > 0)
while ((i >= 0) && isspace (theString[i]))
theString[i--] = '\0';
}
void Strings::trim (const char c, const Directions direction)
{
switch (direction)
{
case left:
trimLeft (c);
break;
case right:
trimRight (c);
break;
case leftAndRight:
trimLeft (c);
trimRight (c);
break;
default:
break;
}
}
void Strings::trimLeft (const char c)
{
char *marker;
marker = theString;
while (c == marker[0])
marker++;
if (marker != theString)
{
char *newString;
newString = new char [strlen (marker) + 1];
strcpy (newString, marker);
delete [] theString;
theString = newString;
}
}
void Strings::trimRight (const char c)
{
int i;
i = strlen (theString) - 1;
if (i > 0)
while ((i >= 0) && c == theString[i])
theString[i--] = '\0';
}
void Strings::uppercase()
{
for (unsigned int i=0; i<=strlen (theString); i++)
theString[i] = toupper (theString[i]);
}
Strings::operator const char*() const
{
return theString;
}
ostream& operator << (ostream& outputStream, const Strings& string)
{
return outputStream << string.theString;
}
const Strings& Strings::operator = (char character)
{
delete [] theString;
theString = new char [2];
theString [0] = character;
theString [1] = '\0';
return *this;
}
const Strings& Strings::operator = (const char* string)
{
delete [] theString;
if (string != (char*)0)
{
theString = new char [strlen (string) + 1];
strcpy (theString, string);
}
else
{
theString = new char [1];
theString [0] = '\0';
}
return *this;
}
const Strings& Strings::operator = (const Strings& string)
{
if (this != &string)
{
delete [] theString;
theString = new char [strlen (string.theString) + 1];
strcpy (theString, string.theString);
}
return *this;
}
Strings operator + (const Strings& string1, const Strings& string2)
{
Strings temp;
temp = string1;
temp.append (string2);
return temp;
}
Strings operator + (const Strings& string, const char* s)
{
Strings temp;
temp = string;
temp.append (s);
return temp;
}
Strings operator + (const char* s, const Strings& string)
{
Strings temp;
temp = s;
temp.append (string);
return temp;
}
Strings operator + (const Strings& string, const char character)
{
Strings temp;
temp = string;
temp.append (character);
return temp;
}
Strings operator + (const char character, const Strings& string)
{
Strings temp;
temp = character;
temp.append (string);
return temp;
}
Strings operator + (const Strings& string, const int number)
{
Strings temp;
temp = string;
temp.append (number);
return temp;
}
Strings operator + (const int number, const Strings& string)
{
Strings temp;
temp.append (number);
temp.append (string);
return temp;
}
const Strings& Strings::operator += (char character)
{
append (character);
return *this;
}
const Strings& Strings::operator += (const char* string)
{
append (string);
return *this;
}
const Strings& Strings::operator += (const Strings& string)
{
append (string);
return *this;
}
const Strings& Strings::operator += (const int number)
{
append (number);
return *this;
}
int Strings::operator == (const Strings& string) const
{
return (strcmp (theString, string.theString) == 0);
}
int Strings::operator == (const char* string) const
{
return (strcmp (theString, string) == 0);
}
int Strings::operator != (const Strings& string) const
{
return !(strcmp (theString, string.theString) == 0);
}
int Strings::operator != (const char* string) const
{
return !(strcmp (theString, string) == 0);
}
int Strings::operator < (const Strings& string) const
{
return (strcmp (theString, string.theString) < 0);
}
int Strings::operator < (const char* string) const
{
return (strcmp (theString, string) < 0);
}
int Strings::operator > (const Strings& string) const
{
return (strcmp (theString, string.theString) > 0);
}
int Strings::operator > (const char* string) const
{
return (strcmp (theString, string) > 0);
}
int Strings::operator <= (const Strings& string) const
{
return (strcmp (theString, string.theString) <= 0);
}
int Strings::operator <= (const char* string) const
{
return (strcmp (theString, string) <= 0);
}
int Strings::operator >= (const Strings& string) const
{
return (strcmp (theString, string.theString) >= 0);
}
int Strings::operator >= (const char* string) const
{
return (strcmp (theString, string) >= 0);
}
const char& Strings::operator [] (const unsigned int index) const
{
if (index > length())
return theString[length()];
else
return theString[index];
}
// Copyright (c) 1995-1997 D J Supel and ISX Corporation
syntax highlighted by Code2HTML, v. 0.9.1