Introduction to Strings
C++ provides the std::string class in the <string>
header for powerful and safe string manipulation. Unlike C-style character arrays,
std::string manages memory automatically and provides many useful methods.
std::string
std::string is a class that represents a sequence of characters. It automatically manages memory, grows and shrinks as needed, and provides rich functionality for string manipulation.
Header: #include <string>
#include <iostream>
#include <string> // Required for std::string
using namespace std;
int main() {
// Create a string
string greeting = "Hello, World!";
// Print the string
cout << greeting << endl;
// Get length
cout << "Length: " << greeting.length() << endl; // 13
// Strings are mutable
greeting[0] = 'J';
cout << greeting << endl; // "Jello, World!"
// Concatenation with +
string name = "Alice";
string message = "Hello, " + name + "!";
cout << message << endl; // "Hello, Alice!"
return 0;
}
Why Use std::string?
Memory Safe
Automatic memory management, no buffer overflows
Dynamic Size
Grows and shrinks automatically as needed
Rich API
Many built-in methods for manipulation
String Declaration & Initialization
There are many ways to create and initialize strings in C++. The
std::string class provides multiple constructors for flexibility.
#include <iostream>
#include <string>
using namespace std;
int main() {
// Method 1: Default constructor (empty string)
string s1;
cout << "s1: \"" << s1 << "\" (empty)" << endl;
// Method 2: Initialize with string literal
string s2 = "Hello";
string s3("World");
string s4{"C++11 style"}; // Uniform initialization
// Method 3: Copy constructor
string s5 = s2; // Copy of s2
string s6(s3); // Copy of s3
// Method 4: Repeat character n times
string s7(5, '*'); // "*****"
string s8(10, 'A'); // "AAAAAAAAAA"
cout << "s7: " << s7 << endl;
// Method 5: Substring
string s9 = "Hello, World!";
string s10(s9, 0, 5); // "Hello" (from index 0, length 5)
string s11(s9, 7); // "World!" (from index 7 to end)
cout << "s10: " << s10 << endl;
cout << "s11: " << s11 << endl;
// Method 6: From C-string
const char* cstr = "C-style string";
string s12(cstr);
// Method 7: From iterators
string source = "ABCDEFGH";
string s13(source.begin(), source.begin() + 4); // "ABCD"
return 0;
}
Practice Questions: Declaration
Task: Create a string containing 20 dashes ('-').
Show Solution
string dashes(20, '-');
cout << dashes << endl; // "--------------------"
Task: From "Programming in C++", extract "C++" using substring constructor.
Show Solution
string full = "Programming in C++";
string extracted(full, 15, 3); // Start at 15, length 3
cout << extracted << endl; // "C++"
String Operations
C++ strings support intuitive operators for concatenation, comparison, and assignment—making string manipulation natural and readable.
Concatenation
#include <iostream>
#include <string>
using namespace std;
int main() {
string first = "Hello";
string second = "World";
// Using + operator
string combined = first + ", " + second + "!";
cout << combined << endl; // "Hello, World!"
// Using += operator
string message = "Count: ";
message += "1, ";
message += "2, ";
message += "3";
cout << message << endl; // "Count: 1, 2, 3"
// Concatenate with char
string s = "ABC";
s += 'D'; // "ABCD"
s = s + 'E'; // "ABCDE"
// append() method
string str = "Hello";
str.append(" World"); // "Hello World"
str.append(3, '!'); // "Hello World!!!"
str.append("12345", 0, 3); // "Hello World!!!123"
cout << str << endl;
return 0;
}
Comparison
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "apple";
string s2 = "banana";
string s3 = "apple";
// Comparison operators (lexicographic)
cout << boolalpha; // Print true/false instead of 1/0
cout << "s1 == s3: " << (s1 == s3) << endl; // true
cout << "s1 != s2: " << (s1 != s2) << endl; // true
cout << "s1 < s2: " << (s1 < s2) << endl; // true ('a' < 'b')
cout << "s2 > s1: " << (s2 > s1) << endl; // true
// compare() method: returns 0 if equal, <0 if less, >0 if greater
int result = s1.compare(s2);
if (result == 0) cout << "Equal" << endl;
else if (result < 0) cout << "s1 comes before s2" << endl;
else cout << "s1 comes after s2" << endl;
// Compare substrings
string str = "Hello, World!";
// Compare "Hello" with "Hello"
cout << str.compare(0, 5, "Hello") << endl; // 0 (equal)
return 0;
}
Assignment
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "Initial";
// Direct assignment
s1 = "New value";
cout << s1 << endl;
// Assign from another string
string s2 = "Source";
s1 = s2;
cout << s1 << endl; // "Source"
// assign() method
s1.assign("Assigned");
s1.assign(5, 'X'); // "XXXXX"
s1.assign("ABCDEF", 3); // "ABC" (first 3 chars)
// Swap strings
string a = "First";
string b = "Second";
a.swap(b); // or swap(a, b);
cout << "a: " << a << ", b: " << b << endl; // a: Second, b: First
return 0;
}
Practice Questions: Operations
Task: Write code to check if "cat" comes before "dog" alphabetically.
Show Solution
string s1 = "cat";
string s2 = "dog";
if (s1 < s2) {
cout << s1 << " comes before " << s2 << endl;
}
// Output: cat comes before dog
Accessing Characters
Individual characters in a string can be accessed using the subscript
operator [] or the safer at() method which
provides bounds checking.
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, World!";
// Using [] operator (no bounds check)
cout << "First: " << str[0] << endl; // 'H'
cout << "Last: " << str[12] << endl; // '!'
// Using at() method (bounds checked - throws exception)
cout << "Third: " << str.at(2) << endl; // 'l'
// Modify characters
str[0] = 'J';
str.at(7) = 'C';
cout << str << endl; // "Jello, Corld!"
// front() and back()
cout << "Front: " << str.front() << endl; // 'J'
cout << "Back: " << str.back() << endl; // '!'
// Exception handling with at()
try {
char c = str.at(100); // Out of bounds!
} catch (const out_of_range& e) {
cout << "Error: " << e.what() << endl;
}
// Iterate through characters
cout << "Characters: ";
for (char c : str) {
cout << c << " ";
}
cout << endl;
return 0;
}
String Iteration Methods
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello";
// Method 1: Index-based loop
cout << "Index-based: ";
for (size_t i = 0; i < str.length(); i++) {
cout << str[i];
}
cout << endl;
// Method 2: Range-based for (read-only)
cout << "Range-based: ";
for (char c : str) {
cout << c;
}
cout << endl;
// Method 3: Range-based for (modifiable)
for (char& c : str) {
c = toupper(c); // Convert to uppercase
}
cout << "Uppercase: " << str << endl; // "HELLO"
// Method 4: Iterator-based
cout << "Iterator: ";
for (auto it = str.begin(); it != str.end(); ++it) {
cout << *it;
}
cout << endl;
// Method 5: Reverse iteration
cout << "Reverse: ";
for (auto it = str.rbegin(); it != str.rend(); ++it) {
cout << *it;
}
cout << endl; // "OLLEH"
return 0;
}
Practice Questions: Accessing
Task: Count the number of vowels in "Programming is fun".
Show Solution
string str = "Programming is fun";
int vowels = 0;
for (char c : str) {
c = tolower(c);
if (c == 'a' || c == 'e' || c == 'i' ||
c == 'o' || c == 'u') {
vowels++;
}
}
cout << "Vowels: " << vowels << endl; // 5
String Methods
The std::string class provides many useful methods for
querying string properties and modifying string contents.
Size and Capacity
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, World!";
// Length/Size (same thing)
cout << "length(): " << str.length() << endl; // 13
cout << "size(): " << str.size() << endl; // 13
// Check if empty
string empty;
cout << "empty(): " << empty.empty() << endl; // 1 (true)
cout << "str empty: " << str.empty() << endl; // 0 (false)
// Capacity (allocated memory)
cout << "capacity(): " << str.capacity() << endl;
// Reserve memory
str.reserve(100); // Reserve space for 100 chars
cout << "After reserve: " << str.capacity() << endl;
// Resize string
str.resize(5); // Keep first 5 chars: "Hello"
cout << "After resize(5): \"" << str << "\"" << endl;
str.resize(10, '!'); // Extend with '!'
cout << "After resize(10, '!'): \"" << str << "\"" << endl; // "Hello!!!!!"
// Clear string
str.clear();
cout << "After clear: empty = " << str.empty() << endl; // true
return 0;
}
Substring Extraction
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, World!";
// substr(pos, len) - extract substring
string sub1 = str.substr(0, 5); // "Hello"
string sub2 = str.substr(7); // "World!" (to end)
string sub3 = str.substr(7, 5); // "World"
cout << "sub1: " << sub1 << endl;
cout << "sub2: " << sub2 << endl;
cout << "sub3: " << sub3 << endl;
// Extract middle portion
string text = "The quick brown fox";
string middle = text.substr(4, 5); // "quick"
cout << "Middle: " << middle << endl;
return 0;
}
Insert, Erase, Replace
#include <iostream>
#include <string>
using namespace std;
int main() {
// INSERT
string str = "Hello World";
str.insert(5, ","); // Insert at position 5
cout << "Insert: " << str << endl; // "Hello, World"
str.insert(7, "Beautiful ");
cout << "Insert: " << str << endl; // "Hello, Beautiful World"
// ERASE
str = "Hello, World!";
str.erase(5, 2); // Erase 2 chars starting at position 5
cout << "Erase: " << str << endl; // "HelloWorld!"
str.erase(5); // Erase from position 5 to end
cout << "Erase: " << str << endl; // "Hello"
// REPLACE
str = "Hello, World!";
str.replace(7, 5, "C++"); // Replace 5 chars at position 7
cout << "Replace: " << str << endl; // "Hello, C++!"
str = "I like cats and cats are cute";
str.replace(str.find("cats"), 4, "dogs");
cout << "Replace: " << str << endl; // First "cats" -> "dogs"
return 0;
}
Practice Questions: Methods
Task: Extract the file extension from "document.txt".
Show Solution
string filename = "document.txt";
size_t dotPos = filename.rfind('.'); // Find last dot
if (dotPos != string::npos) {
string ext = filename.substr(dotPos + 1);
cout << "Extension: " << ext << endl; // "txt"
}
Searching & Replacing
C++ strings provide powerful search functions to find characters, substrings, and patterns within strings.
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, World! Hello, C++!";
// find() - find first occurrence
size_t pos = str.find("Hello");
cout << "First 'Hello' at: " << pos << endl; // 0
// find() with starting position
pos = str.find("Hello", 1); // Search from index 1
cout << "Second 'Hello' at: " << pos << endl; // 14
// find() single character
pos = str.find('!');
cout << "First '!' at: " << pos << endl; // 12
// rfind() - find last occurrence (reverse find)
pos = str.rfind("Hello");
cout << "Last 'Hello' at: " << pos << endl; // 14
// Check if substring exists
if (str.find("World") != string::npos) {
cout << "'World' found!" << endl;
}
// string::npos means "not found"
pos = str.find("Python");
if (pos == string::npos) {
cout << "'Python' not found" << endl;
}
return 0;
}
More Search Functions
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, World!";
// find_first_of() - find first of any character in set
size_t pos = str.find_first_of("aeiou"); // First vowel
cout << "First vowel at: " << pos << endl; // 1 ('e')
// find_last_of() - find last of any character in set
pos = str.find_last_of("aeiou");
cout << "Last vowel at: " << pos << endl; // 8 ('o' in World)
// find_first_not_of() - find first char NOT in set
string digits = "12345abc678";
pos = digits.find_first_not_of("0123456789");
cout << "First non-digit at: " << pos << endl; // 5 ('a')
// find_last_not_of()
string padded = " Hello ";
pos = padded.find_last_not_of(' ');
cout << "Last non-space at: " << pos << endl; // 7 ('o')
return 0;
}
Replace All Occurrences
#include <iostream>
#include <string>
using namespace std;
// Function to replace all occurrences
string replaceAll(string str, const string& from, const string& to) {
size_t pos = 0;
while ((pos = str.find(from, pos)) != string::npos) {
str.replace(pos, from.length(), to);
pos += to.length(); // Move past replacement
}
return str;
}
int main() {
string text = "I like cats. cats are cute. I have two cats.";
// Replace all "cats" with "dogs"
text = replaceAll(text, "cats", "dogs");
cout << text << endl;
// "I like dogs. dogs are cute. I have two dogs."
return 0;
}
Practice Questions: Searching
Task: Count how many times "the" appears in "the cat and the dog and the bird".
Show Solution
string str = "the cat and the dog and the bird";
string target = "the";
int count = 0;
size_t pos = 0;
while ((pos = str.find(target, pos)) != string::npos) {
count++;
pos += target.length();
}
cout << "Count: " << count << endl; // 3
String Input/Output
C++ provides multiple ways to read and write strings. Understanding
the difference between cin, getline(), and
other methods is essential for proper input handling.
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
// cin >> stops at whitespace
cout << "Enter your first name: ";
cin >> name;
cout << "Hello, " << name << "!" << endl;
// Input: "John Doe" -> name = "John" (stops at space)
// Clear the input buffer
cin.ignore(numeric_limits<streamsize>::max(), '\n');
// getline() reads entire line
string fullName;
cout << "Enter your full name: ";
getline(cin, fullName);
cout << "Hello, " << fullName << "!" << endl;
// Input: "John Doe" -> fullName = "John Doe"
// getline() with custom delimiter
string data;
cout << "Enter comma-separated data: ";
getline(cin, data, ','); // Read until comma
cout << "First part: " << data << endl;
return 0;
}
Common Input Problems
#include <iostream>
#include <string>
#include <limits>
using namespace std;
int main() {
// PROBLEM: Mixing cin >> and getline()
int age;
string name;
cout << "Enter age: ";
cin >> age;
// After cin >>, newline '\n' remains in buffer!
// WRONG: This will read empty string
// getline(cin, name); // Reads the leftover '\n'
// SOLUTION: Clear the buffer first
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Enter name: ";
getline(cin, name);
cout << "Age: " << age << ", Name: " << name << endl;
// Alternative: Use getline() for everything
string ageStr;
cout << "Enter age again: ";
getline(cin, ageStr);
int age2 = stoi(ageStr); // Convert string to int
return 0;
}
String Stream (stringstream)
#include <iostream>
#include <string>
#include <sstream> // For stringstream
using namespace std;
int main() {
// Build string from multiple values
stringstream ss;
ss << "Name: " << "Alice" << ", Age: " << 25;
string result = ss.str();
cout << result << endl; // "Name: Alice, Age: 25"
// Parse string into values
string data = "100 3.14 hello";
stringstream parser(data);
int num;
double pi;
string word;
parser >> num >> pi >> word;
cout << "num: " << num << endl; // 100
cout << "pi: " << pi << endl; // 3.14
cout << "word: " << word << endl; // hello
// Split string by delimiter
string csv = "apple,banana,cherry";
stringstream csvStream(csv);
string token;
cout << "Tokens: ";
while (getline(csvStream, token, ',')) {
cout << "[" << token << "] ";
}
cout << endl; // [apple] [banana] [cherry]
return 0;
}
Practice Questions: Input/Output
Task: Split "Hello World Program" into separate words using stringstream.
Show Solution
#include <sstream>
#include <vector>
string sentence = "Hello World Program";
stringstream ss(sentence);
string word;
vector words;
while (ss >> word) {
words.push_back(word);
}
for (const string& w : words) {
cout << w << endl;
}
// Output:
// Hello
// World
// Program
String Conversions
Converting between strings and numbers is a common task. C++11 introduced
convenient functions like stoi(), stod(), and
to_string() for easy conversions.
#include <iostream>
#include <string>
using namespace std;
int main() {
// STRING TO NUMBER (C++11)
// stoi() - string to int
string numStr = "42";
int num = stoi(numStr);
cout << "stoi: " << num << endl; // 42
// stol() - string to long
string longStr = "1234567890";
long longNum = stol(longStr);
// stoll() - string to long long
string llStr = "9999999999999";
long long llNum = stoll(llStr);
// stof() - string to float
string floatStr = "3.14";
float f = stof(floatStr);
// stod() - string to double
string doubleStr = "3.14159265359";
double d = stod(doubleStr);
cout << "stod: " << d << endl;
// With different bases
string hexStr = "FF";
int hexNum = stoi(hexStr, nullptr, 16); // Base 16
cout << "Hex FF = " << hexNum << endl; // 255
string binStr = "1010";
int binNum = stoi(binStr, nullptr, 2); // Base 2
cout << "Binary 1010 = " << binNum << endl; // 10
return 0;
}
Number to String
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
using namespace std;
int main() {
// to_string() - number to string (C++11)
int num = 42;
string s1 = to_string(num);
cout << "to_string(42): \"" << s1 << "\"" << endl;
double pi = 3.14159;
string s2 = to_string(pi);
cout << "to_string(pi): \"" << s2 << "\"" << endl;
// Note: to_string gives many decimal places
// For formatted output, use stringstream
stringstream ss;
ss << fixed << setprecision(2) << pi;
string s3 = ss.str();
cout << "Formatted: \"" << s3 << "\"" << endl; // "3.14"
// Build complex strings
int age = 25;
string name = "Alice";
string msg = name + " is " + to_string(age) + " years old.";
cout << msg << endl;
return 0;
}
Error Handling in Conversions
#include <iostream>
#include <string>
using namespace std;
int main() {
// Handle invalid conversions
try {
string invalid = "not a number";
int num = stoi(invalid); // Throws exception!
} catch (const invalid_argument& e) {
cout << "Invalid argument: " << e.what() << endl;
} catch (const out_of_range& e) {
cout << "Out of range: " << e.what() << endl;
}
// Partial conversion with position
string mixed = "123abc456";
size_t pos;
int num = stoi(mixed, &pos); // Converts "123"
cout << "Converted: " << num << endl; // 123
cout << "Stopped at position: " << pos << endl; // 3
cout << "Remaining: " << mixed.substr(pos) << endl; // "abc456"
return 0;
}
C-String Conversion
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
// std::string to C-string
string str = "Hello, World!";
// c_str() returns const char* (null-terminated)
const char* cstr = str.c_str();
cout << "c_str(): " << cstr << endl;
// data() also returns const char* (C++11: same as c_str)
const char* data = str.data();
// Copy to char array
char buffer[50];
strcpy(buffer, str.c_str());
// C-string to std::string
const char* source = "C-style string";
string converted = source; // Implicit conversion
string converted2(source); // Explicit constructor
cout << "Converted: " << converted << endl;
return 0;
}
Practice Questions: Conversions
Task: Given "10 20 30", parse and calculate the sum.
Show Solution
#include <sstream>
string nums = "10 20 30";
stringstream ss(nums);
string token;
int sum = 0;
while (ss >> token) {
sum += stoi(token);
}
cout << "Sum: " << sum << endl; // 60
C-String vs std::string
Understanding the differences between C-style strings and std::string
helps you choose the right tool and work with legacy code.
| Feature | C-String (char[]) | std::string |
|---|---|---|
| Memory | Fixed size, manual management | Dynamic, automatic management |
| Size | strlen() or manual count |
.length() or .size() |
| Concatenation | strcat() |
+ or += |
| Comparison | strcmp() |
==, <, > |
| Copy | strcpy() |
= |
| Buffer Overflow | Risk | Safe |
| Null Terminator | Required | Handled internally |
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
// C-STRING WAY
char cstr1[20] = "Hello";
char cstr2[20] = "World";
char cstr3[40];
// Concatenation (unsafe if buffer too small!)
strcpy(cstr3, cstr1);
strcat(cstr3, " ");
strcat(cstr3, cstr2);
cout << "C-string: " << cstr3 << endl;
// Comparison
if (strcmp(cstr1, cstr2) < 0) {
cout << cstr1 << " comes before " << cstr2 << endl;
}
// Length
cout << "Length: " << strlen(cstr1) << endl;
// STD::STRING WAY (PREFERRED)
string str1 = "Hello";
string str2 = "World";
// Concatenation (safe, automatic resize)
string str3 = str1 + " " + str2;
cout << "std::string: " << str3 << endl;
// Comparison (natural operators)
if (str1 < str2) {
cout << str1 << " comes before " << str2 << endl;
}
// Length
cout << "Length: " << str1.length() << endl;
return 0;
}
std::string in modern C++
for safety and convenience. Use C-strings only when interfacing with C libraries or
APIs that require char*.
Key Takeaways
Use std::string
Prefer std::string over C-strings for safety
Easy Operations
Use + for concatenation, == for comparison
Search Methods
find(), rfind(), find_first_of()
Input with getline()
Use getline() for full line input
Conversions
stoi(), stod(), to_string()
Use .at() for Safety
Bounds checking prevents crashes
Knowledge Check
Quick Quiz
Test what you have learned about C++ strings