User-defined String Class:
#include <iostream>
#include <cstring> // for strlen,strcpy,strcmp,strcat
#include <utility> // for std::swap
using namespace std;
class String
{
private:
char* str; //pointer to dynamically allocated char array
size_t length; // size_t is unsigned integer [Link] cannot be negative
// using int canbe lead undefined behaviour or integer overflow if the string is very large
public:
// Default constructor
String() : str(nullptr), length(0) {}
// Parameterized constructor
String(const char* s) //const-->prevent accidental modification,safe & accept string literals
{
length = strlen(s); // Get the length of the input C-string
str = new char[length + 1]; //allocate new memory
strcpy(str, s); //copy the characters
}
// Copy constructor
String(const String& other) // &--> prevent recursion call infinite loop
{
length = [Link]; // Copy the length
str = new char[length + 1]; //allocate new memory
strcpy(str, [Link]); //copy characters
}
// Move constructor : Moves owernship of another object's resource
String(String&& other) noexcept : str([Link]), length([Link])
{//noexcept is a C++ keyword that guarantees the function will not throw exceptions.
[Link] = nullptr; // Nullify source so it doesn’t delete the same memory
[Link] = 0;
}
// Copy assignment operator
String& operator=(const String& other)
{
if (this != &other) // Check for self-assignment
{
delete[] str; // Delete current string
length = [Link]; // Take over other's string
str = new char[length + 1]; //allocate new memory
strcpy(str, [Link]); //copy characters
}
return *this;
}
// Move assignment operator
String& operator=(String&& other) noexcept
{
if (this != &other) // Check for self-assignment
{
delete[] str; // Delete current string
str = [Link]; // Take over other's string
length = [Link]; //Take other's lenght
[Link] = nullptr;
[Link] = 0;
}
return *this;
}
// Concatenation Operator: Returns a new String combining two strings
String operator+(const String& other) const
{
size_t newLength = length + [Link]; // Combined length
char* newStr = new char[newLength + 1]; // Allocate memory
if (str)
strcpy(newStr, str); // Copy first string
else
newStr[0] = '\0'; // If empty, make sure null terminated
if ([Link])
strcat(newStr, [Link]); // Append second string
String result(newStr); // Create new String object
delete[] newStr; // Clean temporary buffer
return result; // Return concatenated string
}
// Comparison Operator: Check if two strings are equal
bool operator==(const String& other) const
{
if (str == nullptr && [Link] == nullptr) return true; // Both null
if (str == nullptr || [Link] == nullptr) return false; // One null
return strcmp(str, [Link]) == 0; // Compare contents
}
// output Stream Operator (<<): Enables `cout << s;`
friend ostream& operator<<(ostream& os, const String& s)
{
os << ([Link] ? [Link] : ""); // Avoid null pointer crash
return os;
}
// Input Stream Operator (>>): Enables `cin >> s;`
friend istream& operator>>(istream& is, String& s)
{
char buffer[1000]; // Temporary buffer
is >> buffer; // Read input string
delete[] [Link]; // Clean existing memory
[Link] = strlen(buffer); // Update length
[Link] = new char[[Link] + 1]; // Allocate new memory
strcpy([Link], buffer); // Copy buffer into str
return is;
}
// Destructor: Frees dynamic memory
~String()
{
delete[] str; // Deallocate memory
}
};
int main()
{
String s1; // Default constructor
cout << "Enter a string: ";
cin >> s1; // Input operator
cout << "You entered: " << s1 << endl; // Output operator
String s2 = "Hello"; // Parameterized constructor
String s3 = s2; // Copy constructor
cout << "Copied string: " << s3 << endl;
String s4 = std::move(s3); // Move constructor
cout << "Moved string: " << s4 << endl;
String s5;
s5 = s4; // Copy assignment
cout << "Copy assigned: " << s5 << endl;
String s6;
s6 = std::move(s5); // Move assignment
cout << "Move assigned: " << s6 << endl;
String s7 = s4 + s6; // Concatenation
cout << "Concatenated: " << s7 << endl;
if (s4 == s6) // Comparison
cout << "s4 and s6 are equal.\n";
else
cout << "s4 and s6 are not equal.\n";
return 0;
}