C++ String Class Fundamentals and Operations
The C-style string (null-terminated character array) presents significant complexity and difficulty in large-scale application development. To address these challenges, the C++ Standard Library provides the string class, which is defined in the <string> header file.
Comparison Between String and C-Style Strings
Character arrays are pointers, whereas strings are classes
The string class ancapsulates char*, managing the underlying character sequence as a container.
Strings provide numerous practical member methods
Built-in functionality includes search (find), copy (copy), remove (erase), replace (replace), and insert (insert) operations.
No manual memory management required
The string class automatically handles memory allocation and deallocation. During string copying and value retrieval, the class maintains integrity, eliminating concerns about buffer overflows and out-of-bounds access.
Essential String Operations
String Constructors
string(); // Creates an empty string, e.g., string str;
string(const string& str); // Initializes using another string object
string(const char* s); // Initializes using C-string s
string(int n, char c); // Initializes using n copies of character c
String Assignment Operations
string& operator=(const char* s); // Assigns C-string to current string
string& operator=(const string &s); // Assigns string to current string
string& operator=(char c); // Assigns single character
string& assign(const char *s); // Assigns C-string s
string& assign(const char *s, int n); // Assigns first n characters of s
string& assign(const string &s); // Assigns string s
string& assign(int n, char c); // Assigns n copies of character c
string& assign(const string &s, int start, int n); // Assigns n characters from s starting at start
void demonstrateAssignment()
{
string str1; // Default constructor
string str2(str1); // Copy constructor
string str3 = str1;
string str4 = "abcd";
string str5(10, 'a');
cout << str4 << endl;
cout << str5 << endl;
// Basic assignment
str1 = "hello";
str2 = str4;
// Assign first n characters
str3.assign("abcdef", 4);
cout << str3 << endl;
// Assign substring from position with length
string str6;
str6.assign(str1, 1, 3); // Extracts "ell" from "hello"
cout << str6 << endl;
}
Character Access Operations
char& operator[](int index); // Access character via []
char& at(int index); // Access character via at() method
void demonstrateAccess()
{
string text = "hello world";
for (int i = 0; i < text.size(); i++)
{
cout << text[i] << endl;
cout << text.at(i) << endl;
}
// Difference between [] and at():
// [] causes undefined behavior on out-of-bounds access
// at() throws out_of_range exception
try
{
cout << text.at(100) << endl;
}
catch (out_of_range & e)
{
cout << e.what() << endl;
}
catch (...)
{
cout << "Index out of bounds" << endl;
}
}
String Concatenation
string& operator+=(const string& str); // Overloaded += operator
string& operator+=(const char* str); // Overloaded += operator
string& operator+=(const char c); // Overloaded += operator
string& append(const char *s); // Appends entire string s
string& append(const char *s, int n); // Appends first n characters of s
string& append(const string &s); // Equivalent to operator+=()
string& append(const string &s, int pos, int n); // Appends n characters from s starting at pos
string& append(int n, char c); // Appends n copies of character c
Search and Replace Operations
int find(const string& str, int pos = 0) const; // Find first occurrence of str from pos
int find(const char* s, int pos = 0) const; // Find first occurrence of s from pos
int find(const char* s, int pos, int n) const; // Find first n chars of s from pos
int find(const char c, int pos = 0) const; // Find first occurrence of character c
int rfind(const string& str, int pos = npos) const; // Find last occurrence of str
int rfind(const char* s, int pos = npos) const; // Find last occurrence of s
int rfind(const char* s, int pos, int n) const; // Find last n chars of s
int rfind(const char c, int pos = 0) const; // Find last occurrence of character c
string& replace(int pos, int n, const string& str); // Replace n chars from pos with str
string& replace(int pos, int n, const char* s); // Replace n chars from pos with s
void demonstrateConcatAndSearch()
{
// Concatenation
string part1 = "I ";
string part2 = "love programming";
part1 += part2;
cout << part1 << endl;
part1.append(" in C++");
cout << part1 << endl;
// Search operations
string sequence = "abcdefg";
int position = sequence.find("bcd"); // Returns index or -1 if not found
cout << "Position: " << position << endl;
int lastPos = sequence.rfind("cd"); // Reverse search
cout << "Last position: " << lastPos << endl;
// Replacement
string greeting = "hello";
greeting.replace(1, 3, "XXX"); // Replace "ell" with "XXX"
cout << greeting << endl; // Output: "hXXXo"
}
String Comparison
/*
compare returns 1 when greater, -1 when less, 0 when equal.
Case-sensitive comparison follows dictionary order.
Uppercase letters precede lowercase letters.
*/
int compare(const string &s) const; // Compare with string s
int compare(const char *s) const; // Compare with C-string s
void demonstrateComparison()
{
string first = "abc";
string second = "abcd";
if (first.compare(second) == 0)
{
cout << "Strings are equal" << endl;
}
else if (first.compare(second) == 1)
{
cout << "First string is greater" << endl;
}
else
{
cout << "First string is smaller" << endl;
}
}
Substring Extraction
string substr(int pos = 0, int n = npos) const; // Returns substring of n chars from pos
void demonstrateSubstring()
{
string source = "abcdef";
string extracted = source.substr(1, 3);
cout << "Extracted: " << extracted << endl; // Output: "bcd"
// Example: Extract username from email
string email = "john.doe@company.org";
int atPosition = email.find("@");
string username = email.substr(0, atPosition);
cout << "Username: " << username << endl;
}
Insertion and Deletion
string& insert(int pos, const char* s); // Insert C-string at position
string& insert(int pos, const string& str); // Insert string at position
string& insert(int pos, int n, char c); // Insert n copies of character c
string& erase(int pos, int n = npos); // Erase n characters from position
void demonstrateModification()
{
string message = "hello";
message.insert(1, "+++");
cout << message << endl; // Output: "h+++ello"
// Remove inserted portion
message.erase(1, 3);
cout << message << endl; // Output: "hello"
}
String and C-Style String Conversion
// Convert string to char*
string cppStr = "example";
const char* cStr = cppStr.c_str();
// Convert char* to string
char* rawStr = "example";
string convertedStr(rawStr);
In C++, implicit conversion exists from const char* to string, but not vice versa. For string objects, use c_str() method to obtain the correesponding C-string representation.
Best practice recommends using string objects throughout the program, converting to C-strings only when necesary for compatibility.
When modifying string content, both subscript operator [] and at() method return character references. However, after memory reallocation, these references may become invalid.
string data = "abcdefg";
char& ref1 = data[2];
char& ref2 = data[3];
ref1 = '1';
ref2 = '2';
cout << data << endl;
cout << (int*)data.c_str() << endl;
data = "completely different string";
cout << data << endl;
cout << (int*)data.c_str() << endl;