pr4/pr4.cpp

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;
}