Giao diện
📝 std::string — Text Handling
std::string là container chuyên cho text — quản lý memory tự động và cung cấp nhiều string operations hữu ích. Tạo String
cpp
#include <string>
#include <iostream>
int main() {
// Empty string
std::string s1;
// From literal
std::string s2 = "Hello";
std::string s3("World");
std::string s4{"Modern C++"}; // C++11
// Repeated character
std::string s5(5, 'x'); // "xxxxx"
// Copy
std::string s6(s2);
// Substring
std::string s7(s2, 1, 3); // "ell" (start=1, len=3)
return 0;
}Basic Operations
Concatenation
cpp
std::string a = "Hello";
std::string b = "World";
// Operator +
std::string c = a + " " + b; // "Hello World"
// Append
a += " C++"; // "Hello C++"
a.append("!"); // "Hello C++!"
// ⚠️ Không thể concat 2 literals trực tiếp
// std::string bad = "Hello" + "World"; // ❌ Error
std::string good = std::string("Hello") + "World"; // ✅Length
cpp
std::string s = "Hello";
size_t len1 = s.size(); // 5 (preferred)
size_t len2 = s.length(); // 5 (same)
bool empty = s.empty(); // falseAccess
cpp
std::string s = "Hello";
char c1 = s[0]; // 'H' — no bounds check
char c2 = s.at(0); // 'H' — with bounds check
char first = s.front(); // 'H'
char last = s.back(); // 'o'
// Modify
s[0] = 'h'; // "hello"Substring Operations
substr()
cpp
std::string s = "Hello World";
std::string sub1 = s.substr(0, 5); // "Hello"
std::string sub2 = s.substr(6); // "World" (từ index 6 đến hết)
std::string sub3 = s.substr(6, 3); // "Wor"find()
cpp
std::string s = "Hello World Wide Web";
// Find first occurrence
size_t pos = s.find("World"); // 6
if (pos != std::string::npos) {
std::cout << "Found at " << pos << std::endl;
}
// Find từ vị trí cụ thể
size_t pos2 = s.find("W", 7); // 12 ("Wide")
// Find last occurrence
size_t pos3 = s.rfind("W"); // 17 ("Web")
// Find character
size_t pos4 = s.find('o'); // 4
// Find any of characters
size_t pos5 = s.find_first_of("aeiou"); // 1 ('e')replace()
cpp
std::string s = "Hello World";
s.replace(6, 5, "C++"); // "Hello C++"
// replace từ index 6, 5 characters, với "C++"
// Replace all occurrences (manual loop)
std::string text = "banana";
size_t pos = 0;
while ((pos = text.find("a", pos)) != std::string::npos) {
text.replace(pos, 1, "o");
++pos;
}
// "bonono"insert() and erase()
cpp
std::string s = "Hello World";
s.insert(5, " Beautiful"); // "Hello Beautiful World"
s.erase(6, 10); // "Hello World"
s.erase(5); // "Hello" (từ index 5 đến hết)Comparison
cpp
std::string a = "apple";
std::string b = "banana";
// Operators
if (a < b) { // Lexicographic comparison
std::cout << "apple comes before banana" << std::endl;
}
if (a == b) { }
if (a != b) { }
// compare() — returns int
int result = a.compare(b);
// < 0: a < b
// = 0: a == b
// > 0: a > b
// Case-insensitive (no built-in, manual)
#include <algorithm>
#include <cctype>
std::string lower_a = a;
std::transform(lower_a.begin(), lower_a.end(), lower_a.begin(), ::tolower);Conversion
String ↔ Number
cpp
#include <string>
// String to number
std::string s1 = "42";
int num1 = std::stoi(s1); // 42
long num2 = std::stol(s1);
double num3 = std::stod("3.14"); // 3.14
// Number to string
int n = 123;
std::string s2 = std::to_string(n); // "123"
double d = 3.14159;
std::string s3 = std::to_string(d); // "3.141590"C-string Interop
cpp
std::string cpp_str = "Hello";
// std::string → C-string
const char* c_str = cpp_str.c_str(); // Null-terminated
const char* data = cpp_str.data(); // C++11: same as c_str()
// C-string → std::string
const char* c = "World";
std::string s(c);String View (C++17)
cpp
#include <string_view>
void printView(std::string_view sv) {
std::cout << sv << std::endl;
}
int main() {
std::string s = "Hello World";
// string_view không copy, chỉ "view" vào data
std::string_view view1(s);
std::string_view view2(s.data(), 5); // "Hello"
printView(s); // ✅ No copy
printView("literal"); // ✅ No copy
return 0;
}📌 Khi nào dùng string_view?
- Read-only access vào string
- Tránh unnecessary copies khi pass vào functions
- CẢNH BÁO: string_view không own data — đảm bảo source string còn sống!
Small String Optimization (SSO)
┌─────────────────────────────────────────────────────────────────┐
│ SMALL STRING OPTIMIZATION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Short strings (≤15-22 chars depending on implementation): │
│ ┌────────────────────────────┐ │
│ │ string object itself │ ← Data stored inline │
│ │ contains the characters │ No heap allocation! │
│ └────────────────────────────┘ │
│ │
│ Long strings: │
│ ┌────────────────────────────┐ ┌─────────────────────┐ │
│ │ ptr | size | capacity │────▶│ "Long string..." │ │
│ └────────────────────────────┘ └─────────────────────┘ │
│ string object heap memory │
│ │
└─────────────────────────────────────────────────────────────────┘SSO giúp short strings rất nhanh vì không cần heap allocation.
Raw String Literals (C++11)
cpp
// Regular string — cần escape
std::string path1 = "C:\\Users\\HPN\\file.txt";
std::string regex1 = "\\d+\\.\\d+";
// Raw string — không cần escape
std::string path2 = R"(C:\Users\HPN\file.txt)";
std::string regex2 = R"(\d+\.\d+)";
// Multi-line
std::string html = R"(
<html>
<body>
<h1>Hello</h1>
</body>
</html>
)";Performance Tips
| Operation | Time Complexity |
|---|---|
size(), empty() | O(1) |
operator[], at() | O(1) |
append(), += | O(m) amortized (m = added length) |
find() | O(n) |
substr() | O(k) (k = substring length) |
Concatenation a + b | O(n+m) (creates new string) |
📌 Best Practice
Với nhiều concatenations, dùng std::ostringstream hoặc pre-reserve() để tránh multiple allocations.
📚 Tổng kết
| Feature | Key Takeaway |
|---|---|
std::string | Thay thế char arrays |
c_str() | Interop với C APIs |
find(), substr() | Text processing |
std::stoi/stod | String ↔ Number |
std::string_view | Zero-copy read-only view (C++17) |
| SSO | Short strings = no heap |
| Raw literals | R"(...)" for special chars |
➡️ Tiếp theo
Tiếp theo: std::map & unordered_map — Key-value storage.
🧠 Quiz
Câu 1: Đoạn code sau in ra gì?
cpp
std::string s = "Hello World";
std::string sub = s.substr(6, 3);
std::cout << sub;- [ ] A)
"Wor" - [x] B)
Wor - [ ] C)
World - [ ] D)
lo W
💡 Giải thích:
substr(pos, len)trích xuất chuỗi con từ vị tríposvới độ dàilen. Vị trí 6 là ký tự 'W', lấy 3 ký tự →"Wor". Nếu chỉ truyềnsubstr(6)thì lấy từ vị trí 6 đến hết →"World".
Câu 2: std::string_view khác std::string ở điểm nào quan trọng nhất?
- [ ] A)
string_viewnhanh hơn vì dùng encoding UTF-8 - [ ] B)
string_viewtự động resize khi cần - [x] C)
string_viewkhông sở hữu data — chỉ "nhìn" vào string có sẵn, không copy - [ ] D)
string_viewchỉ dùng được với string literals
💡 Giải thích:
std::string_view(C++17) là non-owning reference — nó không copy data mà chỉ lưu pointer + length. Điều này tránh allocation khi chỉ cần đọc string. Cảnh báo: phải đảm bảo source string còn sống khi string_view đang được dùng, nếu không sẽ là dangling reference.
Câu 3: Điều gì xảy ra khi chạy code này?
cpp
std::string a = "Hello";
std::string b = "World";
const char* c = (a + b).c_str();
std::cout << c;- [ ] A) In ra
HelloWorldbình thường - [x] B) Undefined Behavior — temporary string đã bị hủy
- [ ] C) Compilation error vì không thể cộng 2 strings
- [ ] D) In ra chuỗi rỗng
💡 Giải thích:
a + btạo một temporary string. Gọi.c_str()trả về pointer vào internal buffer của temporary đó. Nhưng temporary bị hủy ngay sau dòng lệnh, nênctrở thành dangling pointer. Truy cập nó là Undefined Behavior. Cần lưu string vào biến trước:std::string ab = a + b; const char* c = ab.c_str();.