Ch10: Char Manipulation / Strings¶
TL;DR: Low-Level C-Strings: C-string คือ Array ของตัวอักษรที่ลงท้ายด้วย Null Terminator (
\0) ซึ่งต้องการการดูแลพื้นที่หน่วยความจำเองและต้องระมัดระวังขอบเขตการเขียนข้อมูลเพื่อไม่ให้เกิด Buffer Overflow
⚡ Quick Reference¶
#include <iostream>
#include <string>
#include <string_view>
#include <cctype>
#include <cstring>
int main() {
// std::string - คลาสเก็บข้อมูลสายอักขระแบบไดนามิกของ C++
std::string str = "Hello C++";
// std::string_view - มุมมองส่องข้อความแบบอ่านอย่างเดียวไม่โคลนข้อมูล (C++17)
std::string_view view = str;
// std::isalnum, std::isalpha, std::isdigit, std::isspace - ตรวจสอบคุณสมบัติตัวอักษร
bool is_letter = std::isalpha('A');
// std::toupper, std::tolower - แปลงประเภทตัวอักษรเป็นพิมพ์ใหญ่หรือพิมพ์เล็ก
char upper = std::toupper('a');
char buffer[20] = "Hello";
// std::strlen - คำนวณหาความยาวของ C-style string
size_t len = std::strlen(buffer);
// std::strcmp - เปรียบเทียบข้อความ C-style string ทางพจนานุกรม
int cmp = std::strcmp(buffer, "Hello");
// std::strcat - ต่อสายอักขระ C-style string
std::strcat(buffer, " World");
// std::strcpy - คัดลอกข้อความ C-style string ไปยังปลายทาง
char dest[20];
std::strcpy(dest, buffer);
return 0;
}
🧠 Core Concepts¶
- Low-Level C-Strings: C-string คือ Array ของตัวอักษรที่ลงท้ายด้วย Null Terminator (
\0) ซึ่งต้องการการดูแลพื้นที่หน่วยความจำเองและต้องระมัดระวังขอบเขตการเขียนข้อมูลเพื่อไม่ให้เกิด Buffer Overflow - Standard String Helper Library: Library
<cctype>และ<cstring>จัดเตรียมฟังก์ชันพื้นฐานสำหรับคัดกรองข้อมูลตัวอักษร (เช่นisalpha,isdigit) และฟังก์ชันจัดการ Buffer (เช่นstrlen,strcpy) - High-Level
std::string&std::string_view: C++ ครอบการจัดการหน่วยความจำด้วยstd::string(ช่วยขยายขนาดเมมโมรี่อัตโนมัติ) และเพิ่มstd::string_viewเพื่อใช้อ่านข้อมูลโดยไม่มีการคัดลอก (Non-owning, read-only)
⚠️ Pitfalls (Quick Scan)¶
| ข้อผิดพลาด | วิธีแก้ |
|---|---|
การตรวจสอบผลลัพธ์ของ std::isalnum กับเลข 1 โดยตรง |
ประเมินผลลัพธ์ในเงื่อนไขแบบ boolean หรือใช้ static_cast<bool> |
ส่งผ่านตัวแปร char ที่มีค่าติดลบไปยังฟังก์ชันกลุ่ม <cctype> | ทำการ Cast ชนิดข้อมูลเป็นunsigned char` ก่อนส่งผ่านฟังก์ชันเสมอ |
|
ใช้คำสั่ง sizeof หาขนาดของ Char Array ที่ลดรูปเป็น Pointer แล้ว |
ใช้ std::strlen ในการนับจำนวนตัวอักษรที่ไม่รวม null terminator |
สั่งเลื่อน Pointer ค้นหาของข้อความต้นทางในลูปค้นหา std::strchr |
ใช้ Pointer ตัวแยกมารับแอดเดรสผลลัพธ์ที่ได้จากการค้นหา และกำหนดให้สายอักขระหลักเป็น read-only |
ใช้ฟังก์ชัน std::strcat หรือ std::strcpy โดยเผื่อขนาดปลายทางไว้ไม่พอ |
มั่นใจว่าขนาด Array ปลายทางใหญ่พอหรือหันไปใช้ std::string แทน |
พยายามป้อน const char[] เป็นตัวแปรปลายทางในการต่อหรือคัดลอกข้อความ C-string |
ป้อนเฉพาะ Array ตัวอักษรที่ไม่ได้เป็นค่าคงที่ (non-const) เท่านั้น |
ใช้ตัวดำเนินการ += เชื่อมข้อมูลตัวเลขจำนวนเต็มเข้ากับ std::string |
ใช้ std::to_string เพื่อแปลงตัวเลขให้เป็นข้อความก่อนนำไปเชื่อมต่อ |
ลืมป้อน Null Terminator ด้วยตนเองหลังใช้ฟังก์ชัน std::strncpy |
ใส่ Null Terminator (\0) ปิดท้ายสายอักขระที่ตำแหน่งสุดท้ายด้วยตนเอง |
พิมพ์ข้อมูลปลายทางที่ได้จากการคัดลอกผ่าน std::string::copy |
ทำ Zero-init ตัวแปรปลายทางก่อน หรือเขียน Null Terminator ทับตำแหน่งสุดท้าย |
นำ String Literal สองตัวมาบวกกันตรงๆ ด้วยเครื่องหมาย + |
มั่นใจว่ามีตัวแปรตัวใดตัวหนึ่งเป็น std::string หรือวางสองข้อความติดกันโดยไม่มีตัวเชื่อม |
เปรียบเทียบค่าระหว่าง std::string กับ Char Array ที่ไม่ได้ลงท้ายด้วย Null Terminator |
ตรวจสอบให้มั่นใจเสมอว่า Array ตัวอักษรลงท้ายด้วย \0 ทุกครั้งก่อนเปรียบเทียบค่า |
ปล่อยให้ std::string_view ทำงานต่อไปหลังจากที่ตัวแปร String หลักหมดอายุแล้ว |
ห้ามใช้ std::string_view หากสายอักขระที่เป็นเจ้าของข้อมูลหลุดพ้นจากขอบเขตสโคปไปแล้ว |
เรียกใช้ std::strlen บนพอยน์เตอร์ข้อมูลของ std::string_view ที่ถูกแก้ไขขนาดแล้ว |
ใช้คำสั่ง sv.length() หรือ sv.size() แทนที่จะไปดึงความยาวดิบจากพอยน์เตอร์ตรงๆ |
📖 Full Details¶
Cause → Effect → Fix พร้อม timestamp (คลิกเพื่อดู)
* **การตรวจสอบผลลัพธ์ของ `std::isalnum` กับเลข `1` โดยตรง** -> **เงื่อนไขอาจเป็นเท็จบนบาง Compiler เนื่องจากฟังก์ชันกลุ่มตรวจคัดกรองจะคืนค่าใดๆ ที่ไม่ใช่ศูนย์เมื่อเป็นจริง (05:54)** -> **ประเมินผลลัพธ์ในเงื่อนไขแบบ boolean หรือใช้ `static_cast📎 Repo Files¶
15.2CharacterManipulation/main.cpp15.3CStringManipulation/main.cpp15.4CStringConcatenationAndCopy/main.cpp15.6DeclaringAndUsingStdString/main.cpp15.7ConcatenatingStdStrings/main.cpp15.8AccessingCharactersInStdString/main.cpp15.9StdStringSizeAndCapacity/main.cpp15.10ModifyingStdStrings/main.cpp15.11ComparingStdStrings/main.cpp15.12StdStringCompare/main.cpp15.13StdStringReplacingCopyingResizingSwapping/main.cpp15.14SearchingStdString/main.cpp15.15TransformingStdStringFromToNumbers/main.cpp15.16EscapeSequences/main.cpp15.17RawStringLiterals/main.cpp15.18CopiedStrings/main.cpp15.19StringView/main.cpp