#include "String.hpp"
#include "../Functions/functions.hpp"
// O(1)
String::String() {
// Allocate space.
array = new char[1];
// Add the null.
array[0] = '0';
// Adjust private variables.
_capacity = 0;
_size = 0;
}
// O(1)
String::String(char c) {
// Allocate space.
array = new char[2];
// Add the character and the null.
array[0] = c;
array[1] = '0';
// Adjust private variables.
_capacity = 1;
_size = 1;
}
// O(n)
String::String(char* str) {
// Get the length of the incoming string.
int length = 0;
while (str[length])
++length;
// Allocate space for the string plus a null.
array = new char[length + 1];
// Fill our array up, including the null.
for (int i = 0; i <= length; ++i)
array[i] = str[i];
// Adjust private variables.
_capacity = length;
_size = length;
}
// O(1)
String::~String() {
delete[] array;
}
// O(n)
char String::at(int index) const {
// If our index is negative, or beyond the size of our array, we
cannot return
// anything.
return (index < 0 || (unsigned int)index >= size()) ? throw
"Index"
: array[index];
}
void String::clear() {
for (unsigned int i = 0; i < _capacity; ++i)
array[i] = '0';
_size = 0;
}
// O(n)
unsigned int String::size() const {
return _size;
}
// O(1)
bool String::empty() const {
return !this->array[0];
}
// O(1)
unsigned int String::capacity() const {
return this->_capacity;
}
// O(n)
void String::reserve(unsigned int n) {
if (!n)
return;
// Make a new array.
char* _array = new char[_capacity + n + 1]();
// Fill it up.
int length = this->size();
for (int i = 0; i <= length; ++i)
_array[i] = array[i];
// Remove old memory.
delete[] array;
// Save new memory.
array = _array;
// Adjust private variables.
_capacity += n;
return;
}
// O(n)
void String::insert(char c, int index) {
// Prepend and append as easy cases.
if (index <= 0)
prepend(c);
else if ((unsigned int)index >= size())
append(c);
else {
// Increase capacity, if needed.
if (this->size() == this->_capacity) {
this->reserve(this->size() * 2);
}
// Move all elements after index over.
for (int i = this->size() + 1; i >= index; --i)
array[i] = array[i - 1];
// Insert our new character.
array[index] = c;
_size++;
}
return;
}
// O(n)
void String::erase(char c) {
// Create a new array.
char* _array = new char[_capacity + 1];
// Copy all non-erased characters to the new array.
int length = size();
for (int i = 0, j = 0; i <= length; ++i) {
if (array[i] != c)
_array[j++] = array[i];
else
_size--;
}
// Remove the old array.
delete[] array;
array = _array;
return;
}
// O(n)
void String::remove(int index) {
// Copy all characters to the left, overwriting index.
int length = this->size();
for (int i = index; i < length; ++i)
array[i] = array[i + 1];
_size--;
return;
}
// O(1) Amortized Cost due to doubling.
// More info:
// https://www.interviewcake.com/concept/java/dynamic-array-
amortized-analysis
void String::append(char c) {
unsigned int length = size();
if (length >= this->capacity()) {
this->reserve((length + 1) * 2);
}
array[length] = c;
array[length + 1] = 0;
_size++;
return;
}
// O(n)
void String::prepend(char c) {
unsigned int length = size();
if (length >= this->capacity()) {
this->reserve((length + 1) * 2);
}
for (int i = length + 1; i > 0; --i)
array[i] = array[i - 1];
array[0] = c;
_size++;
return;
}
// O(n)
bool String::compare(char* str) const {
int length = size();
// Compare all the way up to the null.
for (int i = 0; i <= length; ++i) {
if (str[i] != array[i])
return false;
}
return true;
}
// O(n)
bool String::compare(const String& str) const {
return this->compare(str.array);
}
// O(n)
void String::concatenate(char* str) {
// Get our lengths.
unsigned int strlen = 0, length = size();
while (str[strlen])
++strlen;
// Reserve the space
if (length + strlen > this->_capacity) {
this->reserve(strlen);
}
// Copy things over.
for (unsigned int i = length, j = 0; i <= length + strlen; ++i,
++j) {
this->array[i] = str[j];
}
_size += strlen;
return;
}
// O(n)
void String::concatenate(String& str) {
this->concatenate(str.array);
return;
}
// O(n)
inline bool exact_match(char* a, char* b) {
return (!b[0]) ? true : a[0] == b[0] && exact_match(a + 1, b +
1);
}
// O(n^2)
unsigned int String::find(char* str, int start) const {
unsigned int i, length;
for (i = start, length = size(); i < length; ++i) {
if (exact_match(this->array + i, str))
return i;
}
return i;
}
// O(n)
unsigned int String::find(char c, int start) const {
unsigned int i, length;
for (i = start, length = size(); i < length; ++i)
if (array[i] == c)
return i;
return i;
}
// O(n^2)
unsigned int String::find(String& str, int start) const {
return this->find(str.array, start);
}
// O(n)
void String::reverse() {
int length = size() - 1;
for (int i = 0; i < length / 2; ++i) {
array[i] ^= array[length - i];
array[length - i] ^= array[i];
array[i] ^= array[length - i];
}
return;
}
// O(n)
void String::shift(int n) {
int length = size();
for (int i = 0; i < length; ++i) {
array[i] = array[i] + n % 255;
if (!array[i])
++array[i];
}
return;
}
// O(n)
int String::toInt() const {
return stringtoint(this->array);
}
// O(n) since append is O(1) amortized.
String String::substr(int start, int end) const {
String ret;
for (int i = start; i < end; ++i)
ret.append(array[i]);
return ret;
}
void String::print(std::ostream& oss) const {
for (int i = 0; array[i]; ++i)
oss << array[i];
}
std::ostream& operator<<(std::ostream& oss, const String& str)
{
str.print(oss);
return oss;
}
char String::pop_back() {
if (empty())
throw "Nothing to pop";
char c = array[_size - 1];
array[_size--] = '0';
return c;
}

#include String.hpp#include ..Functionsfunctions.hpp.docx

  • 1.
    #include "String.hpp" #include "../Functions/functions.hpp" //O(1) String::String() { // Allocate space. array = new char[1]; // Add the null. array[0] = '0'; // Adjust private variables. _capacity = 0; _size = 0; } // O(1) String::String(char c) { // Allocate space. array = new char[2]; // Add the character and the null. array[0] = c; array[1] = '0'; // Adjust private variables. _capacity = 1; _size = 1; } // O(n) String::String(char* str) { // Get the length of the incoming string. int length = 0;
  • 2.
    while (str[length]) ++length; // Allocatespace for the string plus a null. array = new char[length + 1]; // Fill our array up, including the null. for (int i = 0; i <= length; ++i) array[i] = str[i]; // Adjust private variables. _capacity = length; _size = length; } // O(1) String::~String() { delete[] array; } // O(n) char String::at(int index) const { // If our index is negative, or beyond the size of our array, we cannot return // anything. return (index < 0 || (unsigned int)index >= size()) ? throw "Index" : array[index]; } void String::clear() { for (unsigned int i = 0; i < _capacity; ++i) array[i] = '0'; _size = 0; }
  • 3.
    // O(n) unsigned intString::size() const { return _size; } // O(1) bool String::empty() const { return !this->array[0]; } // O(1) unsigned int String::capacity() const { return this->_capacity; } // O(n) void String::reserve(unsigned int n) { if (!n) return; // Make a new array. char* _array = new char[_capacity + n + 1](); // Fill it up. int length = this->size(); for (int i = 0; i <= length; ++i) _array[i] = array[i]; // Remove old memory. delete[] array; // Save new memory. array = _array; // Adjust private variables.
  • 4.
    _capacity += n; return; } //O(n) void String::insert(char c, int index) { // Prepend and append as easy cases. if (index <= 0) prepend(c); else if ((unsigned int)index >= size()) append(c); else { // Increase capacity, if needed. if (this->size() == this->_capacity) { this->reserve(this->size() * 2); } // Move all elements after index over. for (int i = this->size() + 1; i >= index; --i) array[i] = array[i - 1]; // Insert our new character. array[index] = c; _size++; } return; } // O(n) void String::erase(char c) { // Create a new array. char* _array = new char[_capacity + 1]; // Copy all non-erased characters to the new array. int length = size(); for (int i = 0, j = 0; i <= length; ++i) { if (array[i] != c) _array[j++] = array[i];
  • 5.
    else _size--; } // Remove theold array. delete[] array; array = _array; return; } // O(n) void String::remove(int index) { // Copy all characters to the left, overwriting index. int length = this->size(); for (int i = index; i < length; ++i) array[i] = array[i + 1]; _size--; return; } // O(1) Amortized Cost due to doubling. // More info: // https://www.interviewcake.com/concept/java/dynamic-array- amortized-analysis void String::append(char c) { unsigned int length = size(); if (length >= this->capacity()) { this->reserve((length + 1) * 2); } array[length] = c; array[length + 1] = 0; _size++; return; } // O(n)
  • 6.
    void String::prepend(char c){ unsigned int length = size(); if (length >= this->capacity()) { this->reserve((length + 1) * 2); } for (int i = length + 1; i > 0; --i) array[i] = array[i - 1]; array[0] = c; _size++; return; } // O(n) bool String::compare(char* str) const { int length = size(); // Compare all the way up to the null. for (int i = 0; i <= length; ++i) { if (str[i] != array[i]) return false; } return true; } // O(n) bool String::compare(const String& str) const { return this->compare(str.array); } // O(n) void String::concatenate(char* str) { // Get our lengths. unsigned int strlen = 0, length = size(); while (str[strlen]) ++strlen; // Reserve the space if (length + strlen > this->_capacity) {
  • 7.
    this->reserve(strlen); } // Copy thingsover. for (unsigned int i = length, j = 0; i <= length + strlen; ++i, ++j) { this->array[i] = str[j]; } _size += strlen; return; } // O(n) void String::concatenate(String& str) { this->concatenate(str.array); return; } // O(n) inline bool exact_match(char* a, char* b) { return (!b[0]) ? true : a[0] == b[0] && exact_match(a + 1, b + 1); } // O(n^2) unsigned int String::find(char* str, int start) const { unsigned int i, length; for (i = start, length = size(); i < length; ++i) { if (exact_match(this->array + i, str)) return i; } return i; } // O(n) unsigned int String::find(char c, int start) const { unsigned int i, length;
  • 8.
    for (i =start, length = size(); i < length; ++i) if (array[i] == c) return i; return i; } // O(n^2) unsigned int String::find(String& str, int start) const { return this->find(str.array, start); } // O(n) void String::reverse() { int length = size() - 1; for (int i = 0; i < length / 2; ++i) { array[i] ^= array[length - i]; array[length - i] ^= array[i]; array[i] ^= array[length - i]; } return; } // O(n) void String::shift(int n) { int length = size(); for (int i = 0; i < length; ++i) { array[i] = array[i] + n % 255; if (!array[i]) ++array[i]; } return; } // O(n) int String::toInt() const { return stringtoint(this->array);
  • 9.
    } // O(n) sinceappend is O(1) amortized. String String::substr(int start, int end) const { String ret; for (int i = start; i < end; ++i) ret.append(array[i]); return ret; } void String::print(std::ostream& oss) const { for (int i = 0; array[i]; ++i) oss << array[i]; } std::ostream& operator<<(std::ostream& oss, const String& str) { str.print(oss); return oss; } char String::pop_back() { if (empty()) throw "Nothing to pop"; char c = array[_size - 1]; array[_size--] = '0'; return c; }