Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- using namespace std;
- /*! @class String <iostream>
- * @brief A custom String implementation
- *
- * A custom C++ implementation of a String object for pedagogical purposes.
- * Is efficient for specifying the length of your String and does not depend
- * on the use of a NULL termination.
- *
- * @author Dobromir Stoyanov
- * @version 0.2
- * @date 2018-04-25
- * @invariant String data will always point to NULL or a valid address.
- * @invariant String length will always indicate amount of allocated space.
- */
- class String
- {
- char* data; /*!< The ASCII characters that comprise the String */
- unsigned length; /*!< The number of characters allocated in data */
- public:
- /*!
- * @brief Empty String Constructor.
- * @post String length is set equal to 0.
- */
- String();
- /*!
- * @brief Single-character String Constructor.
- * @param[in] c A char literal.
- * @post String data equals @a c and String length equals 1.
- */
- String(char c);
- /*!
- * @brief char* String Constructor
- * @param[in] c A char* null-terminated string.
- * @post String length equals @code{.cpp}strlen(c)@endcode.
- * @post String data equals @a c allocated values, except the null-terminator.
- */
- String(const char* c);
- /*!
- * @brief Copy String Constructor
- * @param[in] s A String instance.
- * @post This String will be identical to String @a s.
- */
- String(const String& s);
- /*!
- * @brief Default String Destructor
- * @post String data is deleted.
- */
- ~String();
- /*!
- * @brief String length.
- * @return Value in String @c length.
- */
- unsigned len() const;
- /*!
- * @brief String index of @a c.
- * @param[in] c A char literal.
- * @return The index of @a c in String, if exists; -1 otherwise.
- */
- int index(char c) const;
- /*!
- * @brief Converts lowercase alphabetic characters to uppercase.
- * @param[in] first Starting index of String to change case.
- * @param[in] last Ending index of String to change case.
- * @pre @a first is less than or equal to @a last and @a last is less than
- * or equal to String length.
- * @post All lowercase alphabetic characters in String data greater than
- * or equal to @a first, but less than @a last are uppercase.
- * @throw int
- */
- void upcase(unsigned first, unsigned last);
- /*!
- * @brief Converts uppercase alphabetic characters to lowercase.
- * @param[in] first Starting index of String to change case.
- * @param[in] last Ending index of String to change case.
- * @pre @a first is less than or equal to @a last and @a last is less than
- * or equal to String length.
- * @post All uppercase alphabetic characters in String data greater than
- * or equal to @a first, but less than @a last are lowercase.
- * @throw int
- */
- void downcase(unsigned first, unsigned last);
- /*!
- * @brief Toggles lowercase alphabetic characters to uppercase, and vice versa.
- * @param[in] first Starting index of String to change case.
- * @param[in] last Ending index of String to change case.
- * @pre @a first is less than or equal to @a last and @a last is less than
- * or equal to String length.
- * @post All lowercase alphabetic characters in String data greater than
- * or equal to @a first, but less than @a last are uppercase, and
- all uppercase alphabetic characters in String data are lowercase.
- * @throw int
- */
- void togglecase(unsigned first, unsigned last);
- //@{
- /*!
- * @brief Stream operators.
- * @param so A stream object.
- * @param s A String object.
- * @return Stream object containing String content.
- */
- friend std::ostream& operator<< (std::ostream& so, const String& s);
- friend std::istream& operator>> (std::istream& so, String& s);
- //@}
- //@{
- /*!
- * @brief Access String character.
- * @param j Index value in String.
- * @pre @a j is less than String length.
- * @return character at @a j index of String data.
- * @throw int
- */
- char operator[] (unsigned j) const;
- char& operator[] (unsigned j);
- //@}
- /*!
- * @brief Sets String value.
- * @param[in] s A String object.
- * @return A String reference to *this.
- * @post String will be equivalent to @a s.
- */
- String& operator= (const String& s);
- /*!
- * @brief Append to String.
- * @param[in] s A String object.
- * @return A String reference to *this.
- * @post String will equal the concatenation of itself with @a s.
- */
- String& operator+= (const String& s);
- //@{
- /*!
- * @brief String concatenation (addition).
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return Copy of a String object.
- * @post The String will be the concatenation of @a lhs and @a rhs.
- */
- friend String operator+ (const String& lhs, const String& rhs);
- friend String operator+ (const String& lhs, char rhs);
- friend String operator+ (const String& lhs, const char* rhs);
- friend String operator+ (char lhs, const String& rhs);
- friend String operator+ (const char* lhs, const String& rhs);
- //@}
- //@{
- /*!
- * @brief String equality
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return True, if @a lhs and @a rhs have the same length, and each
- * character in their String data are identical in both value
- * and index.
- */
- friend bool operator== (const String& lhs, const String& rhs);
- friend bool operator== (const String& lhs, char rhs);
- friend bool operator== (const String& lhs, const char* rhs);
- friend bool operator== (char lhs, const String& rhs);
- friend bool operator== (const char* lhs, const String& rhs);
- //@}
- //@{
- /*!
- * @brief String inequality: Greater-than.
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return True, if @a lhs is in dictionary order (Capitals-first) to
- * @a rhs when comparing alphabetical characters or @a lhs is
- * greater in ASCII value to @a rhs, in corresponding String
- * data indices.
- */
- friend bool operator> (const String& lhs, const String& rhs);
- friend bool operator> (const String& lhs, char rhs);
- friend bool operator> (const String& lhs, const char* rhs);
- friend bool operator> (char lhs, const String& rhs);
- friend bool operator> (const char* lhs, const String& rhs);
- //@}
- //@{
- /*!
- * @brief String non-equality
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return True, if @a lhs is not equal to @a rhs.
- * @see String::operator==
- */
- friend bool operator!= (const String& lhs, const String& rhs);
- friend bool operator!= (const String& lhs, char rhs);
- friend bool operator!= (const String& lhs, const char* rhs);
- friend bool operator!= (char lhs, const String& rhs);
- friend bool operator!= (const char* lhs, const String& rhs);
- //@}
- //@{
- /*!
- * @brief String inequality: Less-than.
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return True, if @a lhs is neither equal to, nor greater-than @a rhs.
- * @see String::operator==,String::operator>
- */
- friend bool operator< (const String& lhs, const String& rhs);
- friend bool operator< (const String& lhs, char rhs);
- friend bool operator< (const String& lhs, const char* rhs);
- friend bool operator< (char lhs, const String& rhs);
- friend bool operator< (const char* lhs, const String& rhs);
- //@}
- //@{
- /*!
- * @brief String inequality: Less-than or equal
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return True, if @a lhs is not greater-than @a rhs.
- * @see String::operator>
- */
- friend bool operator<= (const String& lhs, const String& rhs);
- friend bool operator<= (const String& lhs, char rhs);
- friend bool operator<= (const String& lhs, const char* rhs);
- friend bool operator<= (char lhs, const String& rhs);
- friend bool operator<= (const char* lhs, const String& rhs);
- //@}
- //@{
- /*!
- * @brief String inequality: Greater-than or equal
- * @param[in] lhs The left-hand operand String or String convertable.
- * @param[in] rhs The right-hand operand String or String convertable.
- * @return True, if @a lhs is greater-than or equal to @a rhs.
- * @see String::operator>,String::operator==
- */
- friend bool operator>= (const String& lhs, const String& rhs);
- friend bool operator>= (const String& lhs, char rhs);
- friend bool operator>= (const String& lhs, const char* rhs);
- friend bool operator>= (char lhs, const String& rhs);
- friend bool operator>= (const char* lhs, const String& rhs);
- //@}
- };
- String::String()
- {
- length = 0;
- data = new char[0];
- }
- String::String(char c)
- {
- length = 1;
- data = new char(c);
- }
- String::String(const char* c)
- {
- if (c)
- {
- unsigned n = 0;
- while (c[n] != '\0') n++;
- length = n;
- data = new char[n];
- for (unsigned j = 0; j < n; j++)
- data[j] = c[j];
- }
- else
- {
- length = 0;
- data = new char[0];
- }
- }
- String::String(const String& s)
- {
- length = s.len();
- data = new char[length];
- for (unsigned j = 0; j < length; j++)
- data[j] = s[j];
- }
- String::~String()
- {
- delete[] data;
- }
- unsigned String::len() const
- {
- return length;
- }
- int String::index(char c) const
- {
- for (unsigned j = 0; j < length; j++)
- if (data[j] == c) return (int)j;
- return -1;
- }
- void String::upcase(unsigned first, unsigned last)
- {
- if ((first >= last) || (last > length)) throw 1;
- for (unsigned j = first; j < last; j++)
- if ('a' <= data[j] && data[j] <= 'z')
- data[j] -= ('a' - 'A');
- }
- void String::downcase(unsigned first, unsigned last)
- {
- if ((first >= last) || (last > length)) throw 1;
- for (unsigned j = first; j < last; j++)
- if ('A' <= data[j] && data[j] <= 'Z')
- data[j] += ('a' - 'A');
- }
- void String::togglecase(unsigned first, unsigned last)
- {
- if ((first >= last) || (last > length)) throw 1;
- for (unsigned j = first; j < last; j++)
- if ('A' <= data[j] && data[j] <= 'Z')
- data[j] += ('a' - 'A');
- else if ('a' <= data[j] && data[j] <= 'z')
- data[j] -= ('a' - 'A');
- }
- std::ostream& operator<< (std::ostream& os, const String& s)
- {
- if (s.len() > 0)
- {
- for (unsigned j = 0; j < s.len(); j++)
- os << s[j];
- }
- else os << "";
- return os;
- }
- std::istream& operator>> (std::istream& is, String& s)
- {
- char* c = new char[1000];
- is >> c;
- s = String(c);
- delete[] c;
- return is;
- }
- char String::operator[] (unsigned j) const
- {
- if (j >= length) throw 1;
- return data[j];
- }
- char& String::operator[] (unsigned j)
- {
- if (j >= length) throw 1;
- return data[j];
- }
- String& String::operator= (const String& s)
- {
- if (this == &s) return *this;
- delete data;
- length = s.len();
- data = new char[length];
- for (unsigned j = 0; j < length; j++)
- data[j] = s[j];
- return *this;
- }
- String& String::operator+= (const String& s)
- {
- unsigned len = length + s.len();
- char* str = new char[len];
- for (unsigned j = 0; j < length; j++)
- str[j] = data[j];
- for (unsigned i = 0; i < s.len(); i++)
- str[length + i] = s[i];
- delete data;
- length = len;
- data = str;
- return *this;
- }
- String operator+ (const String& lhs, const String& rhs)
- {
- return String(lhs) += rhs;
- }
- String operator+ (const String& lhs, char rhs)
- {
- return String(lhs) += String(rhs);
- }
- String operator+ (const String& lhs, const char* rhs)
- {
- return String(lhs) += String(rhs);
- }
- String operator+ (char lhs, const String& rhs)
- {
- return String(lhs) += rhs;
- }
- String operator+ (const char* lhs, const String& rhs)
- {
- return String(lhs) += rhs;
- }
- bool operator== (const String& lhs, const String& rhs)
- {
- if (lhs.len() != rhs.len()) return false;
- unsigned cap = lhs.len();
- unsigned n = 0;
- while ((n < cap) && (lhs[n] == rhs[n])) n++;
- return (n == cap);
- }
- bool operator== (const String& lhs, char rhs)
- {
- return (lhs == String(rhs));
- }
- bool operator== (const String& lhs, const char* rhs)
- {
- return (lhs == String(rhs));
- }
- bool operator== (char lhs, const String& rhs)
- {
- return (String(lhs) == rhs);
- }
- bool operator== (const char* lhs, const String& rhs)
- {
- return (String(lhs) == rhs);
- }
- bool operator> (const String& lhs, const String& rhs)
- {
- unsigned cap = (lhs.len() < rhs.len()) ? lhs.len() : rhs.len();
- unsigned n = 0;
- while ((n < cap) && (lhs[n] == rhs[n])) n++;
- if (n == cap) return (lhs.len() > rhs.len());
- if ((('A' <= lhs[n] && lhs[n] <= 'Z') || ('a' <= lhs[n] && lhs[n] <= 'z')) &&
- (('A' <= rhs[n] && rhs[n] <= 'Z') || ('a' <= rhs[n] && rhs[n] <= 'z')))
- {
- char A = (lhs[n] & ~32);
- char B = (rhs[n] & ~32);
- if (A != B) return (A > B);
- }
- return lhs[n] > rhs[n];
- }
- bool operator> (const String& lhs, char rhs)
- {
- return (lhs > String(rhs));
- }
- bool operator> (const String& lhs, const char* rhs)
- {
- return (lhs > String(rhs));
- }
- bool operator> (char lhs, const String& rhs)
- {
- return (String(lhs) > rhs);
- }
- bool operator> (const char* lhs, const String& rhs)
- {
- return (String(lhs) > rhs);
- }
- bool operator!= (const String& lhs, const String& rhs)
- {
- return !(lhs == rhs);
- }
- bool operator!= (const String& lhs, char rhs)
- {
- return !(lhs == rhs);
- }
- bool operator!= (const String& lhs, const char* rhs)
- {
- return !(lhs == rhs);
- }
- bool operator!= (char lhs, const String& rhs)
- {
- return !(lhs == rhs);
- }
- bool operator!= (const char* lhs, const String& rhs)
- {
- return !(lhs == rhs);
- }
- bool operator< (const String& lhs, const String& rhs)
- {
- return !(lhs == rhs) && !(lhs > rhs);
- }
- bool operator< (const String& lhs, char rhs)
- {
- return !(lhs == rhs) && !(lhs > rhs);
- }
- bool operator< (const String& lhs, const char* rhs)
- {
- return !(lhs == rhs) && !(lhs > rhs);
- }
- bool operator< (char lhs, const String& rhs)
- {
- return !(lhs == rhs) && !(lhs > rhs);
- }
- bool operator< (const char* lhs, const String& rhs)
- {
- return !(lhs == rhs) && !(lhs > rhs);
- }
- bool operator<= (const String& lhs, const String& rhs)
- {
- return !(lhs > rhs);
- }
- bool operator<= (const String& lhs, char rhs)
- {
- return !(lhs > rhs);
- }
- bool operator<= (const String& lhs, const char* rhs)
- {
- return !(lhs > rhs);
- }
- bool operator<= (char lhs, const String& rhs)
- {
- return !(lhs > rhs);
- }
- bool operator<= (const char* lhs, const String& rhs)
- {
- return !(lhs > rhs);
- }
- bool operator>= (const String& lhs, const String& rhs)
- {
- return (lhs == rhs) || (lhs > rhs);
- }
- bool operator>= (const String& lhs, char rhs)
- {
- return (lhs == rhs) || (lhs > rhs);
- }
- bool operator>= (const String& lhs, const char* rhs)
- {
- return (lhs == rhs) || (lhs > rhs);
- }
- bool operator>= (char lhs, const String& rhs)
- {
- return (lhs == rhs) || (lhs > rhs);
- }
- bool operator>= (const char* lhs, const String& rhs)
- {
- return (lhs == rhs) || (lhs > rhs);
- }
- char main_menu()
- {
- char res;
- cout << endl << endl << endl;
- cout << endl << " ~~~ String Simulator ~~~ ";
- cout << endl << endl;
- cout << "(0) Assign values to String s1, s2, and s3" << endl;
- cout << "(1) Toggle Case s1, Upcase s2[0, 4], and Downcase s3[2, 4]" << endl;
- cout << "(2) Copy s2 into s5 and set s2 = s2 + s4" << endl;
- cout << "(3) Find 'c' in s5, -1 if not found." << endl;
- cout << "(4) Add 'fooBlah' to s1" << endl;
- cout << "(5) Add Random character to s4" << endl;
- cout << "(6) Insert String into s5" << endl;
- cout << "(7) Perform Logical Comparisons" << endl;
- cout << "(8) Display Currently Registered Strings" << endl;
- cout << "(9) Exit simulation" << endl << endl << endl;
- cout << "Enter a selection (0-9): ";
- cin >> res;
- return res;
- }
- void DisplayStrings(const String& s1, const String& s2, const String& s3,
- const String& s4, const String& s5)
- {
- cout << endl << "--- Current Registered Strings --- " << endl;
- cout << " Length Content" << endl;
- cout << " String s1: " << s1.len() << " " << s1 << endl;
- cout << " String s2: " << s2.len() << " " << s2 << endl;
- cout << " String s3: " << s3.len() << " " << s3 << endl;
- cout << " String s4: " << s4.len() << " " << s4 << endl;
- cout << " String s5: " << s5.len() << " " << s5 << endl;
- }
- void AssignStrings(String& s1, String& s2, String& s3)
- {
- // Assign s1 (random alphabet)
- unsigned int N = rand() % 10; // Random length
- #define N 6
- char c1[N];
- for (unsigned j = 0; j<N; j++)
- {
- char c = (char)(rand() % 26 + 65); // Random Alphabet
- c1[j] = c;
- }
- // Assign s2 (random name)
- const char* names[10] = { "Alpha", "bob", "Joe", "chris", "Foo",
- "foobar", "crystal", "Bart", "Bob", "Omega" };
- const char* c2 = names[N];
- // Assign s3 (random ASCII)
- char c3[N];
- for (unsigned j = 0; j<N; j++)
- {
- char c = (char)(rand() % 255); // Random ASCII
- c3[j] = c;
- }
- s1 = c1;
- s2 = c2;
- s3 = c3;
- }
- void LogicalTests(const String& s1, const String& s2, const String& s3,
- const String& s4, const String& s5)
- {
- cout << endl << "*** Logical Tests ***" << endl;
- cout << " s1 == s2? " << ((s1 == s2) ? "True" : "False") << endl;
- cout << " s1 != s2? " << ((s1 != s2) ? "True" : "False") << endl;
- cout << " s2 > s5? " << ((s2 > s5) ? "True" : "False") << endl;
- cout << " s4 < s2 " << ((s4 < s2) ? "True" : "False") << endl;
- cout << " s1 <= fooBlah? " << ((s1 <= "fooBlah") ? "True" : "False") << endl;
- cout << " s4 >= C " << ((s4 >= 'C') ? "True" : "False") << endl;
- }
- int main()
- {
- bool isDone = false;
- char choice;
- String s1, s2, s3;
- String s4 = '\0';
- String s5;
- srand(443);
- do
- {
- char c = (char)(rand() % 26 + 65);
- choice = main_menu();
- try
- {
- switch (choice)
- {
- case '0': AssignStrings(s1, s2, s3); break;
- case '1': s1.togglecase(0, s1.len());
- s2.upcase(0, 4);
- s3.downcase(2, 4); break;
- case '2': s5 = s2; s2 += s4; break;
- case '3': cout << endl << "Find 'c' in s5: " << s5.index('c'); break;
- case '4': s1 = s1 + "fooBlah"; break;
- case '5': s4[0] = c; break;
- case '6': cout << endl << "Enter String into s5" << endl;
- cout << "> ";
- cin >> s5; break;
- case '7': LogicalTests(s1, s2, s3, s4, s5); break;
- case '8': DisplayStrings(s1, s2, s3, s4, s5); break;
- case '9': isDone = true; break;
- default: cout << "Invalid selection. Try again."; break;
- }
- }
- catch (int e)
- {
- cout << "Error " << e << ": Index out of bounds" << endl;
- }
- } while (!isDone);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement