C++ String Operations

C++’s for String Puzzels
A guide to working with strings in C++
Table of Contents
- 1. Getting Started
- 2. Creating Strings
- 3. Accessing & Measuring
- 4. String Manipulation
- 5. Search & Compare
- 6. Conversions
- 7. Character Utilities
- 8. Essential Patterns
- 9. Practice Problems
- 10. Common Mistakes
1. Getting Started
What is std::string?
graph LR
A[std::string] --> B[Dynamic Array]
A --> C[Automatic Memory]
A --> D[Rich Operations]
B --> E[Can grow/shrink]
C --> F[No manual management]
D --> G[100+ built-in methods]
std::string is a dynamic array that manages its own memory and provides many built-in methods for string operations.
Required headers:
#include <string> // For std::string
#include <cctype> // For isdigit, toupper, etc.
#include <algorithm> // For sort, reverse, etc.
2. Creating Strings
| Method | Code | Result |
|---|---|---|
| String literal | string s = "Hello"; | “Hello” |
| Constructor | string s("Hello"); | “Hello” |
| Empty string | string s; | ”” |
| Repeated char | string s(5, 'A'); | “AAAAA” |
| Copy | string s2 = s1; | Copy of s1 |
| Partial copy | string s(s1, 2, 3); | 3 chars from index 2 |
This table shows different ways to create strings in C++, from simple literals to more complex constructors that repeat characters or copy parts of other strings.
Example:
#include <iostream>
#include <string>
using namespace std;
int main() {
string name = "Alice";
string stars(3, '*');
cout << stars << name << stars; // ***Alice***
return 0;
}
3. Accessing & Measuring
Access Methods Comparison
graph TD
A[Access Character] --> B["s[i]"]
A --> C["s.at(i)"]
A --> D["s.front()"]
A --> E["s.back()"]
B --> F[Fast]
B --> G[No bounds check]
C --> H[Safe]
C --> I[Throws exception]
D --> J[First char]
E --> K[Last char]
The diagram compares different ways to access characters in a string: s[i] is fast but unsafe, s.at(i) is safe but slower, while s.front() and s.back() access the first and last characters.
| Operation | Code | Time | Safe? |
|---|---|---|---|
| Index access | s[0] | O(1) | No |
| Safe access | s.at(0) | O(1) | Yes |
| First char | s.front() | O(1) | No |
| Last char | s.back() | O(1) | No |
| Length | s.length() or s.size() | O(1) | Yes |
| Is empty? | s.empty() | O(1) | Yes |
This table lists common string operations with their time complexity and safety: most are fast (O(1)) but some like s[0] don’t check bounds, while s.at(0) does.
Iteration Guide
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "CODE";
// Method 1: Classic loop
for (int i = 0; i < s.length(); i++)
cout << s[i];
// Method 2: Range-based (recommended)
for (char c : s)
cout << c;
// Method 3: Iterators
for (auto it = s.begin(); it != s.end(); ++it)
cout << *it;
return 0;
}
4. String Manipulation
Substring Extraction Example
Original: "Programming"
0123456789...
substr(0, 4) → "Prog"
substr(3, 4) → "gram"
substr(7) → "ming"
Code:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Programming";
cout << s.substr(0, 4); // "Prog"
cout << s.substr(3, 4); // "gram"
cout << s.substr(7); // "ming"
return 0;
}
Common Operations Table
| Operation | Code | Example |
|---|---|---|
| Append | s += "text" | “Hi” → “Hitext” |
| Insert | s.insert(2, "XX") | “Hi” → “HiXX” |
| Erase | s.erase(1, 2) | “Hello” → “Hlo” |
| Replace | s.replace(0, 2, "YY") | “Hello” → “YYllo” |
| Clear | s.clear() | → “” |
| Reverse | reverse(s.begin(), s.end()) | “Hi” → “iH” |
This table shows basic string manipulation operations: how to add text, insert at positions, remove parts, replace sections, clear the string, or reverse it.
5. Search & Compare
Find Operation Flow
graph LR
A[s.find 'x'] --> B{Found?}
B -->|Yes| C[Returns position]
B -->|No| D[Returns string::npos]
C --> E[Use position]
D --> F[Handle not found]
This flowchart shows how the find function works: it searches for a substring and returns either the position where found or string::npos if not found.
Search Methods:
| Function | Searches from | Example |
|---|---|---|
find() | Beginning → End | s.find("cat") |
rfind() | End → Beginning | s.rfind("cat") |
find_first_of() | First occurrence of any char | s.find_first_of("aeiou") |
find_last_of() | Last occurrence of any char | s.find_last_of("aeiou") |
This table lists different search functions: find() searches forward, rfind() searches backward, while find_first_of() and find_last_of() find any character from a set.
Find pattern:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World";
size_t pos = s.find("World");
if (pos != string::npos) {
cout << "Found at: " << pos; // Found at: 6
} else {
cout << "Not found";
}
return 0;
}
Comparison Operators
| Operator | Meaning | Example |
|---|---|---|
== | Equal | "abc" == "abc" → true |
!= | Not equal | "abc" != "xyz" → true |
< | Less than | "abc" < "xyz" → true |
> | Greater than | "xyz" > "abc" → true |
<= | Less or equal | "abc" <= "abc" → true |
>= | Greater or equal | "abc" >= "abc" → true |
This table shows how to compare strings using standard operators: strings are compared lexicographically (like dictionary order).
6. Conversions
String ↔ Number Flow
graph LR
A[String] -->|stoi, stoll, stod| B[Number]
B -->|to_string| A
style A fill:#e1f5ff
style B fill:#fff4e1
This diagram shows bidirectional conversion between strings and numbers: use stoi/stoll/stod to convert strings to numbers, and to_string to convert numbers back to strings.
Conversion Table:
| From → To | Function | Example |
|---|---|---|
| string → int | stoi() | stoi("42") → 42 |
| string → long long | stoll() | stoll("1234567890") → 1234567890LL |
| string → double | stod() | stod("3.14") → 3.14 |
| int → string | to_string() | to_string(42) → “42” |
| double → string | to_string() | to_string(3.14) → “3.140000” |
This table lists functions to convert between strings and different number types: stoi for integers, stoll for long long, stod for doubles, and to_string for all numbers to strings.
With Error Handling:
#include <iostream>
#include <string>
using namespace std;
int main() {
string input = "123abc";
try {
int num = stoi(input); // Converts "123", ignores "abc"
cout << "Number: " << num;
} catch (invalid_argument& e) {
cout << "Invalid format!";
}
return 0;
}
7. Character Utilities
Character Classification
graph TD
A[Character 'c'] --> B{Check Type}
B --> C[isdigit c]
B --> D[isalpha c]
B --> E[isalnum c]
B --> F[isspace c]
C --> G[0-9?]
D --> H[a-z, A-Z?]
E --> I[Letter or digit?]
F --> J[Space, tab, newline?]
This diagram shows character classification functions: isdigit checks for digits, isalpha for letters, isalnum for letters or digits, and isspace for whitespace characters.
Quick Reference:
| Function | Returns true if… | Example |
|---|---|---|
isdigit(c) | Character is 0-9 | isdigit('5') → true |
isalpha(c) | Character is a-z or A-Z | isalpha('A') → true |
isalnum(c) | Character is alphanumeric | isalnum('7') → true |
isspace(c) | Character is whitespace | isspace(' ') → true |
isupper(c) | Character is uppercase | isupper('A') → true |
islower(c) | Character is lowercase | islower('a') → true |
tolower(c) | Converts to lowercase | tolower('A') → ‘a’ |
toupper(c) | Converts to uppercase | toupper('a') → ‘A’ |
This table lists character utility functions for checking types (like isdigit for numbers) and converting case (tolower/toupper).
Example:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
// Count digits in a string
string s = "abc123xyz456";
int count = 0;
for (char c : s) {
if (isdigit(c)) count++;
}
cout << count; // 6
return 0;
}
8. Essential Patterns
Pattern 1: Frequency Counter
#include <iostream>
#include <string>
using namespace std;
int main() {
// Count each letter's frequency
string s = "hello";
int freq[26] = {0};
for (char c : s) {
freq[c - 'a']++;
}
// freq['h'-'a'] = 1, freq['e'-'a'] = 1, etc.
for (int i = 0; i < 26; i++) {
if (freq[i] > 0) {
cout << char('a' + i) << ": " << freq[i] << endl;
}
}
return 0;
}
Mapping:
Character: a b c d e ...
Index: 0 1 2 3 4 ...
Formula: c - 'a'
LeetCode Problems Using Frequency Counter
| Problem | What it asks (simplified) | Customization |
|---|---|---|
| 383. Ransom Note | Check if ransom note can be built from magazine letters | Count magazine frequencies, then decrement for ransom note. Check if all counts remain ≥ 0. |
| 387. First Unique Character | Find first non-repeating character in string | Count all frequencies, then scan string to find first char with count == 1. |
| 242. Valid Anagram | Check if two strings are anagrams | Count frequencies for both strings, check if all counts match (covered in Pattern 3). |
| 438. Find All Anagrams | Find all starting indices of anagrams in string | Use sliding window with frequency count. Maintain window size = p.length(), slide and compare frequency maps. |
Pattern 2: Two-Pointer Technique
graph LR
A["Start: left=0, right=n-1"] --> B["Compare s[left] vs s[right]"]
B --> C{Equal?}
C -->|Yes| D[Move both pointers inward]
C -->|No| E[Not palindrome]
D --> F{"left < right?"}
F -->|Yes| B
F -->|No| G[Is palindrome]
This flowchart shows the two-pointer technique for palindrome checking: start pointers at ends, compare characters, and move inward until they meet or find a mismatch.
Palindrome Check:
#include <iostream>
#include <string>
using namespace std;
bool isPalindrome(string s) {
int left = 0, right = s.length() - 1;
while (left < right) {
if (s[left] != s[right]) return false;
left++;
right--;
}
return true;
}
int main() {
string test = "racecar";
if (isPalindrome(test)) {
cout << test << " is a palindrome" << endl;
} else {
cout << test << " is not a palindrome" << endl;
}
return 0;
}
Example:
"racecar"
↑ ↑ Compare, both move inward
↑ ↑ Compare, both move inward
↑ ↑ Compare, both move inward
↑ Left >= Right, DONE
LeetCode Problems Using Two-Pointer Technique
| Problem | What it asks (simplified) | Customization |
|---|---|---|
| 125. Valid Palindrome | Check if string reads same forwards and backwards | Skip non-alphanumeric chars, compare lowercase versions from both ends (covered in practice problems). |
| 344. Reverse String | Reverse characters in array in-place | Swap characters from both ends until pointers meet (covered in practice problems). |
| 167. Two Sum II | Find two numbers that sum to target in sorted array | Start pointers at ends, move based on sum comparison (target > sum: move left pointer right, target < sum: move right pointer left). |
| 11. Container With Most Water | Find two lines that form container with maximum water | Calculate area at each step, move the shorter line inward to potentially find larger area. |
| 26. Remove Duplicates | Remove duplicates from sorted array in-place | Use slow pointer to track unique position, fast pointer to scan array. |
Pattern 3: Anagram Detection
flowchart TD
A[Two Strings] --> B[Method 1: Sort Both]
A --> C[Method 2: Count Frequencies]
B --> D["sort both strings"]
B --> E["compare s1 == s2"]
D --> E
E --> F["O(n log n) time"]
C --> G["Create freq array"]
C --> H["Count chars in s1"]
C --> I["Decrement for s2"]
H --> J["Check all counts = 0"]
I --> J
J --> K["O(n) time - FASTER!"]
This flowchart shows two approaches to check if two strings are anagrams: sorting both strings and comparing (slower) vs. counting character frequencies and checking for balance (faster).
Method 1: Sorting
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool isAnagram(string s1, string s2) {
sort(s1.begin(), s1.end());
sort(s2.begin(), s2.end());
return s1 == s2;
}
int main() {
string str1 = "listen";
string str2 = "silent";
if (isAnagram(str1, str2)) {
cout << "Anagrams" << endl;
} else {
cout << "Not anagrams" << endl;
}
return 0;
}
Method 2: Frequency Array (faster)
#include <iostream>
#include <string>
using namespace std;
bool isAnagram(string s1, string s2) {
if (s1.length() != s2.length()) return false;
int freq[26] = {0};
for (char c : s1) freq[c - 'a']++;
for (char c : s2) freq[c - 'a']--;
for (int x : freq)
if (x != 0) return false;
return true;
}
int main() {
string str1 = "listen";
string str2 = "silent";
if (isAnagram(str1, str2)) {
cout << "Anagrams" << endl;
} else {
cout << "Not anagrams" << endl;
}
return 0;
}
LeetCode Problems Using Anagram Detection
| Problem | Difficulty | Customization |
|---|---|---|
| 242. Valid Anagram | Easy | Use frequency counting: count chars in s, decrement for t, check if all counts are zero. |
| 49. Group Anagrams | Medium | Sort each string to create keys, or use frequency count as key in map, group strings with same key. |
| 438. Find All Anagrams | Medium | Use sliding window with frequency count. Maintain window size = p.length(), compare frequency maps at each position. |
| 266. Palindrome Permutation | Easy | Count frequencies, ensure at most one character has odd count (for palindrome possibility). |
9. Practice Problems
Problem 1: Reverse String
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void reverseString(string& s) {
int left = 0, right = s.length() - 1;
while (left < right) {
swap(s[left++], s[right--]);
}
}
int main() {
string s = "hello";
reverseString(s);
cout << s << endl; // "olleh"
// Or using algorithm:
string s2 = "world";
reverse(s2.begin(), s2.end());
cout << s2 << endl; // "dlrow"
return 0;
}
This demonstrates a common string manipulation task used in text processing, cryptography, and data transformation. The two-pointer technique efficiently reverses strings in-place without extra space.
Problem 2: First Unique Character
#include <iostream>
#include <string>
using namespace std;
int firstUniqChar(string s) {
int freq[26] = {0};
for (char c : s)
freq[c - 'a']++;
for (int i = 0; i < s.length(); i++)
if (freq[s[i] - 'a'] == 1) return i;
return -1;
}
int main() {
string s = "leetcode";
int index = firstUniqChar(s);
if (index != -1) {
cout << "First unique character at index: " << index << endl;
} else {
cout << "No unique character found" << endl;
}
return 0;
}
This pattern is crucial for finding unique elements in strings, commonly used in data validation, compression algorithms, and text analysis. It uses frequency counting to identify the first non-repeating character.
Problem 3: Valid Palindrome (Ignore Non-Alphanumeric)
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
bool isPalindrome(string s) {
int left = 0, right = s.length() - 1;
while (left < right) {
while (left < right && !isalnum(s[left])) left++;
while (left < right && !isalnum(s[right])) right--;
if (tolower(s[left]) != tolower(s[right]))
return false;
left++; right--;
}
return true;
}
int main() {
string test = "A man, a plan, a canal: Panama";
if (isPalindrome(test)) {
cout << "Valid palindrome" << endl;
} else {
cout << "Not a palindrome" << endl;
}
return 0;
}
Palindrome checking is essential for string validation in algorithms, word games, and DNA sequence analysis. This implementation ignores case and non-alphanumeric characters for robust text comparison.
Problem 4: Reverse Words
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string reverseWords(string s) {
reverse(s.begin(), s.end()); // Reverse entire string
int n = s.length(), start = 0;
for (int end = 0; end <= n; end++) {
if (end == n || s[end] == ' ') {
reverse(s.begin() + start, s.begin() + end);
start = end + 1;
}
}
return s;
}
int main() {
string s = "the sky is blue";
string result = reverseWords(s);
cout << result << endl; // "blue is sky the"
return 0;
}
Process:
Original: "the sky is blue"
Step 1: "eulb si yks eht" (reverse all)
Step 2: "blue is sky the" (reverse each word)
Word reversal is a key technique in natural language processing, text formatting, and data preprocessing. The approach first reverses the entire string, then reverses each word individually.
Problem 5: Compress String (Run-Length Encoding)
#include <iostream>
#include <string>
using namespace std;
string compress(string s) {
string result;
int count = 1;
for (int i = 1; i <= s.length(); i++) {
if (i < s.length() && s[i] == s[i-1]) {
count++;
} else {
result += s[i-1];
result += to_string(count);
count = 1;
}
}
return result;
}
int main() {
string s = "aaabbcccc";
string compressed = compress(s);
cout << compressed << endl; // "a3b2c4"
return 0;
}
Run-length encoding is a fundamental compression technique used in data storage, image processing, and network protocols. This implementation counts consecutive characters to create a compressed representation.
Problem 6: Remove Spaces
#include <iostream>
#include <string>
using namespace std;
string removeSpaces(string s) {
string result;
for (char c : s) {
if (c != ' ') result += c;
}
return result;
}
// Or replace spaces:
string replaceSpaces(string s) {
string result;
for (char c : s) {
result += (c == ' ') ? "%20" : string(1, c);
}
return result;
}
int main() {
string s = "hello world";
cout << removeSpaces(s) << endl; // "helloworld"
cout << replaceSpaces(s) << endl; // "hello%20world"
return 0;
}
Space removal is a basic text cleaning operation used in data parsing, search functionality, and user input validation. The example shows both complete removal and URL-style replacement.
Problem 7: Extracting URL Parts
Parse a URL to extract the protocol, domain, and path components.
#include <iostream>
#include <string>
using namespace std;
void parseURL(string url) {
// Find protocol (before "://")
size_t protocolEnd = url.find("://");
if (protocolEnd == string::npos) {
cout << "Invalid URL format" << endl;
return;
}
string protocol = url.substr(0, protocolEnd);
// Find domain (after "://" until first "/" or end)
size_t domainStart = protocolEnd + 3;
size_t pathStart = url.find("/", domainStart);
string domain;
string path;
if (pathStart != string::npos) {
domain = url.substr(domainStart, pathStart - domainStart);
path = url.substr(pathStart);
} else {
domain = url.substr(domainStart);
path = "/";
}
cout << "Protocol: " << protocol << endl;
cout << "Domain: " << domain << endl;
cout << "Path: " << path << endl;
}
int main() {
string url = "https://www.example.com/path/to/resource";
parseURL(url);
// Output:
// Protocol: https
// Domain: www.example.com
// Path: /path/to/resource
return 0;
}
URL parsing is critical for web development, network programming, and data extraction. This technique breaks down URLs into components like protocol, domain, and path for further processing.
Problem 8: Transforming Dates in Strings
Convert date formats like “MM/DD/YYYY” to “YYYY-MM-DD” or vice versa.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// Convert MM/DD/YYYY to YYYY-MM-DD
string convertDateFormat(string date) {
// Find positions of slashes
size_t firstSlash = date.find("/");
size_t secondSlash = date.find("/", firstSlash + 1);
if (firstSlash == string::npos || secondSlash == string::npos) {
return "Invalid date format";
}
// Extract month, day, year
string month = date.substr(0, firstSlash);
string day = date.substr(firstSlash + 1, secondSlash - firstSlash - 1);
string year = date.substr(secondSlash + 1);
// Ensure 2-digit month and day
if (month.length() == 1) month = "0" + month;
if (day.length() == 1) day = "0" + day;
// Return in YYYY-MM-DD format
return year + "-" + month + "-" + day;
}
// Convert YYYY-MM-DD to MM/DD/YYYY
string convertDateFormatReverse(string date) {
// Find positions of dashes
size_t firstDash = date.find("-");
size_t secondDash = date.find("-", firstDash + 1);
if (firstDash == string::npos || secondDash == string::npos) {
return "Invalid date format";
}
// Extract year, month, day
string year = date.substr(0, firstDash);
string month = date.substr(firstDash + 1, secondDash - firstDash - 1);
string day = date.substr(secondDash + 1);
// Remove leading zeros
if (month[0] == '0') month = month.substr(1);
if (day[0] == '0') day = day.substr(1);
// Return in MM/DD/YYYY format
return month + "/" + day + "/" + year;
}
int main() {
string date1 = "12/25/2023";
cout << convertDateFormat(date1) << endl; // "2023-12-25"
string date2 = "2023-07-04";
cout << convertDateFormatReverse(date2) << endl; // "7/4/2023"
return 0;
}
Date format conversion is essential for data processing, internationalization, and database operations. The example demonstrates bidirectional conversion between common date formats.
Problem 9: Roman to Decimal
Convert Roman numerals to decimal integers (I=1, V=5, X=10, L=50, C=100, D=500, M=1000).
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
int romanToInt(string s) {
unordered_map<char, int> romanValues = {
{'I', 1}, {'V', 5}, {'X', 10},
{'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}
};
int total = 0;
int prevValue = 0;
// Iterate from right to left
for (int i = s.length() - 1; i >= 0; i--) {
int currentValue = romanValues[s[i]];
// If current value is less than previous (right neighbor),
// subtract it, otherwise add it
if (currentValue < prevValue) {
total -= currentValue;
} else {
total += currentValue;
}
prevValue = currentValue;
}
return total;
}
int main() {
string roman1 = "III"; // 3
string roman2 = "IV"; // 4
string roman3 = "IX"; // 9
string roman4 = "LVIII"; // 58
string roman5 = "MCMXCIV"; // 1994
cout << roman1 << " = " << romanToInt(roman1) << endl;
cout << roman2 << " = " << romanToInt(roman2) << endl;
cout << roman3 << " = " << romanToInt(roman3) << endl;
cout << roman4 << " = " << romanToInt(roman4) << endl;
cout << roman5 << " = " << romanToInt(roman5) << endl;
return 0;
}
The Roman numeral conversion is used in historical data processing, educational software, and legacy system integration. The algorithm handles subtractive notation correctly.
Problem 10: Splitting String into Tokens
Split a string into tokens using multiple possible delimiters (spaces, commas, periods, etc.).
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> splitTokens(const string& s, const string& delimiters) {
vector<string> tokens;
size_t start = 0;
size_t end = 0;
while ((end = s.find_first_of(delimiters, start)) != string::npos) {
// Add token if there's content between delimiters
if (end > start) {
tokens.push_back(s.substr(start, end - start));
}
start = end + 1; // Skip the delimiter
}
// Add the last token if there's remaining content
if (start < s.length()) {
tokens.push_back(s.substr(start));
}
return tokens;
}
// Alternative approach using stringstream (simpler for single delimiters)
#include <sstream>
vector<string> splitBySpace(const string& s) {
vector<string> tokens;
stringstream ss(s);
string token;
while (ss >> token) {
tokens.push_back(token);
}
return tokens;
}
int main() {
string text = "Hello, world! How are you? I'm fine.";
string delimiters = " ,.!?"; // Space, comma, period, exclamation, question mark
vector<string> tokens = splitTokens(text, delimiters);
cout << "Original: " << text << endl;
cout << "Tokens:" << endl;
for (const string& token : tokens) {
cout << "\"" << token << "\"" << endl;
}
// Output:
// "Hello"
// "world"
// "How"
// "are"
// "you"
// "I'm"
// "fine"
// Example with space-only splitting
string sentence = "The quick brown fox jumps over the lazy dog";
vector<string> words = splitBySpace(sentence);
cout << "\nWords:" << endl;
for (const string& word : words) {
cout << word << " ";
}
cout << endl;
return 0;
}
This covers a fundamental string processing technique that’s essential for parsing text data, CSV files, command-line arguments, and many other real-world applications. The example shows splitting a sentence with punctuation into clean word tokens.
10. Common Mistakes
Mistake 1: Off-by-One Errors
// Wrong
for (int i = 0; i <= s.length(); i++) // Goes beyond!
// Correct
for (int i = 0; i < s.length(); i++)
Mistake 2: Modifying While Iterating
// Wrong
for (int i = 0; i < s.length(); i++) {
if (s[i] == 'x') {
s.erase(i, 1); // Changes length!
}
}
// Correct
string result;
for (char c : s) {
if (c != 'x') result += c;
}
s = result;
Mistake 3: Input Buffer Issues
#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
string line;
// ❌ WRONG
cout << "Enter a number: ";
cin >> n;
cout << "Enter a line: ";
getline(cin, line); // Gets empty line because cin leaves newline!
cout << "Line: '" << line << "'" << endl;
// ✅ CORRECT
cout << "Enter another number: ";
cin >> n;
cin.ignore(); // Clear the newline character
cout << "Enter another line: ";
getline(cin, line); // Now works!
cout << "Line: '" << line << "'" << endl;
return 0;
}
When to use what:
| Need | Use | Example |
|---|---|---|
| One word | cin >> s | Input: “Hello World” → s = “Hello” |
| Full line | getline(cin, s) | Input: “Hello World” → s = “Hello World” |
| Multiple words separately | Multiple cin >> | cin >> a >> b |
This table shows different input methods: cin » for single words, getline for entire lines, and multiple cin » for separate words.
Reference
Time Complexity Guide
| Operation | Complexity |
|---|---|
Access s[i] | O(1) |
length() / size() | O(1) |
find() | O(n·m) |
substr() | O(m) |
+ / append | O(n) |
compare() | O(n) |
| Sort string | O(n log n) |
This table shows the time complexity of common string operations: most basic operations are fast (O(1)), while searching and sorting take longer.
Most Used Operations
// Measuring
s.length(), s.size(), s.empty()
// Accessing
s[i], s.at(i), s.front(), s.back()
// Modifying
s += "text", s.append("text"), s.insert(pos, "text")
s.erase(pos, len), s.clear()
// Searching
s.find("text"), s.rfind("text"), s.find(pos) != string::npos
// Substring
s.substr(pos, len)
// Conversion
stoi(s), stoll(s), stod(s), to_string(num)
// Character checks
isdigit(c), isalpha(c), isalnum(c),
tolower(c), toupper(c)
// Algorithms (need <algorithm>)
reverse(s.begin(), s.end())
sort(s.begin(), s.end())
Final Tips
Do:
- Use range-based for loops for readability
- Check
string::nposwhen using find - Use frequency arrays for character counting
- Practice two-pointer technique
- Handle edge cases (empty strings, single char)
Don’t:
- Use
<=in loop conditions with.length() - Modify strings while iterating
- Forget
cin.ignore()aftercin >> - Ignore bounds checking for critical code