C++ strings std::string string methods tutorial

C++ Strings: Complete std::string Guide with Examples

Back to C++ RoadmapC++ Programming Course • 65 Lessons

C++ Strings Overview

C++ offers two string systems: C-style character arrays (null-terminated char[]) and std::string from the <string> header. In modern C++, std::string is the default choice. It manages its own memory, knows its own length, supports comparison operators, and integrates with the standard library.

C-strings still appear in legacy code, C APIs, and performance-critical paths. But for day-to-day programming, std::string is safer, more expressive, and almost as fast — especially since move semantics eliminated most copy overhead.

Creating Strings

#include <iostream>
#include <string>
using namespace std;

int main() {
    // From string literal
    string s1 = "Hello, World!";
    string s2("Hello, World!");
    string s3{"Hello, World!"};

    // Empty string
    string empty;
    cout << "Empty length: " << empty.length() << endl;  // 0

    // Repeat a character
    string dashes(40, '-');   // 40 dashes
    cout << dashes << endl;

    // From C-string
    const char* cstr = "C-string";
    string s4(cstr);

    // Substring of another string
    string s5(s1, 0, 5);    // "Hello"
    string s6(s1, 7);       // "World!"

    // From iterators
    string s7(s1.begin(), s1.begin() + 5);  // "Hello"

    cout << s5 << " | " << s6 << " | " << s7 << endl;
    return 0;
}

Accessing Characters

#include <iostream>
#include <string>
using namespace std;

int main() {
    string text = "Hello";

    // operator[] — no bounds checking
    cout << text[0] << endl;   // H
    cout << text[4] << endl;   // o

    // .at() — throws on out-of-bounds
    cout << text.at(1) << endl;  // e
    try { text.at(10); }
    catch (const out_of_range& e) { cout << "Error: " << e.what() << endl; }

    // front() and back()
    cout << "First: " << text.front() << endl;  // H
    cout << "Last:  " << text.back() << endl;   // o

    // Modify characters
    text[0] = 'J';
    text.back() = '!';
    cout << text << endl;  // Jell!

    // C-string access
    const char* raw = text.c_str();   // Null-terminated
    const char* data = text.data();   // Same in C++11+
    cout << raw << endl;

    return 0;
}

Modifying Strings

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "Hello World";

    // append
    s.append("!!!");
    cout << s << endl;  // Hello World!!!

    // insert
    s.insert(5, ",");
    cout << s << endl;  // Hello, World!!!

    // erase
    s.erase(12, 3);     // Remove 3 chars starting at index 12
    cout << s << endl;  // Hello, World

    // replace
    s.replace(7, 5, "C++");
    cout << s << endl;  // Hello, C++

    // push_back / pop_back
    s.push_back('!');
    cout << s << endl;  // Hello, C++!
    s.pop_back();
    cout << s << endl;  // Hello, C++

    // resize
    s.resize(5);
    cout << s << endl;  // Hello

    // clear
    s.clear();
    cout << "Empty: " << s.empty() << endl;  // 1

    return 0;
}

Concatenation

#include <iostream>
#include <string>
using namespace std;

int main() {
    string first = "Hello";
    string last = "World";

    // operator+
    string full = first + ", " + last + "!";
    cout << full << endl;

    // operator+=
    string s = "Count: ";
    s += "1, 2, 3";
    cout << s << endl;

    // append() — same as +=
    string t = "A";
    t.append("BC").append("DE");  // Chainable
    cout << t << endl;  // ABCDE

    // Concatenating with numbers — use to_string()
    int age = 25;
    string msg = "Age: " + to_string(age);
    cout << msg << endl;

    // Using string literals operator (C++14)
    using namespace string_literals;
    auto greeting = "Hello "s + "World"s;  // Both are std::string
    cout << greeting << endl;

    return 0;
}

Comparing Strings

#include <iostream>
#include <string>
using namespace std;

int main() {
    string a = "apple";
    string b = "banana";
    string c = "apple";

    // Comparison operators (lexicographic)
    cout << (a == c) << endl;  // 1 (true)
    cout << (a != b) << endl;  // 1 (true)
    cout << (a < b) << endl;   // 1 (a comes before b)
    cout << (b > a) << endl;   // 1

    // .compare() — returns 0, negative, or positive
    cout << a.compare(c) << endl;  // 0 (equal)
    cout << a.compare(b) << endl;  // negative (a < b)

    // Case-insensitive comparison (no built-in — DIY)
    string x = "Hello", y = "hello";
    auto to_lower = [](string s) {
        for (char& c : s) c = tolower(c);
        return s;
    };
    cout << "Case-insensitive equal: "
         << (to_lower(x) == to_lower(y)) << endl;  // 1

    return 0;
}

Searching and Finding

#include <iostream>
#include <string>
using namespace std;

int main() {
    string text = "The quick brown fox jumps over the lazy dog";

    // find — returns index or string::npos
    size_t pos = text.find("fox");
    if (pos != string::npos) {
        cout << "fox at index " << pos << endl;  // 16
    }

    // rfind — search from the end
    cout << "Last 'the': " << text.rfind("the") << endl;  // 31

    // find_first_of — any character in the set
    cout << "First vowel: " << text.find_first_of("aeiou") << endl;

    // find_last_of
    cout << "Last vowel: " << text.find_last_of("aeiou") << endl;

    // find_first_not_of
    string padded = "   hello   ";
    size_t start = padded.find_first_not_of(' ');
    size_t end = padded.find_last_not_of(' ');
    cout << "Trimmed: [" << padded.substr(start, end - start + 1) << "]" << endl;

    // Count occurrences
    int count = 0;
    size_t p = 0;
    while ((p = text.find("the", p)) != string::npos) {
        count++;
        p += 3;
    }
    cout << "'the' appears " << count << " times" << endl;

    return 0;
}

Substrings and Slicing

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "Hello, World!";

    // substr(start, length)
    string word1 = s.substr(0, 5);    // "Hello"
    string word2 = s.substr(7);       // "World!"
    string word3 = s.substr(7, 5);    // "World"
    cout << word1 << " | " << word2 << " | " << word3 << endl;

    // Split by delimiter
    string csv = "apple,banana,cherry,date";
    size_t start = 0, end;
    while ((end = csv.find(',', start)) != string::npos) {
        cout << csv.substr(start, end - start) << endl;
        start = end + 1;
    }
    cout << csv.substr(start) << endl;  // Last token

    return 0;
}

Number-String Conversions

#include <iostream>
#include <string>
using namespace std;

int main() {
    // Number to string
    string s1 = to_string(42);
    string s2 = to_string(3.14159);
    string s3 = to_string(-100);
    cout << s1 << " | " << s2 << " | " << s3 << endl;

    // String to number
    int n1 = stoi("42");
    long n2 = stol("1000000");
    double n3 = stod("3.14");
    float n4 = stof("2.718");
    cout << n1 << " | " << n2 << " | " << n3 << " | " << n4 << endl;

    // stoi with base
    int hex = stoi("FF", nullptr, 16);   // 255
    int bin = stoi("1010", nullptr, 2);  // 10
    cout << "Hex FF = " << hex << endl;
    cout << "Bin 1010 = " << bin << endl;

    // Error handling
    try {
        int bad = stoi("not_a_number");
    } catch (const invalid_argument& e) {
        cout << "Invalid: " << e.what() << endl;
    }

    return 0;
}

Iterating Over Strings

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    string text = "Hello World";

    // Range-for
    for (char c : text) cout << c << " ";
    cout << endl;

    // Modify with reference
    for (char& c : text) c = toupper(c);
    cout << text << endl;  // HELLO WORLD

    // Algorithm: transform to lowercase
    transform(text.begin(), text.end(), text.begin(), ::tolower);
    cout << text << endl;  // hello world

    // Reverse
    reverse(text.begin(), text.end());
    cout << text << endl;  // dlrow olleh

    // Count specific character
    int spaces = count(text.begin(), text.end(), ' ');
    cout << "Spaces: " << spaces << endl;

    return 0;
}

String Streams

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

int main() {
    // Building strings with ostringstream
    ostringstream oss;
    oss << "Name: " << "Alice" << ", Age: " << 25 << ", GPA: " << 3.95;
    string formatted = oss.str();
    cout << formatted << endl;

    // Parsing with istringstream
    string data = "10 20 30 40 50";
    istringstream iss(data);
    vector<int> nums;
    int n;
    while (iss >> n) {
        nums.push_back(n);
    }
    for (int x : nums) cout << x << " ";
    cout << endl;

    // Split by comma using getline with delimiter
    string csv = "apple,banana,cherry";
    istringstream css(csv);
    string token;
    while (getline(css, token, ',')) {
        cout << "[" << token << "] ";
    }
    cout << endl;

    return 0;
}

std::string_view (C++17)

std::string_view is a lightweight, non-owning reference to a string. It avoids copying when you just need to read a portion of a string.

#include <iostream>
#include <string>
#include <string_view>
using namespace std;

// Accepts string, C-string, or string_view — no copying!
void print_name(string_view name) {
    cout << "Hello, " << name << "!" << endl;
}

int main() {
    string s = "Alice";
    const char* c = "Bob";

    print_name(s);          // From std::string
    print_name(c);          // From C-string
    print_name("Charlie");  // From literal

    // string_view operations (no allocation)
    string_view sv = "Hello, World!";
    cout << sv.substr(0, 5) << endl;        // Hello (returns string_view)
    cout << sv.starts_with("Hello") << endl; // 1 (C++20)

    // WARNING: string_view does NOT own the data
    // Don't return a string_view to a local string!

    return 0;
}

Raw String Literals

#include <iostream>
#include <string>
using namespace std;

int main() {
    // Regular string — must escape backslashes and quotes
    string path = "C:\\Users\\Documents\\file.txt";
    string json = "{\"name\": \"Alice\"}";

    // Raw string literal R"(...)" — no escaping needed
    string raw_path = R"(C:\Users\Documents\file.txt)";
    string raw_json = R"({"name": "Alice", "age": 25})";

    cout << raw_path << endl;
    cout << raw_json << endl;

    // Multi-line raw strings
    string html = R"(
<html>
  <body>
    <h1>Hello</h1>
  </body>
</html>
)";
    cout << html << endl;

    // Custom delimiter for strings containing ")
    string tricky = R"delim(She said "Hello" and typed R"(raw)")delim";
    cout << tricky << endl;

    return 0;
}

Common Mistakes

1. Comparing C-strings with ==:

const char* a = "hello";
const char* b = "hello";
// if (a == b) — compares POINTERS, not content!
// Fix: use strcmp(a, b) == 0, or use std::string

2. Returning string_view to local:

string_view bad() {
    string local = "temporary";
    return local;  // DANGLING — local destroyed after return
}

3. Forgetting that + doesn’t work between two C-strings:

// auto s = "Hello" + " World";  // ERROR: can't add two char arrays
auto s = "Hello"s + " World";    // Fix: make one a std::string

Practice Exercises

Exercise 1: Write a function that checks if a string is a palindrome, ignoring case and non-alphanumeric characters.

Exercise 2: Write a function that counts the number of words in a string.

Exercise 3: Implement a simple find-and-replace function that replaces all occurrences of a substring.

Exercise 4: Write a CSV parser that reads a comma-separated string and returns a vector<vector<string>>.

Summary

std::string is a powerful, safe, and efficient string type that handles memory automatically. You learned creation, access, modification, searching, substrings, number conversions, string streams, and the modern string_view for zero-copy reads. Use std::string by default, string_view for read-only parameters, and C-strings only when interfacing with C APIs. In the next lesson, you will learn structures — your first step toward custom data types.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *