C++ course menu
C++ Strings: std::string Operations, Searching, Substrings and Conversion
Learn std::string in C++: creating and joining strings, length and indexing, looping over characters, substr, find and replace, comparing strings, changing case, splitting with stringstream, and C-style strings vs std::string.
On this page
Text is everywhere: names, messages, file contents, commands. In C++ you work with text using std::string from <string>. A std::string manages its own memory, grows as needed, and comes with methods for searching, slicing and modifying text.
Creating and joining strings#
#include <iostream>
#include <string>
int main() {
std::string first = "Asha";
std::string last = "Rao";
std::string full = first + " " + last; // + joins strings
full += "!"; // += appends
std::cout << full << '\n';
std::cout << "Length: " << full.size() << '\n';
std::cout << std::string(10, '-') << '\n'; // 10 copies of '-'
}Asha Rao!
Length: 9
----------std::string(10, '-') builds a string of ten dashes. size() and length() are two names for the same thing.
Characters and indexing#
Each character has an index, starting at 0. s[i] reads or changes one character; s.at(i) does the same with a bounds check:
#include <iostream>
#include <string>
int main() {
std::string word = "cat";
std::cout << word[0] << ' ' << word.back() << '\n';
word[0] = 'b';
std::cout << word << '\n';
for (char c : word) {
std::cout << c << '-';
}
std::cout << '\n';
}c t
bat
b-a-t-Substrings with substr#
s.substr(start, count) returns a new string of count characters beginning at start. Leave out count to go to the end:
#include <iostream>
#include <string>
int main() {
std::string date = "2026-10-23";
std::string year = date.substr(0, 4);
std::string month = date.substr(5, 2);
std::string day = date.substr(8);
std::cout << day << '/' << month << '/' << year << '\n';
}23/10/2026Searching with find#
s.find(text) returns the index of the first match, or the special value std::string::npos if there is none:
#include <iostream>
#include <string>
int main() {
std::string email = "asha.rao@example.com";
std::size_t at = email.find('@');
if (at != std::string::npos) {
std::cout << "User: " << email.substr(0, at) << '\n';
std::cout << "Domain: " << email.substr(at + 1) << '\n';
}
std::cout << std::boolalpha;
std::cout << (email.find("xyz") == std::string::npos) << '\n';
std::cout << email.ends_with(".com") << '\n'; // C++20
}User: asha.rao
Domain: example.com
true
trueRelated methods: rfind searches from the end, and C++20 adds starts_with and ends_with. C++23 adds contains.
Modifying strings#
#include <iostream>
#include <string>
int main() {
std::string s = "I like tea";
s.replace(s.find("tea"), 3, "coffee"); // replace 3 chars at that position
std::cout << s << '\n';
s.insert(0, "Yes, ");
std::cout << s << '\n';
s.erase(0, 5); // remove 5 chars from index 0
std::cout << s << '\n';
}I like coffee
Yes, I like coffee
I like coffeeComparing strings#
==, !=, < and > compare strings by their characters, in dictionary order (by character code, so uppercase letters come before lowercase ones):
#include <iostream>
#include <string>
int main() {
std::string a = "apple";
std::string b = "banana";
std::cout << std::boolalpha;
std::cout << (a == "apple") << ' ' << (a < b) << ' ' << ("Zebra" < a) << '\n';
}true true true"Zebra" < "apple" is true because 'Z' (90) has a smaller code than 'a' (97). To compare without caring about case, convert both strings to the same case first.
Changing case#
std::toupper and std::tolower (from <cctype>) work on one character at a time:
#include <cctype>
#include <iostream>
#include <string>
std::string to_upper(std::string s) {
for (char& c : s) {
c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
}
return s;
}
int main() {
std::cout << to_upper("Hello, C++!") << '\n';
}HELLO, C++!Taking the parameter by value gives the function its own copy to change and return. The cast to unsigned char avoids undefined behaviour for characters outside the basic ASCII range.
Splitting a string#
std::string has no split method. A common approach reads words from a std::stringstream (from <sstream>), or uses std::getline with a separator:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::stringstream words("practice makes progress");
std::string word;
while (words >> word) {
std::cout << "[" << word << "]";
}
std::cout << '\n';
std::stringstream csv("Asha,Pune,21");
std::vector<std::string> fields;
std::string field;
while (std::getline(csv, field, ',')) {
fields.push_back(field);
}
std::cout << fields[1] << " has " << fields.size() << " fields\n";
}[practice][makes][progress]
Pune has 3 fieldsNumbers and strings#
Convert with std::to_string, std::stoi and std::stod, as shown in Type Conversion. A std::stringstream can also build mixed text, much like std::cout:
#include <iomanip>
#include <iostream>
#include <sstream>
int main() {
std::ostringstream out;
out << "Total: " << std::fixed << std::setprecision(2) << 1234.5;
std::string text = out.str();
std::cout << text << " (" << text.size() << " chars)\n";
}Total: 1234.50 (14 chars)C-style strings#
A string literal like "hello" is actually a C-style string: an array of char ending with an invisible '\0' character. Old C code works with these through char* and functions like strlen. In C++, store text in std::string; it converts from literals automatically and avoids buffer-overflow bugs. If an old API needs a C-style string, s.c_str() provides one.
Common mistakes#
Practice#
Practice exercise
Write bool is_palindrome(const std::string& s) that ignores spaces and letter case, and test it with "Never odd or even" and "C++".
Show solution
#include <cctype>
#include <iostream>
#include <string>
bool is_palindrome(const std::string& s) {
std::string cleaned;
for (char c : s) {
if (c != ' ') {
cleaned += static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
}
}
for (std::size_t i = 0, j = cleaned.size(); i < j; ++i) {
--j;
if (cleaned[i] != cleaned[j]) return false;
}
return true;
}
int main() {
std::cout << std::boolalpha;
std::cout << is_palindrome("Never odd or even") << '\n';
std::cout << is_palindrome("C++") << '\n';
}true
falsePractice exercise
Given std::string sentence = "the quick brown fox";, print it with the first letter of every word capitalized: The Quick Brown Fox.
Show solution
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string sentence = "the quick brown fox";
bool new_word = true;
for (char& c : sentence) {
if (c == ' ') {
new_word = true;
} else if (new_word) {
c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
new_word = false;
}
}
std::cout << sentence << '\n';
}The Quick Brown FoxKey takeaway#
Finished this lesson?