193 lines
5.3 KiB
C++
193 lines
5.3 KiB
C++
#include <iostream>
|
|
|
|
using namespace std;
|
|
|
|
class BaseString
|
|
{
|
|
protected:
|
|
char* p;
|
|
int len;
|
|
int capacity;
|
|
|
|
public:
|
|
explicit BaseString(int Capacity = 256) // mark Single-argument constructors explicit to avoid unintentional implicit conversions
|
|
{
|
|
cout << "\nBase Constructor 0\n";
|
|
capacity = Capacity;
|
|
p = new char[capacity];
|
|
len = 0;
|
|
p[0] = '\0'; // Initialize with an empty string
|
|
}
|
|
|
|
explicit BaseString(const char* ptr) //create object from input string
|
|
// mark Single-argument constructors explicit to avoid unintentional implicit conversions
|
|
{
|
|
cout << "\nBase Constructor 1\n";
|
|
len = Length(ptr);
|
|
capacity = len + 1; // allocate needed memory dynamically based on the Length of the input including null terminator
|
|
p = new char[capacity];
|
|
CopyString(p, ptr, len);
|
|
}
|
|
|
|
~BaseString()
|
|
{
|
|
cout << "\nBase Destructor\n";
|
|
delete[] p;
|
|
len = 0;
|
|
}
|
|
|
|
static int Length(const char* str) //static because method is not using object state and don`t need access to class members
|
|
{
|
|
int length = 0;
|
|
while (*str != '\0')
|
|
{
|
|
length++;
|
|
str++;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
static void CopyString(char* destination, const char* source, int length) //static because method is not using object state and don`t need access to class members
|
|
{
|
|
while (length--)
|
|
{
|
|
*destination++ = *source++;
|
|
}
|
|
*destination = '\0'; // Ensure the destination is null-terminated
|
|
}
|
|
|
|
int Length() const { return len; }
|
|
int Capacity() const { return capacity; }
|
|
char& operator[](int i) { return p[i]; }
|
|
|
|
BaseString& operator=(const BaseString& s)
|
|
{
|
|
cout << "\nBase Operator = \n";
|
|
if (this != &s) // self-copy||self-assignment checking.
|
|
{
|
|
char* new_p = new char[s.capacity];
|
|
CopyString(new_p, s.p, s.len);
|
|
delete[] p;
|
|
p = new_p;
|
|
len = s.Length(); // not using len = s.len because len may not be actual. just in case.
|
|
capacity = s.capacity;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
BaseString(const BaseString& s) // copy constructor
|
|
// using const can avoid unnecessary copying of objects
|
|
{
|
|
cout << "\nBase Copy Constructor\n";
|
|
len = s.Length();
|
|
capacity = s.capacity;
|
|
p = new char[capacity];
|
|
CopyString(p, s.p, len);
|
|
}
|
|
|
|
virtual void print() const
|
|
{
|
|
const char* ptr = p;
|
|
while (*ptr != '\0')
|
|
{
|
|
cout << *ptr;
|
|
ptr++;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
class DerivedString : public BaseString
|
|
{
|
|
public:
|
|
explicit DerivedString(const char* ptr) : BaseString(ptr)// mark Single-argument constructors explicit to avoid unintentional implicit conversions
|
|
{
|
|
cout << "\nDerived Constructor\n";
|
|
}
|
|
|
|
explicit DerivedString(int Capacity = 256) : BaseString(Capacity) // mark Single-argument constructors explicit to avoid unintentional implicit conversions
|
|
{
|
|
cout << "\nDerived Constructor 0\n";
|
|
}
|
|
|
|
DerivedString& operator=(const DerivedString& s)
|
|
{
|
|
cout << "\nDerived Operator =\n";
|
|
if (this != &s) // self-copy||self-assignment checking.
|
|
{
|
|
BaseString::operator=(s);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
DerivedString(const DerivedString& s) : BaseString(s) // using const can avoid unnecessary copying of objects
|
|
{
|
|
cout << "\nDerived Copy Constructor\n";
|
|
}
|
|
|
|
void print() const override
|
|
{
|
|
cout << "Derived: ";
|
|
BaseString::print();
|
|
}
|
|
|
|
int LastIndexOf(const char* substr) const
|
|
{
|
|
int substrLen = BaseString::Length(substr);
|
|
if (substrLen > len) return -1; // substr longer than the string
|
|
|
|
const char* start = p + len - substrLen; // Start from the last possible position
|
|
while (start >= p)
|
|
{
|
|
const char* current = start;
|
|
const char* sub = substr;
|
|
while (*sub != '\0' && *current == *sub)
|
|
{
|
|
current++;
|
|
sub++;
|
|
}
|
|
if (*sub == '\0') // If the entire substring matches
|
|
{
|
|
return start - p;
|
|
}
|
|
start--;
|
|
}
|
|
return -1; // Not found
|
|
}
|
|
};
|
|
|
|
int main() {
|
|
char str[] = "Hello, world!";
|
|
|
|
// creating objects of BaseString and calling functions
|
|
cout << "Creating and manipulating BaseString object:\n";
|
|
BaseString aa(str);
|
|
aa.print();
|
|
cout << "\nLength: " << aa.Length() << endl;
|
|
cout << "Capacity: " << aa.Capacity() << endl;
|
|
cout << "Character at index 1: " << aa[1] << endl;
|
|
|
|
// creating objects of DerivedString and calling functions
|
|
cout << "\nCreating and manipulating DerivedString object:\n";
|
|
DerivedString a(str);
|
|
DerivedString b;
|
|
b = a; // calling operator =
|
|
b.print();
|
|
cout << "\nLength: " << b.Length() << endl;
|
|
cout << "Capacity: " << b.Capacity() << endl;
|
|
cout << "Character at index 2: " << b[2] << endl;
|
|
|
|
//LastIndexOf
|
|
const char* substr = "wo";
|
|
int lastIndex = a.LastIndexOf(substr);
|
|
if (lastIndex != -1)
|
|
{
|
|
cout << "Last index of '" << substr << "': " << lastIndex << endl;
|
|
}
|
|
else
|
|
{
|
|
cout << "Substring '" << substr << "' not found." << endl;
|
|
}
|
|
return 0;
|
|
}
|