Notifications

No notifications

/Phase 2

std::string โ€” Modern C++ Strings

Strings, Done Right ๐Ÿงต

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";

Building Strings

string a;                       // empty
string b = "hello";             // from literal
string c(5, '*');               // "*"
string d{"world"};              // brace init
string e = a + " " + b;         // concatenation

Common Operations

OperationCode
Lengths.size() / s.length()
Empty?s.empty()
Indexs[i] (no bounds check) / s.at(i) (throws)
Appends += "..." or s.append("...")
Substrings.substr(pos, len)
Finds.find("xyz") (returns string::npos if not found)
Replaces.replace(pos, len, "new")
Comparea == b, a < b (lexicographic)
To C strings.c_str()

Numbers โ†” Strings

string s = to_string(42);        // "42"
int    n = stoi("123");          // 123
double d = stod("3.14");         // 3.14

Iterating

for (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.

On this page

Detailed Theory

std::string is one of the friendliest tools in C++. It owns its memory, grows automatically, and works seamlessly with STL algorithms.

Why Not 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 behaviour

std::string handles all that for you:

string a = "hello";
a += " world!";          // โœ… grows automatically

You'll only see char* when calling C APIs (use s.c_str() for read-only, s.data() for read-write in C++17+).

Construction

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+

Length & Access

string s = "hello";
s.size();        // 5
s.length();      // 5 (alias of size)
s.empty();       // false

s[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.

Modification

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 empty

Substrings

string s = "Hello, World!";
s.substr(7);             // "World!"           (from pos to end)
s.substr(7, 5);          // "World"            (from pos, length)

Searching

size_t i = s.find("World");
if (i == string::npos) cout << "not found";
else                   cout << "at " << i;

MethodWhat
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.

Comparison

"abc" == "abc";         // true (string vs string)
"abc" < "abd";          // true โ€” lexicographic
s.compare(other);        // -1 / 0 / +1 like strcmp

std::string overloads ==, !=, <, <=, >, >= โ€” comparisons just work.

Numbers โ†” Strings

NeedFunction
int โ†’ stringto_string(n)
double โ†’ stringto_string(d)
string โ†’ intstoi(s)
string โ†’ long longstoll(s)
string โ†’ doublestod(s)

int    n = stoi("42");
string s = to_string(3.14);     // note: trailing zeros โ€” for control use stringstream / format

For precise control over formatting, use stringstream or C++20's std::format.

Iteration

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.

Splitting (the missing built-in)

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.

Joining

vector<string> words = {"one", "two", "three"};
string joined;
for (size_t i = 0; i < words.size(); ++i) {
    if (i) joined += ", ";
    joined += words[i];
}

string_view (C++17) โ€” Borrowed View

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.

Common Pitfalls

BugCause
Comparing pointer addressesif (s == "hi") โ€” fine for string, but if (cstr == "hi") compares pointers
Signed/unsigned mismatchs.size() is unsigned โ€” for (int i = 0; i < s.size(); ++i) warns
string::npos ignoredAlways check before using find's result
stoi on bad inputThrows invalid_argument / out_of_range โ€” catch if user-supplied

Cheat-Sheet

NeedCode
Makestring s = "hi";
Lengths.size()
Appends += "..."
Substrings.substr(i, n)
Finds.find("x") (check != string::npos)
Replaces.replace(i, n, "y")
Erases.erase(i, n)
To intstoi(s)
From intto_string(n)
Iteratefor (char c : s)
To C-strings.c_str()

You now have a string toolkit that handles 99% of real-world text work. Up next: vector, the workhorse container.