C++ provides std::string from <string> "” a full-featured class that manages memory automatically. Unlike C-style char arrays, std::string can grow dynamically, supports operators, and has dozens of useful methods. You never have to worry about buffer overflows or null terminators.
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "Hello";
string s2 = "World";
// Concatenation
string s3 = s1 + ", " + s2 + "!";
cout << s3 << endl; // Hello, World!
// Length
cout << "Length: " << s3.length() << endl; // 13
cout << "Size: " << s3.size() << endl; // same as length()
// Access characters
cout << "First: " << s3[0] << endl; // H
cout << "Last: " << s3.back() << endl; // !
cout << "At(6): " << s3.at(6) << endl; // W (bounds-checked)
// Comparison (lexicographic)
cout << boolalpha;
cout << (s1 == "Hello") << endl; // true
cout << (s1 < s2) << endl; // true (H < W)
// Append
s1 += " there";
cout << s1 << endl; // Hello there
// Empty check
string empty = "";
cout << "Empty: " << empty.empty() << endl; // true
return 0;
}
| Method | Description | Example |
|---|---|---|
substr(pos, len) | Extract substring | "Hello".substr(1,3) → "ell" |
find(str) | Find first occurrence, returns string::npos if not found | s.find("ll") → 2 |
rfind(str) | Find last occurrence | s.rfind('l') → 3 |
replace(pos,len,str) | Replace portion with new string | s.replace(0,5,"Hi") |
erase(pos, len) | Remove characters | s.erase(0, 3) |
insert(pos, str) | Insert at position | s.insert(5, " World") |
c_str() | Convert to C-string (const char*) | s.c_str() |
to_string(n) | Number to string | to_string(42) → "42" |
stoi(s) | String to int | stoi("42") → 42 |
stod(s) | String to double | stod("3.14") → 3.14 |
compare(str) | Lexicographic compare (0 = equal) | s.compare("Hello") |
clear() | Erase all content | s.clear() |
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s = "Hello, World!";
// substr
cout << s.substr(7, 5) << endl; // World
// find "” returns string::npos if not found
size_t pos = s.find("World");
if (pos != string::npos)
cout << "Found at: " << pos << endl; // 7
// replace
s.replace(7, 5, "C++");
cout << s << endl; // Hello, C++!
// Convert to upper/lower using transform
string upper = s;
transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
cout << upper << endl; // HELLO, C++!
string lower = s;
transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
cout << lower << endl; // hello, c++!
// Number conversions
int n = stoi("42");
double d = stod("3.14");
string ns = to_string(100);
cout << n << " " << d << " " << ns << endl; // 42 3.14 100
// Split by delimiter (manual)
string csv = "Alice,Bob,Charlie";
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; // Charlie
return 0;
}
cin >> reads a single word (stops at whitespace). To read an entire line including spaces, use getline(). This is a common source of bugs for beginners.
#include <iostream>
#include <string>
using namespace std;
int main() {
string word, line;
// cin >> reads one word (stops at space/newline)
cout << "Enter a word: ";
cin >> word;
cout << "Word: " << word << endl;
// After cin >>, a '\n' remains in the buffer.
// cin.ignore() discards it before calling getline.
cin.ignore();
// getline reads the entire line including spaces
cout << "Enter a full name: ";
getline(cin, line);
cout << "Full name: " << line << endl;
// getline with custom delimiter "” reads until ';'
string token;
// (simulating reading from a stream)
// getline(cin, token, ';');
// Reading multiple lines in a loop
// while (getline(cin, line)) {
// cout << "Line: " << line << endl;
// }
return 0;
}
// Input: Hello
// John Doe
// Output: Word: Hello
// Full name: John Doe
std::stringstream (from <sstream>) lets you treat a string like a stream "” useful for parsing tokens from a string or building a string from multiple values without repeated concatenation.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main() {
// --- Building a string from mixed types ---
stringstream ss;
ss << "Name: " << "Alice" << ", Age: " << 30 << ", GPA: " << 3.95;
string result = ss.str();
cout << result << endl;
// Name: Alice, Age: 30, GPA: 3.95
// --- Parsing space-separated tokens ---
string sentence = "the quick brown fox";
stringstream parser(sentence);
string token;
vector<string> words;
while (parser >> token) {
words.push_back(token);
}
cout << "Word count: " << words.size() << endl; // 4
for (const auto &w : words) cout << "[" << w << "] ";
cout << endl;
// --- Parsing CSV line ---
string csv = "42,3.14,hello";
stringstream csvStream(csv);
int i; double d; string s;
char comma;
csvStream >> i >> comma >> d >> comma >> s;
cout << i << " | " << d << " | " << s << endl; // 42 | 3.14 | hello
// --- Convert string to number (alternative to stoi) ---
string numStr = "255";
int num;
stringstream(numStr) >> num;
cout << "Parsed: " << num << endl; // 255
return 0;
}
std::string_view (from <string_view>) is a non-owning, read-only reference to a string or substring. It avoids copying when you only need to read string data "” ideal for function parameters that accept both std::string and string literals without allocation.
#include <iostream>
#include <string>
#include <string_view>
using namespace std;
// Accepts both std::string and const char* "” no copy made
void printLength(string_view sv) {
cout << "\"" << sv << "\" has " << sv.length() << " chars" << endl;
}
// Efficient substring "” no allocation, just a view into existing data
string_view firstWord(string_view sv) {
size_t pos = sv.find(' ');
return sv.substr(0, pos); // returns a view, not a new string
}
int main() {
// Works with string literals (no allocation)
printLength("Hello, World!"); // "Hello, World!" has 13 chars
// Works with std::string (no copy)
string s = "C++ is fast";
printLength(s); // "C++ is fast" has 11 chars
// Substring view "” zero allocation
string_view fw = firstWord("quick brown fox");
cout << "First word: " << fw << endl; // quick
// string_view supports most read operations
string_view sv = "Hello, World!";
cout << sv.substr(7, 5) << endl; // World
cout << sv.starts_with("Hello") << endl; // 1 (C++20)
cout << sv.ends_with("!") << endl; // 1 (C++20)
// WARNING: string_view does NOT own the data.
// Never return a string_view to a local string!
// string_view danger() {
// string local = "oops";
// return local; // DANGLING REFERENCE "” undefined behaviour
// }
return 0;
}
| Feature | C-Style (char[] / char*) | std::string |
|---|---|---|
| Memory management | Manual (fixed buffer or malloc/free) | Automatic (dynamic, grows as needed) |
| Null terminator | Required ('\0') | Handled internally |
| Concatenation | strcat() "” unsafe | + or += "” safe |
| Comparison | strcmp() | ==, <, > |
| Length | strlen() "” O(n) | .length() "” O(1) |
| Buffer overflow risk | High (no bounds checking) | None (.at() throws on bad index) |
| Interop with C APIs | Direct | Use .c_str() |
| Performance | Slightly faster for small fixed strings | SSO (Small String Optimisation) in modern compilers |
These are classic string manipulation problems that appear frequently in interviews and competitive programming.
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
// Reverse a string
string reverseStr(string s) {
reverse(s.begin(), s.end());
return s;
}
// Check if a string is a palindrome (case-insensitive)
bool isPalindrome(string s) {
// Normalise: lowercase, remove non-alphanumeric
string clean;
for (char c : s)
if (isalnum(c)) clean += tolower(c);
string rev = clean;
reverse(rev.begin(), rev.end());
return clean == rev;
}
// Count vowels in a string
int countVowels(const string &s) {
int count = 0;
for (char c : s)
if (string("aeiouAEIOU").find(c) != string::npos)
count++;
return count;
}
// Count occurrences of a substring
int countOccurrences(const string &text, const string &pattern) {
int count = 0;
size_t pos = 0;
while ((pos = text.find(pattern, pos)) != string::npos) {
count++;
pos += pattern.length();
}
return count;
}
int main() {
cout << reverseStr("Hello") << endl; // olleH
cout << reverseStr("C++ Rocks") << endl; // skcoR ++C
cout << boolalpha;
cout << isPalindrome("racecar") << endl; // true
cout << isPalindrome("A man a plan a canal Panama") << endl; // true
cout << isPalindrome("hello") << endl; // false
cout << "Vowels in 'Hello World': "
<< countVowels("Hello World") << endl; // 3
cout << "Occurrences of 'is' in 'this is a test': "
<< countOccurrences("this is a test", "is") << endl; // 2
return 0;
}
cin >> stops at whitespace, so it only reads one word. Use getline(cin, str) to read an entire line including spaces. Always call cin.ignore() before getline if a previous cin >> left a newline in the buffer.
#include <iostream>
#include <string>
using namespace std;
int main() {
// cin >> reads ONE word (stops at space)
string firstName;
cout << "First name: ";
cin >> firstName;
cout << "Got: " << firstName << endl;
// cin.ignore() discards the leftover '\n' in the buffer
cin.ignore();
// getline reads the ENTIRE line including spaces
string fullName;
cout << "Full name: ";
getline(cin, fullName);
cout << "Got: " << fullName << endl;
// getline with custom delimiter (read until comma)
string token;
// getline(cin, token, ',');
// Read multiple lines until empty line
string line;
cout << "Enter lines (empty line to stop):" << endl;
while (getline(cin, line) && !line.empty()) {
cout << " > " << line << endl;
}
return 0;
}
std::stringstream from <sstream> lets you treat a string like a stream "” perfect for parsing tokens from a string or building a string from mixed types without manual concatenation.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main() {
// --- Build a string from mixed types ---
int age = 25;
double gpa = 3.85;
string name = "Alice";
ostringstream oss;
oss << name << " | Age: " << age << " | GPA: " << gpa;
string result = oss.str();
cout << result << endl;
// Alice | Age: 25 | GPA: 3.85
// --- Parse tokens from a string ---
string sentence = "the quick brown fox";
istringstream iss(sentence);
string word;
vector<string> words;
while (iss >> word) {
words.push_back(word);
}
cout << "Word count: " << words.size() << endl; // 4
for (const auto &w : words) cout << "[" << w << "] ";
cout << endl;
// --- Parse CSV line ---
string csv = "Alice,30,Engineer";
stringstream ss(csv);
string token;
while (getline(ss, token, ',')) {
cout << token << endl;
}
// Alice
// 30
// Engineer
// --- Convert string to number ---
string numStr = "42";
int n;
stringstream(numStr) >> n;
cout << "Parsed: " << n + 1 << endl; // 43
return 0;
}
std::string_view (C++17) is a non-owning, read-only reference to a string or substring. It avoids copying when you only need to read a string "” ideal for function parameters that don't need to own or modify the string.
#include <iostream>
#include <string>
#include <string_view> // C++17
using namespace std;
// Takes string_view "” works with string, const char*, string literals
// No copy made "” just a pointer + length
void printLength(string_view sv) {
cout << "\"" << sv << "\" has " << sv.length() << " chars" << endl;
}
// Compare: passing by const string& would copy if called with a literal
void printLengthOld(const string &s) {
cout << s.length() << endl;
}
int main() {
string s = "Hello, World!";
const char *cstr = "C-style string";
printLength(s); // no copy
printLength(cstr); // no copy
printLength("literal"); // no copy
// Substring view "” no allocation!
string_view sv = s;
string_view sub = sv.substr(0, 5); // "Hello" "” no copy
cout << sub << endl;
// Common methods
cout << sv.starts_with("Hello") << endl; // true (C++20)
cout << sv.ends_with("!") << endl; // true (C++20)
cout << sv.find("World") << endl; // 7
// CAUTION: string_view does NOT own the data
// Never return a string_view to a local string!
// string_view bad() { string s = "hi"; return s; } // DANGLING!
return 0;
}
// Compile: g++ -std=c++17 string_view.cpp -o sv
| Feature | C-style (char[]) | std::string |
|---|---|---|
| Memory | Fixed size, manual | Dynamic, automatic |
| Null terminator | Required (\0) | Handled internally |
| Concatenation | strcat() | s1 + s2 or += |
| Length | strlen() | s.length() |
| Comparison | strcmp() | s1 == s2 |
| Copy | strcpy() | s2 = s1 |
| Buffer overflow risk | Yes "” dangerous | No "” safe |
| STL compatibility | Limited | Full |
| Prefer in modern C++ | No (only for C interop) | Yes |
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
// Reverse a string
string reverseStr(string s) {
reverse(s.begin(), s.end());
return s;
}
// Check palindrome
bool isPalindrome(const string &s) {
string rev = s;
reverse(rev.begin(), rev.end());
return s == rev;
}
// Count vowels
int countVowels(const string &s) {
int count = 0;
for (char c : s) {
char lower = tolower(c);
if (lower == 'a' || lower == 'e' || lower == 'i' ||
lower == 'o' || lower == 'u') count++;
}
return count;
}
// Remove spaces
string removeSpaces(string s) {
s.erase(remove(s.begin(), s.end(), ' '), s.end());
return s;
}
// Trim leading/trailing whitespace
string trim(const string &s) {
size_t start = s.find_first_not_of(" \t\n\r");
size_t end = s.find_last_not_of(" \t\n\r");
return (start == string::npos) ? "" : s.substr(start, end - start + 1);
}
int main() {
cout << reverseStr("Hello") << endl; // olleH
cout << boolalpha;
cout << isPalindrome("racecar") << endl; // true
cout << isPalindrome("hello") << endl; // false
cout << countVowels("Hello World") << endl; // 3
cout << removeSpaces("H e l l o") << endl; // Hello
cout << "[" << trim(" hello ") << "]" << endl; // [hello]
return 0;
}
Explore 500+ free tutorials across 20+ languages and frameworks.