
9. Fundamentals of C++ Strings
C++ Strings
In this note, we explore how C++ strings work, covering topics such as size
, length
, capacity
, max_size
, and various string operations like insert
, push_back
, pop_back
, compare
, and more.
1. Overview of C++ Strings
In C++, the std::string
class (defined in the <string>
header) offers a convenient way to manipulate sequences of characters. Unlike C-style character arrays (char*
), std::string
manages memory automatically, resizing when needed and keeping track of its own length. This provides both convenience and safety compared to traditional C-strings.
2. Fundamental Properties of std::string
2.1. size()
vs. length()
size()
returns the number of characters currently in the string.
length()
does the same thing—both functions are effectively identical.
2.2. capacity()
capacity()
tells you how much memory (in characters) the string has currently allocated.
- If you exceed the current capacity with more insertions, the string automatically allocates more memory.
- This behavior helps avoid constant reallocation every time a single character is added.
2.3. max_size()
max_size()
returns the maximum possible length of the string, which is typically a very large number (e.g., 2,147,483,647 on many systems).
3. Basic String Operations
3.1. Creating and Initializing Strings
#include <iostream>
#include <string>
using namespace std;
int main() {
// Direct initialization
string text = "Hello world!";
cout << "Text: " << text << endl;
// Creating a string with a specific number of repeated characters
string stars(50, '*');
cout << "Stars: " << stars << endl;
return 0;
}
Output:
Text: Hello world!
Stars: **************************************************
3.2. resize()
and shrink_to_fit()
resize(x)
changes the string size tox
. Ifx
is smaller, the string is truncated. Ifx
is larger, new characters (usually'\0'
or implementation-defined) may be appended.
shrink_to_fit()
requests the string to reduce its capacity to fit its current size exactly.
#include <iostream>
#include <string>
using namespace std;
int main() {
string s(50, '*'); // Creates a string with 50 '*'
cout << s << endl;
cout << "Capacity before resize: " << s.capacity() << endl;
// Resize down to 10 characters
s.resize(10);
// Shrink the capacity to match the new size
s.shrink_to_fit();
cout << s << endl;
cout << "Capacity after shrink_to_fit: " << s.capacity() << endl;
return 0;
}
Example Output:
**************************************************
Capacity before resize: 63
**********
Capacity after shrink_to_fit: 15
3.3. reserve()
reserve(x)
ensures that the string’s capacity is at leastx
.
- This can help optimize string operations if you know you’ll be adding a lot of characters.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Apple";
cout << "Initial capacity: " << text.capacity() << endl;
text.reserve(1000);
cout << "Capacity after reserve(1000): " << text.capacity() << endl;
return 0;
}
Example Output:
Initial capacity: 15
Capacity after reserve(1000): 1007
3.4. clear()
and empty()
clear()
removes all characters from the string, making it empty.
empty()
returns a boolean indicating whether the string is empty.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Happy programmers day";
cout << text << endl; // Output: Happy programmers day
text.clear(); // Clears the string
if (text.empty()) {
cout << "No Text" << endl; // Output: No Text
} else {
cout << text << endl;
}
return 0;
}
4. Appending and Inserting
4.1. append()
vs. operator+=()
operator+=()
concatenates a string or character to the existing string.
append()
does the same but can be more flexible with arguments.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Hi all";
cout << text << endl; // Output: Hi all
// Using operator+=
text += " , bye bye";
cout << text << endl; // Output: Hi all , bye bye
// Using append()
text.append("Salam millet");
cout << text << endl; // Output: Hi all , bye byeSalam millet
return 0;
}
4.2. insert()
insert(iterator, char)
inserts a character at the specified position, which is provided by an iterator.
- Commonly used with
begin()
,end()
, orbegin() + offset
.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Happy programmers day";
cout << text << endl;
// Insert 'E' at the beginning
text.insert(text.begin(), 'E');
cout << text << endl;
// Insert 'E' after the 5th character
text.insert(text.begin() + 5, 'E');
cout << text << endl;
// Insert 'A' before the last character
text.insert(text.end() - 1, 'A');
cout << text << endl;
return 0;
}
Example Output:
Happy programmers day
EHappy programmers day
EHappEy programmers day
EHappEy programmers daAy
5. Accessing String Characters
5.1. Index Access and at()
text[x]
andtext.at(x)
both return the character at indexx
.
at()
performs bounds checking and throws an exception ifx
is out of range, whereastext[x]
does not.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Happy";
cout << text[0] << endl; // H
cout << text.at(0) << endl; // H
text[0] = 'Z';
cout << text << endl; // Zappy
// Using a for loop to print each character
for (int i = 0; i < text.size(); i++) {
cout << text[i] << endl;
}
return 0;
}
5.2. front()
and back()
front()
returns a reference to the first character.
back()
returns a reference to the last character.
- You can also modify the characters directly through these references.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Happy";
cout << text.front() << endl; // H
text.front() = 'P';
cout << text.front() << endl; // P
cout << text.back() << endl; // y
text.back() = 'i';
cout << text.back() << endl; // i
cout << text << endl; // Pappi
return 0;
}
6. Other Common Methods
6.1. substr()
substr(pos, n)
returns a substring starting at indexpos
and spanningn
characters.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Happy programmers day";
// From index 6, get 10 characters
cout << text.substr(6, 10) << endl; // programmer
cout << text << endl; // Happy programmers day
return 0;
}
6.2. pop_back()
and push_back()
pop_back()
removes the last character of the string.
push_back(c)
appends a characterc
to the end of the string.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "SALAM SALAM";
text.pop_back(); // Removes the last character
cout << text << endl; // SALAM SALA
text.push_back('Z'); // Adds 'Z' to the end
cout << text << endl; // SALAM SALAZ
return 0;
}
6.3. compare()
compare()
returns0
if the strings are equal, a negative value if the first string is lexicographically less, and a positive value otherwise.
==
can also be used to check for equality directly.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text1 = "salam";
string text2 = "Salam";
cout << boolalpha << (text1 == text2) << endl; // false
cout << text1.compare(text2) << endl; // 1 (or a positive number)
return 0;
}
6.4. assign()
assign()
is an alternative to the assignment operator=
.
- Both achieve the same result.
#include <iostream>
#include <string>
using namespace std;
int main() {
string text;
text = "Salam";
cout << text << endl;
string text2;
text2.assign("Salam");
cout << text2 << endl;
return 0;
}
6.5. find()
and rfind()
find(x)
searches for the character or substringx
from the left (beginning).
rfind(x)
searches from the right (end).
#include <iostream>
#include <string>
using namespace std;
int main() {
string text = "Happy programmers day";
// find() returns the index of first occurrence, or string::npos if not found
cout << text.find('j') << endl; // Might return a large number if 'j' isn't found
cout << text.find('H') << endl; // 0 if 'H' is the first character
// rfind() returns the index of the last occurrence
cout << text.rfind('j') << endl;
cout << text.rfind('y') << endl;
return 0;
}
7. Complete Example: Putting It All Together
Below is a complete code example demonstrating multiple string operations in one program:
#include <iostream>
#include <string>
using namespace std;
int main() {
// 1. Create and initialize a string
string text = "Hello C++ World!";
cout << "Initial text: " << text << endl;
// 2. Check size and capacity
cout << "Size: " << text.size() << endl;
cout << "Length: " << text.length() << endl;
cout << "Capacity: " << text.capacity() << endl;
cout << "Max Size: " << text.max_size() << endl;
cout << "------------------------" << endl;
// 3. Modify the string with += and append
text += " Let's explore strings.";
text.append(" Indeed!");
cout << "After appending: " << text << endl;
cout << "Size now: " << text.size() << endl;
cout << "Capacity now: " << text.capacity() << endl;
cout << "------------------------" << endl;
// 4. Use reserve to pre-allocate memory
text.reserve(100);
cout << "Capacity after reserve(100): " << text.capacity() << endl;
cout << "------------------------" << endl;
// 5. Using front(), back(), and at()
cout << "First character (front): " << text.front() << endl;
cout << "Last character (back): " << text.back() << endl;
cout << "Third character (at(2)): " << text.at(2) << endl;
cout << "------------------------" << endl;
// 6. Insert characters
text.insert(text.begin(), 'X');
text.insert(text.begin() + 5, 'Y');
cout << "After insertions: " << text << endl;
cout << "------------------------" << endl;
// 7. pop_back() and push_back()
text.pop_back();
text.push_back('Z');
cout << "After pop_back and push_back: " << text << endl;
cout << "------------------------" << endl;
// 8. substr()
cout << "Substring (index 7, length 10): " << text.substr(7, 10) << endl;
cout << "------------------------" << endl;
// 9. compare
string sample = "XHello";
// Compare the first 6 characters of text with sample
cout << "Compare first 6 chars of text to sample: "
<< text.compare(0, 6, sample) << endl;
// 10. find and rfind
cout << "find('C'): " << text.find('C') << endl;
cout << "rfind('C'): " << text.rfind('C') << endl;
cout << "------------------------" << endl;
// 11. clear and check empty
text.clear();
if (text.empty()) {
cout << "text is now empty after clear()" << endl;
}
return 0;
}
Possible Output (Will Vary Depending on Implementation)
Initial text: Hello C++ World!
Size: 16
Length: 16
Capacity: 15
Max Size: 2147483647
------------------------
After appending: Hello C++ World! Let's explore strings. Indeed!
Size now: 49
Capacity now: 63
------------------------
Capacity after reserve(100): 100
------------------------
First character (front): H
Last character (back): !
Third character (at(2)): l
------------------------
After insertions: XHellYHello C++ World! Let's explore strings. Indeed!
------------------------
After pop_back and push_back: XHellYHello C++ World! Let's explore strings. IndeedZ
------------------------
Substring (index 7, length 10): llo C++ Wo
------------------------
Compare first 6 chars of text to sample: 1
find('C'): 12
rfind('C'): 12
------------------------
text is now empty after clear()
8. Additional Notes and Best Practices
- Avoid Out-of-Range Access:
- Using
text.at(index)
throws an exception ifindex
is out of bounds.
- Using
text[index]
whereindex
is out of bounds can lead to undefined behavior.
- Using
- Efficient Concatenation:
- If you plan multiple concatenations, consider using
reserve()
to minimize reallocation overhead.
- If you plan multiple concatenations, consider using
- Comparisons:
==
is straightforward for equality. For greater or less comparisons, usecompare()
.
- Memory:
- While
std::string
simplifies memory management, always be mindful of large strings.max_size()
helps to identify potential limits.
- While
- Iterators:
- Many string operations use iterators (
begin()
,end()
), which are powerful for generic code that might also apply to other containers.
- Many string operations use iterators (
Reference
The content in this document is based on the original notes provided in Azerbaijani. For further details, you can refer to the original document using the following link:
Original Note - Azerbaijani Version