Last 30 Days
No notifications
C++ std::string is a real, dynamic, owning string class โ none of C's manual char* nightmares. It lives in .
#include <string>
using namespace std;string name = "Asha";
name += " Kumar";
cout << name << " has " << name.size() << " characters\n";
string a; // empty
string b = "hello"; // from literal
string c(5, '*'); // "*"
string d{"world"}; // brace init
string e = a + " " + b; // concatenation| Operation | Code |
| Length | s.size() / s.length() |
| Empty? | s.empty() |
| Index | s[i] (no bounds check) / s.at(i) (throws) |
| Append | s += "..." or s.append("...") |
| Substring | s.substr(pos, len) |
| Find | s.find("xyz") (returns string::npos if not found) |
| Replace | s.replace(pos, len, "new") |
| Compare | a == b, a < b (lexicographic) |
| To C string | s.c_str() |
string s = to_string(42); // "42"
int n = stoi("123"); // 123
double d = stod("3.14"); // 3.14for (char c : s) cout << c; // value
for (char& c : s) c = toupper(c); // modify in place
for (size_t i = 0; i < s.size(); ++i) ; // indexed> โ ๏ธ Use size_t (or auto) for string indices โ s.size() returns an unsigned type.
std::string is one of the friendliest tools in C++. It owns its memory, grows automatically, and works seamlessly with STL algorithms.
char*?C-style strings are arrays of char ending in '\0'. Easy to corrupt, easy to overflow, painful to grow.
char a[10] = "hello";
strcat(a, " world!"); // โ buffer overflow โ undefined behaviourstd::string handles all that for you:
string a = "hello";
a += " world!"; // โ
grows automaticallyYou'll only see char* when calling C APIs (use s.c_str() for read-only, s.data() for read-write in C++17+).
string s1; // ""
string s2 = "hi"; // copy from literal
string s3(s2); // copy
string s4(5, 'x'); // "xxxxx"
string s5(s2, 1, 1); // "i" โ substring of s2
string s6{"brace init"}; // C++11+string s = "hello";
s.size(); // 5
s.length(); // 5 (alias of size)
s.empty(); // falses[0]; // 'h' โ fast, no check
s.at(0); // 'h' โ throws std::out_of_range if i >= size
s.front(); // 'h'
s.back(); // 'o'
> Use at() when an out-of-range read is a real possibility (e.g., user input). Use [] in tight loops you've already validated.
s += "!"; // append char or string
s.append(3, 'x'); // s += "xxx"
s.push_back('?'); // append a single char
s.insert(2, "ZZ"); // insert at position 2
s.erase(1, 3); // remove 3 chars from position 1
s.replace(0, 4, "good"); // replace 4 chars with "good"
s.clear(); // make emptystring s = "Hello, World!";
s.substr(7); // "World!" (from pos to end)
s.substr(7, 5); // "World" (from pos, length)size_t i = s.find("World");
if (i == string::npos) cout << "not found";
else cout << "at " << i;| Method | What |
find(x) | first occurrence |
rfind(x) | last occurrence |
find_first_of(chars) | first char in set |
find_first_not_of(chars) | first char NOT in set |
All return string::npos (= -1 cast to size_t) when nothing's found.
"abc" == "abc"; // true (string vs string)
"abc" < "abd"; // true โ lexicographic
s.compare(other); // -1 / 0 / +1 like strcmpstd::string overloads ==, !=, <, <=, >, >= โ comparisons just work.
| Need | Function |
| int โ string | to_string(n) |
| double โ string | to_string(d) |
| string โ int | stoi(s) |
| string โ long long | stoll(s) |
| string โ double | stod(s) |
int n = stoi("42");
string s = to_string(3.14); // note: trailing zeros โ for control use stringstream / formatFor precise control over formatting, use stringstream or C++20's std::format.
for (char c : s) cout << c; // copy each char
for (char& c : s) c = toupper(c); // modify in place
for (const char& c : s) cout << c; // read-only
for (size_t i = 0; i < s.size(); ++i) cout << s[i];> Use 's toupper, tolower, isdigit, isalpha for char tests.
C++ has no split() like Python's. The idiomatic way uses stringstream:
#include <sstream>string line = "alpha,beta,gamma";
stringstream ss(line);
string token;
vector<string> parts;
while (getline(ss, token, ',')) parts.push_back(token);
// parts = {"alpha", "beta", "gamma"}
C++20 added ranges-based string splitting, but stringstream is universal and portable.
vector<string> words = {"one", "two", "three"};
string joined;
for (size_t i = 0; i < words.size(); ++i) {
if (i) joined += ", ";
joined += words[i];
}std::string_view is a non-owning, read-only window into a string. Use it for function parameters that only read:
#include <string_view>bool startsWith(string_view s, string_view prefix) {
return s.size() >= prefix.size()
&& s.compare(0, prefix.size(), prefix) == 0;
}
Avoids copies even when the caller passes a literal, a string, or a sub-range.
> โ ๏ธ Don't store a string_view past the lifetime of its source โ it's a non-owning reference.
| Bug | Cause | |||
| Comparing pointer addresses | if (s == "hi") โ fine for string, but if (cstr == "hi") compares pointers | |||
| Signed/unsigned mismatch | s.size() is unsigned โ for (int i = 0; i < s.size(); ++i) warns | |||
string::npos ignored | Always check before using find's result | |||
stoi on bad input | Throws invalid_argument / out_of_range โ catch if user-supplied | Cheat-Sheet | Need | Code |
| Make | string s = "hi"; | |||
| Length | s.size() | |||
| Append | s += "..." | |||
| Substring | s.substr(i, n) | |||
| Find | s.find("x") (check != string::npos) | |||
| Replace | s.replace(i, n, "y") | |||
| Erase | s.erase(i, n) | |||
| To int | stoi(s) | |||
| From int | to_string(n) | |||
| Iterate | for (char c : s) | |||
| To C-string | s.c_str() |
You now have a string toolkit that handles 99% of real-world text work. Up next: vector, the workhorse container.