C++ Strings Complete Guide
Functions Reference

C++ Strings: Complete Guide with Built-in Functions

Master the C++ string class with comprehensive examples, built-in functions reference table, and advanced string manipulation techniques.

Creation

String Initialization

Manipulation

Modify & Transform

Search

Find & Replace

Comparison

Compare Strings

Introduction to C++ Strings

C++ provides a powerful string class in the <string> header that makes string handling much easier than C-style character arrays. The string class manages memory automatically and provides numerous member functions for string manipulation.

Key Advantages
  • Automatic memory management
  • Rich set of member functions
  • Operator overloading (+, =, ==, etc.)
  • Compatible with STL algorithms
  • Bounds checking with at()
  • Iterators for traversal
Essential Headers
#include <string>    // string class
#include <iostream>  // Input/output
#include <cctype>    // Character functions
#include <algorithm> // STL algorithms
#include <sstream>   // String streams

C++ string vs C-style strings

C++ string: std::string str = "Hello"; (Safe, feature-rich)
C-style: char str[] = "Hello"; (Manual memory, limited functions)

Basic String Operations
#include <iostream>
#include <string>
using namespace std;

int main() {
    // Creating strings
    string str1 = "Hello, World!";
    string str2("C++ Strings");
    string str3(10, '*');  // "**********"
    
    // Basic operations
    cout << "str1: " << str1 << endl;
    cout << "str2: " << str2 << endl;
    cout << "str3: " << str3 << endl;
    
    // Length and capacity
    cout << "Length of str1: " << str1.length() << endl;
    cout << "Capacity of str1: " << str1.capacity() << endl;
    
    // String concatenation
    string greeting = "Hello" + string(" ") + "World";
    cout << "Greeting: " << greeting << endl;
    
    // String comparison
    if (str1 == "Hello, World!") {
        cout << "Strings are equal" << endl;
    }
    
    // Substring
    string sub = str1.substr(7, 5); // "World"
    cout << "Substring: " << sub << endl;
    
    // Character access
    cout << "First character: " << str1[0] << endl;
    cout << "Last character: " << str1.back() << endl;
    
    return 0;
}

Complete C++ String Functions Reference

The following table provides a comprehensive reference of all C++ string class member functions with examples and descriptions:

Function Syntax Description Return Type
Creation & Initialization
Constructor string() Default constructor, creates empty string constructor
Constructor string(const char* s) From C-style string constructor
Constructor string(size_t n, char c) Creates string of n copies of character c constructor
Copy Constructor string(const string& str) Copy constructor constructor
Capacity Functions
length() str.length() Returns number of characters in string size_t
size() str.size() Same as length() size_t
capacity() str.capacity() Returns size of allocated storage size_t
empty() str.empty() Returns true if string is empty bool
resize() str.resize(n, c) Resizes string to n characters void
reserve() str.reserve(n) Requests capacity change void
shrink_to_fit() str.shrink_to_fit() Reduces capacity to fit size (C++11) void
Element Access
operator[] str[index] Access character (no bounds checking) char&
at() str.at(index) Access character with bounds checking char&
front() str.front() Returns first character (C++11) char&
back() str.back() Returns last character (C++11) char&
Modification Functions
append() str.append(s) Appends string to the end string&
push_back() str.push_back(c) Appends character to the end void
pop_back() str.pop_back() Removes last character (C++11) void
insert() str.insert(pos, s) Inserts string at position pos string&
erase() str.erase(pos, len) Erases characters string&
replace() str.replace(pos, len, s) Replaces portion of string string&
clear() str.clear() Clears the string void
swap() str1.swap(str2) Swaps contents with another string void
String Operations
c_str() str.c_str() Returns C-style string (const char*) const char*
data() str.data() Returns pointer to character array const char*
copy() str.copy(buf, len, pos) Copies characters to char array size_t
substr() str.substr(pos, len) Returns substring string
Search Functions
find() str.find(s, pos) Find content in string size_t
rfind() str.rfind(s, pos) Find last occurrence size_t
find_first_of() str.find_first_of(s, pos) Find character from set size_t
find_last_of() str.find_last_of(s, pos) Find last character from set size_t
find_first_not_of() str.find_first_not_of(s, pos) Find character not in set size_t
find_last_not_of() str.find_last_not_of(s, pos) Find last character not in set size_t
Comparison Functions
compare() str.compare(s) Compares two strings int
operator== str1 == str2 Equality operator bool
operator!= str1 != str2 Inequality operator bool
operator< str1 < str2 Less than operator bool
operator> str1 > str2 Greater than operator bool
Iterators
begin() str.begin() Returns iterator to beginning iterator
end() str.end() Returns iterator to end iterator
rbegin() str.rbegin() Returns reverse iterator reverse_iterator
rend() str.rend() Returns reverse iterator end reverse_iterator
cbegin() str.cbegin() Returns const iterator (C++11) const_iterator
cend() str.cend() Returns const iterator end (C++11) const_iterator

1. String Creation and Initialization

C++ strings can be created and initialized in multiple ways. Understanding these methods is essential for effective string handling.

String Creation Examples
#include <iostream>
#include <string>
using namespace std;

int main() {
    // Method 1: Empty string
    string str1;
    cout << "Empty string: '" << str1 << "' Length: " << str1.length() << endl;
    
    // Method 2: From C-string
    string str2 = "Hello, World!";
    string str3("C++ Programming");
    cout << "str2: " << str2 << endl;
    cout << "str3: " << str3 << endl;
    
    // Method 3: From another string (copy)
    string str4 = str2;
    string str5(str3);
    cout << "str4 (copy of str2): " << str4 << endl;
    cout << "str5 (copy of str3): " << str5 << endl;
    
    // Method 4: Repeat character
    string str6(10, '*');      // "**********"
    string str7(5, 'A');       // "AAAAA"
    cout << "str6: " << str6 << endl;
    cout << "str7: " << str7 << endl;
    
    // Method 5: Substring of another string
    string str8 = "Hello, World!";
    string str9(str8, 7, 5);   // "World" (start at 7, length 5)
    cout << "str9 (substring): " << str9 << endl;
    
    // Method 6: From part of C-string
    string str10("Programming", 4);  // "Prog" (first 4 chars)
    cout << "str10: " << str10 << endl;
    
    // Method 7: Using assignment operator
    string str11;
    str11 = "Assigned string";
    cout << "str11: " << str11 << endl;
    
    // Method 8: Using initializer list (C++11)
    string str12{'H', 'e', 'l', 'l', 'o'};
    cout << "str12 (initializer list): " << str12 << endl;
    
    // Method 9: Move constructor (C++11)
    string str13 = move(str11);  // str11 becomes empty
    cout << "str13 (moved from str11): " << str13 << endl;
    cout << "str11 after move: '" << str11 << "'" << endl;
    
    // Method 10: Using string literals (C++14)
    using namespace std::string_literals;
    string str14 = "Modern C++"s;  // s suffix creates std::string
    auto str15 = "Auto deduction"s; // auto deduces std::string
    cout << "str14: " << str14 << endl;
    cout << "str15: " << str15 << endl;
    
    return 0;
}
Initialization Cheat Sheet
string s1;                // Empty
string s2 = "text";       // From literal
string s3("text");        // Constructor
string s4 = s2;           // Copy
string s5(5, 'x');        // Repeat char
string s6(s2, 1, 3);      // Substring
string s7("text", 2);     // First n chars
string s8{'a', 'b', 'c'}; // Initializer list
auto s9 = "text"s;        // Literal suffix (C++14)

2. String Manipulation Functions

C++ provides numerous functions to modify string content. These functions allow you to append, insert, erase, replace, and transform strings.

String Manipulation Examples
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

int main() {
    string str = "Hello";
    
    // 1. append() - Add to the end
    str.append(" World");
    cout << "After append: " << str << endl; // "Hello World"
    
    // 2. Using += operator (concatenation)
    str += "!";
    cout << "After +=: " << str << endl; // "Hello World!"
    
    // 3. insert() - Insert at position
    str.insert(6, "Beautiful ");
    cout << "After insert: " << str << endl; // "Hello Beautiful World!"
    
    // 4. erase() - Remove characters
    str.erase(6, 10); // Remove "Beautiful "
    cout << "After erase: " << str << endl; // "Hello World!"
    
    // 5. replace() - Replace portion
    str.replace(6, 5, "C++"); // Replace "World" with "C++"
    cout << "After replace: " << str << endl; // "Hello C++!"
    
    // 6. push_back() and pop_back()
    str.push_back('?');
    cout << "After push_back: " << str << endl; // "Hello C++!?"
    
    str.pop_back();
    cout << "After pop_back: " << str << endl; // "Hello C++!"
    
    // 7. clear() - Empty the string
    string temp = "Temporary";
    cout << "Before clear: '" << temp << "'" << endl;
    temp.clear();
    cout << "After clear: '" << temp << "'" << endl;
    
    // 8. resize() - Change size
    string resizeStr = "Hello";
    resizeStr.resize(10, '!'); // Extend with '!'
    cout << "After resize(10, '!'): '" << resizeStr << "'" << endl;
    
    resizeStr.resize(3); // Shrink to first 3 chars
    cout << "After resize(3): '" << resizeStr << "'" << endl;
    
    // 9. swap() - Exchange contents
    string a = "First";
    string b = "Second";
    cout << "Before swap - a: " << a << ", b: " << b << endl;
    a.swap(b);
    cout << "After swap - a: " << a << ", b: " << b << endl;
    
    // 10. assign() - Assign new value
    string assignStr;
    assignStr.assign("New String");
    cout << "After assign: " << assignStr << endl;
    
    assignStr.assign(5, 'X');
    cout << "After assign(5, 'X'): " << assignStr << endl;
    
    // 11. Using STL algorithms with strings
    string algorithmStr = "Hello World";
    
    // Convert to uppercase
    transform(algorithmStr.begin(), algorithmStr.end(), 
              algorithmStr.begin(), ::toupper);
    cout << "Uppercase: " << algorithmStr << endl;
    
    // Convert to lowercase
    transform(algorithmStr.begin(), algorithmStr.end(), 
              algorithmStr.begin(), ::tolower);
    cout << "Lowercase: " << algorithmStr << endl;
    
    // Reverse the string
    reverse(algorithmStr.begin(), algorithmStr.end());
    cout << "Reversed: " << algorithmStr << endl;
    
    // 12. Building strings efficiently
    string builder;
    builder.reserve(50); // Pre-allocate memory
    
    for (int i = 0; i < 10; i++) {
        builder.append("Item ").append(to_string(i)).append(", ");
    }
    cout << "Built string: " << builder << endl;
    
    return 0;
}
Performance Tip: Use reserve() before building large strings with multiple append operations. This reduces memory reallocations and improves performance significantly.

4. String Comparison Functions

C++ provides multiple ways to compare strings, including relational operators and the compare() member function for more detailed comparisons.

String Comparison Examples
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

// Function for case-insensitive comparison
bool caseInsensitiveCompare(const string& a, const string& b) {
    if (a.length() != b.length()) return false;
    
    for (size_t i = 0; i < a.length(); i++) {
        if (tolower(a[i]) != tolower(b[i])) return false;
    }
    return true;
}

int main() {
    string str1 = "apple";
    string str2 = "banana";
    string str3 = "Apple";
    string str4 = "apple";
    
    // 1. Using relational operators
    cout << "Using relational operators:" << endl;
    cout << str1 << " == " << str4 << " : " << (str1 == str4) << endl;
    cout << str1 << " != " << str2 << " : " << (str1 != str2) << endl;
    cout << str1 << " < " << str2 << " : " << (str1 < str2) << endl;
    cout << str2 << " > " << str1 << " : " << (str2 > str1) << endl;
    cout << str1 << " <= " << str4 << " : " << (str1 <= str4) << endl;
    cout << str1 << " >= " << str4 << " : " << (str1 >= str4) << endl;
    
    // 2. Using compare() member function
    cout << "\nUsing compare() function:" << endl;
    
    // compare() returns:
    // 0  : strings are equal
    // <0 : first string is less than second (lexicographically)
    // >0 : first string is greater than second
    
    int result = str1.compare(str2);
    cout << str1 << ".compare(" << str2 << ") = " << result 
         << " (apple < banana)" << endl;
    
    result = str2.compare(str1);
    cout << str2 << ".compare(" << str1 << ") = " << result 
         << " (banana > apple)" << endl;
    
    result = str1.compare(str4);
    cout << str1 << ".compare(" << str4 << ") = " << result 
         << " (apple == apple)" << endl;
    
    // 3. compare() with substring comparison
    string longStr = "Hello World Programming";
    string searchStr = "World";
    
    // Compare part of longStr with searchStr
    result = longStr.compare(6, 5, searchStr); // Compare 5 chars from position 6
    cout << "\nSubstring comparison: " << longStr << ".compare(6, 5, \"World\") = " 
         << result << endl;
    
    // 4. compare() with part of another string
    string strA = "apple pie";
    string strB = "apple tart";
    
    // Compare first 5 chars of both strings
    result = strA.compare(0, 5, strB, 0, 5);
    cout << "\nPartial comparison: \"" << strA << "\".compare(0, 5, \"" 
         << strB << "\", 0, 5) = " << result << endl;
    
    // 5. Case-sensitive vs case-insensitive comparison
    cout << "\nCase sensitivity:" << endl;
    cout << "\"apple\" == \"Apple\" : " << (str1 == str3) << " (case-sensitive)" << endl;
    cout << "caseInsensitiveCompare(\"apple\", \"Apple\") : " 
         << caseInsensitiveCompare(str1, str3) << " (case-insensitive)" << endl;
    
    // 6. Lexicographical comparison examples
    cout << "\nLexicographical comparisons:" << endl;
    
    vector<string> words = {"zebra", "apple", "banana", "cherry", "date"};
    sort(words.begin(), words.end());
    
    cout << "Sorted words: ";
    for (const auto& word : words) {
        cout << word << " ";
    }
    cout << endl;
    
    // 7. Numeric string comparison (potential pitfall)
    string num1 = "100";
    string num2 = "20";
    
    cout << "\nNumeric string comparison (lexicographical):" << endl;
    cout << "\"" << num1 << "\" < \"" << num2 << "\" : " << (num1 < num2) << endl;
    cout << "Note: '1' comes before '2' alphabetically, so \"100\" < \"20\"" << endl;
    
    // 8. Practical example: Sorting strings with custom comparator
    vector<string> names = {"John", "mary", "Alice", "bob", "Zach"};
    
    cout << "\nOriginal names: ";
    for (const auto& name : names) cout << name << " ";
    
    // Sort case-insensitively
    sort(names.begin(), names.end(), [](const string& a, const string& b) {
        string aLower = a, bLower = b;
        transform(aLower.begin(), aLower.end(), aLower.begin(), ::tolower);
        transform(bLower.begin(), bLower.end(), bLower.begin(), ::tolower);
        return aLower < bLower;
    });
    
    cout << "\nCase-insensitive sorted: ";
    for (const auto& name : names) cout << name << " ";
    cout << endl;
    
    // 9. Using compare() for switch-like behavior
    string command = "DELETE";
    
    // Convert to uppercase for case-insensitive comparison
    string cmdUpper = command;
    transform(cmdUpper.begin(), cmdUpper.end(), cmdUpper.begin(), ::toupper);
    
    if (cmdUpper.compare("CREATE") == 0) {
        cout << "\nExecuting CREATE command" << endl;
    } else if (cmdUpper.compare("READ") == 0) {
        cout << "\nExecuting READ command" << endl;
    } else if (cmdUpper.compare("UPDATE") == 0) {
        cout << "\nExecuting UPDATE command" << endl;
    } else if (cmdUpper.compare("DELETE") == 0) {
        cout << "\nExecuting DELETE command" << endl;
    } else {
        cout << "\nUnknown command" << endl;
    }
    
    return 0;
}
Important: String comparison is lexicographical (dictionary order), not numerical. For example, "100" < "20" returns true because '1' comes before '2' in ASCII. Convert to numbers for numerical comparison.

5. String Conversion and Advanced Operations

C++ strings can be converted to other types and combined with other C++ features for powerful text processing.

String Conversion and Advanced Examples
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cctype>
#include <locale> // For std::isspace
using namespace std;

int main() {
    // 1. Converting numbers to strings
    cout << "=== Number to String Conversion ===" << endl;
    
    // Using to_string() (C++11)
    int num = 42;
    double pi = 3.14159;
    
    string strNum = to_string(num);
    string strPi = to_string(pi);
    
    cout << "Integer to string: " << strNum << endl;
    cout << "Double to string: " << strPi << endl;
    
    // Using stringstream
    stringstream ss;
    ss << fixed << setprecision(2) << pi;
    string formattedPi = ss.str();
    cout << "Formatted pi: " << formattedPi << endl;
    
    // 2. Converting strings to numbers
    cout << "\n=== String to Number Conversion ===" << endl;
    
    string strInt = "123";
    string strFloat = "45.67";
    
    int convertedInt = stoi(strInt);
    float convertedFloat = stof(strFloat);
    double convertedDouble = stod(strFloat);
    
    cout << "String to int: " << convertedInt << endl;
    cout << "String to float: " << convertedFloat << endl;
    cout << "String to double: " << convertedDouble << endl;
    
    // Handling invalid conversions
    try {
        string invalid = "123abc";
        int value = stoi(invalid);
        cout << "Parsed: " << value << endl;
    } catch (const invalid_argument& e) {
        cout << "Invalid argument: " << e.what() << endl;
    }
    
    // Using stoi with size_t parameter
    string mixed = "123abc";
    size_t pos;
    int parsed = stoi(mixed, &pos);
    cout << "Parsed number: " << parsed << ", stopped at position: " << pos << endl;
    
    // 3. String stream operations
    cout << "\n=== String Stream Operations ===" << endl;
    
    // Parsing CSV data
    string csv = "John,Doe,30,Engineer";
    stringstream csvStream(csv);
    vector<string> fields;
    string field;
    
    while (getline(csvStream, field, ',')) {
        fields.push_back(field);
    }
    
    cout << "CSV fields: ";
    for (const auto& f : fields) {
        cout << "[" << f << "] ";
    }
    cout << endl;
    
    // Building strings with stringstream
    stringstream builder;
    builder << "Name: " << "John" << ", Age: " << 30 
           << ", Salary: $" << fixed << setprecision(2) << 75000.50;
    
    cout << "Built string: " << builder.str() << endl;
    
    // 4. String trimming functions
    cout << "\n=== String Trimming ===" << endl;
    
    // Left trim
    auto ltrim = [](string& s) {
        s.erase(s.begin(), find_if(s.begin(), s.end(), [](unsigned char ch) {
            return !isspace(ch);
        }));
    };
    
    // Right trim
    auto rtrim = [](string& s) {
        s.erase(find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
            return !isspace(ch);
        }).base(), s.end());
    };
    
    // Trim both sides
    auto trim = [&](string& s) {
        ltrim(s);
        rtrim(s);
    };
    
    string untrimmed = "   Hello World!   ";
    cout << "Original: '" << untrimmed << "'" << endl;
    
    trim(untrimmed);
    cout << "Trimmed: '" << untrimmed << "'" << endl;
    
    // 5. String splitting
    cout << "\n=== String Splitting ===" << endl;
    
    auto split = [](const string& s, char delimiter) -> vector<string> {
        vector<string> tokens;
        stringstream tokenStream(s);
        string token;
        
        while (getline(tokenStream, token, delimiter)) {
            tokens.push_back(token);
        }
        return tokens;
    };
    
    string sentence = "The quick brown fox jumps over the lazy dog";
    vector<string> words = split(sentence, ' ');
    
    cout << "Split words: ";
    for (const auto& word : words) {
        cout << "[" << word << "] ";
    }
    cout << endl;
    
    // 6. String joining
    cout << "\n=== String Joining ===" << endl;
    
    auto join = [](const vector<string>& parts, const string& delimiter) -> string {
        if (parts.empty()) return "";
        
        string result = parts[0];
        for (size_t i = 1; i < parts.size(); i++) {
            result += delimiter + parts[i];
        }
        return result;
    };
    
    vector<string> items = {"Apple", "Banana", "Cherry", "Date"};
    string joined = join(items, ", ");
    cout << "Joined: " << joined << endl;
    
    // 7. String case conversion
    cout << "\n=== Case Conversion ===" << endl;
    
    auto toUpper = [](string s) -> string {
        transform(s.begin(), s.end(), s.begin(), ::toupper);
        return s;
    };
    
    auto toLower = [](string s) -> string {
        transform(s.begin(), s.end(), s.begin(), ::tolower);
        return s;
    };
    
    string mixedCase = "Hello World";
    cout << "Original: " << mixedCase << endl;
    cout << "Uppercase: " << toUpper(mixedCase) << endl;
    cout << "Lowercase: " << toLower(mixedCase) << endl;
    
    // 8. Checking string properties
    cout << "\n=== String Property Checks ===" << endl;
    
    auto isNumeric = [](const string& s) -> bool {
        if (s.empty()) return false;
        
        for (char c : s) {
            if (!isdigit(c)) return false;
        }
        return true;
    };
    
    auto isAlpha = [](const string& s) -> bool {
        if (s.empty()) return false;
        
        for (char c : s) {
            if (!isalpha(c)) return false;
        }
        return true;
    };
    
    string test1 = "12345";
    string test2 = "Hello";
    string test3 = "Hello123";
    
    cout << "'" << test1 << "' is numeric: " << isNumeric(test1) << endl;
    cout << "'" << test2 << "' is alphabetic: " << isAlpha(test2) << endl;
    cout << "'" << test3 << "' is alphabetic: " << isAlpha(test3) << endl;
    
    // 9. String encoding and special characters
    cout << "\n=== Special Characters and Encoding ===" << endl;
    
    // Raw string literals (C++11)
    string rawString = R"(This is a "raw" string\nNo escape sequences needed!)";
    cout << "Raw string: " << rawString << endl;
    
    // Unicode strings (C++11)
    string unicodeStr = u8"Hello 世界"; // UTF-8 encoded
    cout << "Unicode string: " << unicodeStr << endl;
    
    // 10. Performance considerations
    cout << "\n=== Performance Tips ===" << endl;
    
    // Using reserve() for building strings
    string largeString;
    largeString.reserve(1000); // Pre-allocate memory
    
    for (int i = 0; i < 100; i++) {
        largeString.append("Item ").append(to_string(i)).append("\n");
    }
    
    cout << "Built large string with " << largeString.length() << " characters" << endl;
    cout << "Capacity: " << largeString.capacity() << endl;
    
    // Using shrink_to_fit() to reduce memory usage
    largeString.shrink_to_fit();
    cout << "After shrink_to_fit, capacity: " << largeString.capacity() << endl;
    
    return 0;
}
String Performance Tips:
  1. Use reserve() before building large strings with multiple append operations
  2. Use shrink_to_fit() after building to minimize memory usage
  3. Pass strings by const reference to avoid unnecessary copies
  4. Use string_view (C++17) for read-only string parameters
  5. Avoid repeated concatenation with + in loops

6. Best Practices and Common Mistakes

Best Practices
  • Use std::string instead of C-style strings
  • Pass strings by const std::string& for read-only access
  • Use reserve() when building large strings
  • Prefer find() over manual character-by-character search
  • Use empty() instead of size() == 0
  • Handle string::npos properly in search operations
  • Use std::string_view (C++17) for read-only parameters
Common Mistakes
  • Not checking string::npos after find()
  • Using [] operator without bounds checking
  • Forgetting to #include <string>
  • Memory leaks with c_str() pointers
  • Inefficient string concatenation in loops
  • Case-sensitive comparison when case-insensitive is needed
  • Assuming ASCII encoding for international text
Good vs Bad Practices Examples
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
    cout << "=== BAD PRACTICES ===" << endl;
    
    // BAD 1: Not checking bounds
    string str = "Hello";
    // char c = str[10]; // UNDEFINED BEHAVIOR!
    // cout << "Bad access: " << c << endl;
    
    // BAD 2: Inefficient concatenation in loop
    string result;
    for (int i = 0; i < 100; i++) {
        result += "data"; // Creates many temporary strings
    }
    
    // BAD 3: Not checking find() result
    string text = "Hello World";
    size_t pos = text.find("Mars");
    // string sub = text.substr(pos, 5); // CRASH if pos == string::npos
    
    // BAD 4: Using C-style strings unnecessarily
    char cstr[100];
    // strcpy(cstr, text.c_str()); // Risk of buffer overflow
    
    cout << "\n=== GOOD PRACTICES ===" << endl;
    
    // GOOD 1: Safe bounds checking
    if (str.length() > 10) {
        char c = str[10];
        cout << "Safe access: " << c << endl;
    } else {
        cout << "Index out of bounds" << endl;
    }
    
    // Or use at() which throws exception
    try {
        char c = str.at(10);
    } catch (const out_of_range& e) {
        cout << "Caught exception: " << e.what() << endl;
    }
    
    // GOOD 2: Efficient string building
    string efficientResult;
    efficientResult.reserve(500); // Pre-allocate memory
    
    for (int i = 0; i < 100; i++) {
        efficientResult.append("data");
    }
    cout << "Efficiently built string of length: " << efficientResult.length() << endl;
    
    // GOOD 3: Proper find() checking
    pos = text.find("Mars");
    if (pos != string::npos) {
        string sub = text.substr(pos, 5);
        cout << "Found substring: " << sub << endl;
    } else {
        cout << "Substring not found" << endl;
    }
    
    // GOOD 4: Using string functions instead of manual loops
    string data = "Hello,World,OpenAI,ChatGPT";
    
    // GOOD: Using find() and substr()
    vector<string> tokens;
    size_t start = 0, end = 0;
    
    while ((end = data.find(',', start)) != string::npos) {
        tokens.push_back(data.substr(start, end - start));
        start = end + 1;
    }
    tokens.push_back(data.substr(start));
    
    cout << "Parsed tokens: ";
    for (const auto& token : tokens) {
        cout << "[" << token << "] ";
    }
    cout << endl;
    
    // GOOD 5: Using modern C++ features
    // C++17: string_view for read-only parameters
    #if __cplusplus >= 201703L
    cout << "\nC++17 string_view example (compiled with C++17 or later)" << endl;
    #endif
    
    // GOOD 6: Proper error handling for conversions
    string numberStr = "123abc";
    try {
        int value = stoi(numberStr);
        cout << "Converted: " << value << endl;
    } catch (const invalid_argument& e) {
        cout << "Invalid number format: " << numberStr << endl;
    } catch (const out_of_range& e) {
        cout << "Number out of range: " << numberStr << endl;
    }
    
    // GOOD 7: Using empty() for emptiness check
    string emptyStr;
    if (emptyStr.empty()) {
        cout << "String is empty (using empty())" << endl;
    }
    
    // BETTER than: if (emptyStr.size() == 0)
    
    // GOOD 8: Avoiding dangling pointers from c_str()
    string temp = "Temporary";
    const char* ptr = temp.c_str();
    temp = "Modified"; // ptr may become invalid
    
    // SAFE: Use c_str() immediately or store the string
    cout << "Current string: " << temp << endl;
    cout << "Current c_str(): " << temp.c_str() << endl;
    
    return 0;
}