- 1 1. บทนำ
- 2 2. สตริงในภาษา C คืออะไร? แนวคิดพื้นฐานและความสำคัญของอักขระสิ้นสุด
- 3 3. วิธีการตัดสตริงย่อยในภาษา C 【ส่วนของไลบรารีมาตรฐาน】
- 4 4. วิธีการตัดส่วนย่อยของสตริงใน C-gengo 【Jisaku kansū hen】
- 5 5. วิธีการตัดสตริงตามรหัสอักขระ
- 6 6. วิธีการแบ่งสตริงในภาษา C
- 7 7. ตัวอย่างการประยุกต์: วิธีการดึงข้อความก่อนและหลังอักขระเฉพาะ
- 8 8. สรุป
1. บทนำ
การจัดการสตริงในภาษา C เป็นหนึ่งในทักษะสำคัญสำหรับการเรียนรู้การเขียนโปรแกรม โดยเฉพาะ การตัดสตริง(การสกัดส่วนของสตริง)มักใช้บ่อยเมื่อทำการประมวลผลข้อมูลหรือแปลงรูปแบบ
ในบทความนี้ เราจะอธิบายอย่างละเอียดเกี่ยวกับ วิธีการตัดสตริงในภาษา C รวมถึง การใช้ฟังก์ชันไลบรารีมาตรฐาน, การสร้างฟังก์ชันของตนเอง, การรองรับอักขระหลายไบต์ (ภาษาญี่ปุ่น), วิธีการแบ่งสตริง เป็นต้น อีกทั้งยังแนะนำตัวอย่างการประยุกต์ใช้และการจัดการข้อผิดพลาด ดังนั้นกรุณาอ่านจนจบ
สิ่งที่คุณจะได้เรียนรู้ในบทความนี้
โดยการอ่านบทความนี้ คุณจะสามารถเรียนรู้ทักษะต่อไปนี้
- แนวคิดพื้นฐานของสตริงในภาษา C และตัวอักขระจบ มีบทบาท
strncpy
strchr
ฟังก์ชันไลบรารีมาตรฐานที่ใช้ในการตัดสตริงย่อย- ฟังก์ชันที่สร้างขึ้นเอง
- พิจารณาอักขระหลายบิต (ภาษาญี่ปุ่น)
strtok
วิธีการแบ่งสตริง- วิธีการดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด
เราจะอธิบายพร้อมตัวอย่างโค้ดเพื่อให้ผู้เริ่มต้นเข้าใจง่าย
ทำไมการตัดสตริงในภาษา C จึงสำคัญ?
ภาษา C จะจัดการสตริงเป็น อาเรย์ (อาเรย์ของชนิด char) ดังนั้นจึงไม่สามารถดึงส่วนของสตริงได้อย่างง่ายดายเหมือนภาษาระดับสูงอื่น ๆ (เช่น Python หรือ JavaScript) ดังนั้นการเลือกวิธีที่เหมาะสมในสถานการณ์ต่อไปนี้จึงสำคัญ
1. การประมวลผลข้อมูลเข้า
เช่น เมื่อวิเคราะห์ข้อมูลเช่นล็อกหรือไฟล์ CSV จำเป็นต้องสกัดข้อมูลเฉพาะบางส่วน
2. การค้นหาคำสำคัญเฉพาะ
การค้นหาคำสำคัญในสตริงและดึงข้อมูลก่อนและหลังเป็นสิ่งจำเป็นสำหรับฟังก์ชันการค้นหาและการสกัดข้อมูล
3. การเพิ่มความปลอดภัยของโปรแกรม
โดยการใช้ฟังก์ชันเช่น strncpy
อย่างเหมาะสม สามารถป้องกัน การโอเวอร์ฟลว์ของบัฟเฟอร์ (การเขียนข้อมูลเกินขนาดบัฟเฟอร์) ได้ ซึ่งสำคัญเพื่อหลีกเลี่ยงความเสี่ยงด้านความปลอดภัย.
โครงสร้างของบทความนี้
ในบทความนี้ เราจะอธิบายตามลำดับต่อไปนี้
- C ภาษาโปรแกรม C คืออะไร? แนวคิดพื้นฐานและความสำคัญของอักขระจบสตริง
- วิธีตัดสตริงย่อยในภาษา C【ฉบับไลบรารีมาตรฐาน】
- วิธีตัดสตริงย่อยในภาษา C【ส่วนที่เขียนฟังก์ชันเอง】
- วิธีการตัดสตริงตามรหัสอักขระ
- วิธีการแบ่งสตริงด้วยภาษา C
- ตัวอย่างการใช้งาน: วิธีดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด
- สรุป
- FAQ
ดังนั้น เรามาเริ่มต้นด้วยการดูรายละเอียดเกี่ยวกับ “สตริงในภาษา C คืออะไร? แนวคิดพื้นฐานและความสำคัญของอักขระสิ้นสุด” กันเถอะ.
2. สตริงในภาษา C คืออะไร? แนวคิดพื้นฐานและความสำคัญของอักขระสิ้นสุด
2.1 แนวคิดพื้นฐานของสตริงในภาษา C
สตริงคือ “อาเรย์ของ char”
ในภาษา C จะจัดการสตริงเป็นอาเรย์ของอักขระ (อาเรย์ของประเภท char)เป็นอาเรย์ของอักขระ ตัวอย่างเช่น โค้ดด้านล่างเป็นตัวอย่างพื้นฐานของการกำหนดและแสดงสตริง
#include <stdio.h>
int main() {
char str[] = "Hello, World!"; // Define a string literal as an array
printf("%s ", str); // Output the string
return 0;
}
ในโค้ดนี้ "Hello, World!"
จะถูกเก็บเป็นอาเรย์ของชนิด char
และจะถูกแสดงผลโดย printf("%s\n", str);
โครงสร้างภายในของสตริง
สตริง "Hello"
จะถูกจัดเก็บในหน่วยความจำดังต่อไปนี้
ดัชนี | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
ข้อความ | H | e | l | l | o | \0 |
ในภาษา C อักขระพิเศษที่บ่งบอกจุดสิ้นสุดของสตริง (null character '\0'
) จะถูกเพิ่มโดยอัตโนมัติที่ส่วนท้าย ดังนั้นความยาวของสตริงจะเป็น 「จำนวนอักขระจริง + 1」
2.2 ความสำคัญของอักขระสิ้นสุด(อักขระนัล 'null character คืออะไร?
'
)
null character คืออะไร?
'ปัญหาเมื่อไม่มี null character
null character('\0'
)เป็นอักขระพิเศษที่บ่งบอกจุดสิ้นสุดของสตริง เพื่อให้จัดการสตริงในภาษา C อย่างถูกต้อง จำเป็นต้องเข้าใจการมีอยู่ของ null character นี้
#include <stdio.h>
int main() {
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicitly specify the null terminator
printf("%s ", str); // Display correctly
return 0;
}
ในโค้ดข้างต้น หากไม่มี '\0'
จะไม่สามารถรับรู้จุดสิ้นสุดของ "Hello"
ทำให้ อาจเกิดพฤติกรรมที่ไม่คาดคิด
2.3 วิธีการกำหนดสตริงอย่างถูกต้อง
เช่น หากลืมใส่ อักขระสิ้นสุด อาจทำให้หน่วยความจำทำงานผิดปกติ
#include <stdio.h>
int main() {
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // Does not include the null terminator
printf("%s ", str); // May cause unexpected behavior
return 0;
}
สาเหตุของข้อผิดพลาด
printf("%s\n", str);
จะพิมพ์ตัวอักษรต่อเนื่องจนกว่าจะพบอักขระศูนย์'\0'
- ถ้า ไม่ได้ มีความเป็นไปได้ที่ข้อมูลอื่น ๆ บนหน่วยความจำจะถูกแสดงออกมา。
วิธี① ใช้ string literal
วิธี② กำหนดอาเรย์อย่างชัดเจน
วิธีการกำหนดสตริงที่พบมากที่สุดคือการใช้ string literal
char str[] = "Hello";
ในวิธีนี้ คอมไพเลอร์ C จะเพิ่ม null character '\0'
ให้โดยอัตโนมัติ ดังนั้นไม่ต้องทำการประมวลผลพิเศษใดๆ
2.4 วิธีตรวจสอบขนาดของสตริง
หากกำหนดด้วยตนเองรวมถึง '\0'
ให้เขียนดังนี้
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
- จำนวนตัวอักษร กำหนดขนาด และใส่ ที่ท้ายเป็นสิ่งสำคัญ。
- ถ้าไม่ใส่ เข้าไปใน จะเกิดพฤติกรรมที่ไม่คาดคิดขึ้น。
การทำงานของ strlen
เพื่อรับความยาวของสตริง (จำนวนอักขระ) ให้ใช้ฟังก์ชัน strlen
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello";
printf("Length of the string: %lu\n", strlen(str)); // Outputs 5 (does not include the null terminator)
return 0;
}
2.5 สรุป
strlen
'\0'
นับจำนวนตัวอักษรจนถึงตัวอักษร nullsizeof(str)
3. วิธีการตัดสตริงย่อยในภาษา C 【ส่วนของไลบรารีมาตรฐาน】
- สตริงในภาษา C คือ
char
แสดงด้วยอาร์เรย์ - อักขระจบ (อักขระศูนย์
'\0'
) บ่งบอกจุดสิ้นสุดของสตริง ดังนั้นจึงต้องรวมไว้เสมอ - เพื่อรับความยาวของสตริง
strlen
ใช้ - หากไม่ได้กำหนดสตริงด้วยวิธีที่เหมาะสม อาจเกิดข้อผิดพลาดที่ไม่คาดคิดได้
3.1 การรับสตริงย่อยด้วย strncpy
เพื่อการตัดสตริงย่อยในภาษา C มีวิธีการใช้ไลบรารีมาตรฐาน ในส่วนนี้ เราจะอธิบายการใช้ฟังก์ชันไลบรารีมาตรฐานอย่าง strncpy
และ strchr
เป็นต้น เพื่อดึงสตริงแบบบางส่วน
โครงสร้างพื้นฐานของ strncpy
strncpy
เป็นฟังก์ชันที่คัดลอกส่วนหนึ่งของสตริงไปยังบัฟเฟอร์อื่น
ตัวอย่างการใช้งานพื้นฐาน
char *strncpy(char *dest, const char *src, size_t n);
dest
src
n
'\0'
ข้อควรระวังของ strncpy
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6]; // Buffer to store the substring
strncpy(dest, src, 5); // Copy the first 5 characters "Hello"
dest[5] = '\0'; // Manually add the null terminator
printf("Substring: %s\n", dest); // Output "Hello"
return 0;
}
3.2 การคัดลอกสตริงอย่างปลอดภัยด้วย strncpy_s
- อักขระศูนย์
'\0'
ต้องเพิ่มด้วยตนเองstrncpy
n
'\0'
ไม่เพิ่มอัตโนมัติdest[n] = '\0';
- ระวังการล้นบัฟเฟอร์
dest
n
โครงสร้างพื้นฐานของ strncpy_s
strncpy_s
เป็นเวอร์ชันที่เสริมความปลอดภัยของ strncpy
เพื่อป้องกันการโอเวอร์ฟลอว์ของบัฟเฟอร์
ตัวอย่างการใช้งาน
errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
dest
destsz
dest
src
n
ข้อดีของ strncpy_s
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
if (strncpy_s(dest, sizeof(dest), src, 5) == 0) {
dest[5] = '\0'; // Add null terminator just in case
printf("Substring: %s\n", dest);
} else {
printf("Copy error\n");
}
return 0;
}
3.3 การตัดสตริงจนถึงอักขระที่กำหนดด้วย strchr
- ขนาดบัฟเฟอร์ () เพื่อกำหนด ทำให้สามารถคัดลอกได้อย่างปลอดภัย。
destsz
n
อย่างไรก็ตาม strncpy_s
ถูกเพิ่มในมาตรฐาน C11 ดังนั้นจึงต้องระวังว่าในบางสภาพแวดล้อมอาจไม่สามารถใช้ได้
โครงสร้างพื้นฐานของ strchr
strchr
เมื่อใช้สามารถหาตำแหน่งของอักขระที่กำหนดและดึงสตริงจนถึงส่วนนั้น
ตัวอย่างการใช้งาน
char *strchr(const char *str, int c);
str
c
char
จุดสำคัญ
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strchr(str, ','); // Find the position of ','
if (pos != NULL) {
int length = pos - str; // Calculate the number of characters up to ','
char result[20];
strncpy(result, str, length);
result[length] = '\0'; // Add the null terminator
printf("Substring: %s\n", result); // Output "Hello"
}
return 0;
}
3.4 การค้นหาคำสำคัญและการตัดสตริงด้วย strstr
strchr
ที่พบครั้งแรกc
ของที่อยู่ที่คืนค่าpos - str
strncpy
โครงสร้างพื้นฐานของ strstr
strstr
เป็นประโยชน์ในการค้นหาสตริงย่อยและดึงสตริงต่อจากตำแหน่งนั้น
ตัวอย่างการใช้งาน
char *strstr(const char *haystack, const char *needle);
กองหญ้า
needle
จุดสำคัญ
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strstr(str, "World"); // Search for the position of "World"
if (pos != NULL) {
printf("Found substring: %s\n", pos);
} else {
printf("Substring not found.\n");
}
return 0;
}
3.5 สรุป
strstr
needle
NULL
needle
haystack
4. วิธีการตัดส่วนย่อยของสตริงใน C-gengo 【Jisaku kansū hen】
strncpy
เมื่อใช้ strncpy สามารถคัดลอกสตริงย่อยได้อย่างปลอดภัย แต่ต้องเพิ่มอักขระศูนย์ (null character) ด้วยตนเอง。strncpy_s
คือdestsz
สามารถกำหนดได้ ทำให้ความปลอดภัยเพิ่มขึ้น.strchr
ถ้าใช้ จะได้ส่วนของสตริงจนถึงตัวอักษรที่กำหนด。strstr
ถ้าใช้ strstr คุณจะสามารถรับตำแหน่งของคีย์เวิร์ดเฉพาะและตัดจากตำแหน่งนั้นออกได้。
การใช้ไลบรารีมาตรฐานทำให้การจัดการสตริงในภาษา C สามารถทำได้อย่างง่ายและปลอดภัย
4.1 ประโยชน์ของการสร้าง Jisaku kansū
หากใช้ Hyōjun raiburari จะสามารถตัดส่วนย่อยของสตริงพื้นฐานได้ แต่ในบางกรณีอาจต้องการวิธีที่ยืดหยุ่นมากกว่า วิธีที่ยืดหยุ่นมากกว่าที่ต้องการได้ ดังนั้นในส่วนนี้เราจะอธิบายเกี่ยวกับการตัดส่วนย่อยของสตริงโดยใช้ Jisaku kansū.
4.2 ฟังก์ชันการสกัดส่วนย่อยของสตริงพื้นฐาน
หากใช้ Hyōjun raiburari สามารถคัดลอกและค้นหาส่วนย่อยของสตริงได้ แต่มีปัญหาเช่นต่อไปนี้。
strncpy
เป็นอักขระศูนย์'\0'
ไม่เพิ่มโดยอัตโนมัติstrchr
และstrstr
สามารถค้นหาได้เฉพาะบางส่วนเท่านั้น- การจัดการสตริงที่ยืดหยุ่นมากขึ้นเป็นเรื่องยาก
ดังนั้น การสร้าง Jisaku kansū ที่สามารถปรับแต่งตามการใช้งานเฉพาะเป็นประโยชน์。
สเปคของฟังก์ชัน
ก่อนอื่น เราจะสร้างฟังก์ชันพื้นฐานที่ตัดสตริงจากตำแหน่งที่ระบุ。
โค้ดการทำงาน
- พารามิเตอร์
const char *source
int start
int length
char *dest
- เนื้อหาการประมวลผล
start
length
dest
'\0'
จุดสำคัญ
#include <stdio.h>
#include <string.h>
void substring(const char *source, int start, int length, char *dest) {
int i;
for (i = 0; i < length && source[start + i] != '\0'; i++) {
dest[i] = source[start + i];
}
dest[i] = '\0'; // Add null terminator
}
int main() {
char text[] = "Hello, World!";
char result[10];
substring(text, 7, 5, result); // Extract "World"
printf("Substring: %s\n", result);
return 0;
}
4.3 การรับส่วนย่อยของสตริงแบบไดนามิกโดยใช้ malloc
for
length
'\0'
dest[i] = '\0';
ให้แน่ใจว่าตัวอักษรศูนย์ถูกวางไว้ที่ท้ายสุด
สเปคของฟังก์ชัน
ในฟังก์ชันข้างต้น จำเป็นต้องจัดสรรขนาดของ dest
ล่วงหน้า อย่างไรก็ตาม หากสามารถจัดสรรขนาดที่ต้องการแบบไดนามิกได้ ฟังก์ชันจะเป็นแบบทั่วไปมากขึ้น。
โค้ดการทำงาน
- จัดสรรหน่วยความจำที่จำเป็นด้วย
เริ่มต้น
ความยาว
- ในที่เรียกใช้ จำเป็นต้องทำ
จุดสำคัญ
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *substring_dynamic(const char *source, int start, int length) {
char *dest = (char *)malloc(length + 1); // +1 for the null terminator
if (dest == NULL) {
return NULL; // Memory allocation failed
}
int i;
for (i = 0; i < length && source[start + i] != '\0'; i++) {
dest[i] = source[start + i];
}
dest[i] = '\0';
return dest;
}
int main() {
char text[] = "Hello, World!";
char *result = substring_dynamic(text, 7, 5);
if (result != NULL) {
printf("Substring: %s\n", result);
free(result); // Free allocated memory
} else {
printf("Memory allocation failed.\n");
}
return 0;
}
4.4 การรองรับอักขระหลายไบต์ (Nihongo)
malloc
ทำให้ไม่ต้องกังวลเรื่องขนาดของบัฟเฟอร์- หลังใช้งานแล้ว คุณต้องทำการปล่อยหน่วยความจำ。
การทำงานที่คำนึงถึงอักขระหลายไบต์
เมื่อทำงานกับ Nihongo (อักขระหลายไบต์เช่น UTF-8) ตัวอักษรหนึ่งอาจ ไม่จำเป็นต้องเป็น 1 ไบต์ ดังนั้นฟังก์ชัน substring
อย่างง่ายจะไม่ทำงานอย่างถูกต้อง。
โค้ดการทำงาน(รองรับ UTF-8)
mbstowcs
wchar_t
wcsncpy
wcstombs
จุดสำคัญ
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // Set the locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert UTF-8 string to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring in wide characters
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert back to multibyte string
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 string
char result[20];
substring_utf8(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
4.5 สรุป
setlocale(LC_ALL, "");
mbstowcs
wcsncpy
wcstombs
5. วิธีการตัดสตริงตามรหัสอักขระ
substring
ถ้าสร้างขึ้นเอง จะสามารถดึง substring ได้อย่างยืดหยุ่น。- การจัดสรรหน่วยความจำแบบไดนามิก (
malloc
) เมื่อใช้, สามารถดึง substring ที่มีขนาดเปลี่ยนแปลงได้。 - เมื่อจัดการกับตัวอักษรหลายไบต์ (ภาษาญี่ปุ่น) ให้ใช้
mbstowcs
/wcstombs
เพื่อใช้ประโยชน์。
หากการใช้ Hyōjun raiburari อย่าง strncpy
หรือ strchr
ยาก การสร้าง การประมวลผลสตริงใน C-gengo จะมีความแข็งแกร่งมากขึ้น。
5.1 กรณี ASCII(ตัวอักษร 1 ไบต์)
ในภาษา C หากไม่ระวังความแตกต่างของรหัสอักขระ การตัดสตริงอาจทำงานไม่ถูกต้องได้อาจเกิดขึ้น。โดยเฉพาะอย่างยิ่งเมื่อจัดการกับอักขระหลายไบต์เช่นภาษาญี่ปุ่นในกรณีเช่น (UTF-8, Shift_JIS, EUC-JP เป็นต้น) 1 ตัวอักษร = 1 ไบต์ไม่ได้ ดังนั้นฟังก์ชันแบบง่ายเช่น strncpy
หรือ substring
ในส่วนนี้ เราจะอธิบายอย่างละเอียดเกี่ยวกับวิธีการตัดสตริงตามรหัสอักขระ
การดึงส่วนย่อยของสตริงพื้นฐาน
ตัวอย่างการทำงาน
อักขระ ASCII มี 1 ตัวอักษร = 1 ไบต์ ดังนั้นสามารถใช้ strncpy
หรือ substring
ฟังก์ชันเพื่อประมวลผลได้อย่างง่ายดาย。
5.2 กรณี UTF-8(ตัวอักษรหลายไบต์)
#include <stdio.h>
#include <string.h>
void substring_ascii(const char *source, int start, int length, char *dest) {
strncpy(dest, source + start, length);
dest[length] = '\0'; // Add null terminator
}
int main() {
char text[] = "Hello, World!";
char result[6];
substring_ascii(text, 7, 5, result); // Extract "World"
printf("Substring: %s\n", result);
return 0;
}
จุดสำคัญ
- ASCII ตัวอักษร (เฉพาะตัวอักษรและตัวเลข) ในกรณี
strncpy
เพียงพอที่จะรองรับได้ '\0'
เพิ่ม (อักขระศูนย์) เสมอ
คุณลักษณะของ UTF-8
วิธีการประมวลผลที่ถูกต้อง
ใน UTF-8 จำนวนไบต์ต่อ 1 ตัวอักษรเปลี่ยนแปลงได้ระหว่าง 1-4 ไบต์ ดังนั้นการใช้ strncpy
อย่างง่ายอาจทำให้ตัดอักขระกลางค้างได้。
การดึงส่วนย่อยของสตริงที่รองรับ UTF-8
ในภาษา C เพื่อประมวลผล UTF-8 อย่างปลอดภัย แนะนำให้ใช้ mbstowcs
เพื่อแปลงเป็นสตริงกว้าง(wchar_t
)แล้วดึงส่วนย่อยของสตริงด้วยวิธีที่แนะนำ。
5.3 กรณี Shift_JIS(ตัวอักษรหลายไบต์)
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // Set the locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Get the substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 string
char result[20];
substring_utf8(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
จุดสำคัญ
setlocale(LC_ALL, "");
mbstowcs
wchar_t
wcsncpy
wcstombs
คุณลักษณะของ Shift_JIS
การดึงส่วนย่อยของสตริงที่รองรับ Shift_JIS
ใน Shift_JIS 1 ตัวอักษรอาจเป็น 1 ไบต์หรือ 2 ไบต์ ดังนั้นการใช้ strncpy
อย่างง่ายอาจทำให้เกิดอักขระเสีย。
การทำงานใน Shift_JIS
ในกรณี Shift_JIS ก็แนะนำให้แปลงเป็นสตริงกว้างแล้วประมวลผลด้วยวิธีที่แนะนำ。
5.4 กรณี EUC-JP(ตัวอักษรหลายไบต์)
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_sjis(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "Japanese"); // Set locale to handle Shift_JIS
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string (Shift_JIS) to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (Shift_JIS)
}
int main() {
char text[] = "こんにちは、世界!"; // Shift_JIS string (depending on environment)
char result[20];
substring_sjis(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
จุดสำคัญ
- Shift_JIS เพื่อประมวลผลอย่างถูกต้อง ตั้งค่า。
mbstowcs
wcstombs
คุณลักษณะของ EUC-JP
การดึงส่วนย่อยของสตริงที่รองรับ EUC-JP
EUC-JP เช่นเดียวกับ Shift_JIS มีจำนวนไบต์ต่อ 1 ตัวอักษรที่แตกต่างกัน จึงจำเป็นต้องใช้การแปลงเป็นสตริงกว้าง。
5.5 สรุป
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_eucjp(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "ja_JP.eucJP"); // Set locale to handle EUC-JP
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string (EUC-JP) to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (EUC-JP)
}
int main() {
char text[] = "こんにちは、世界!"; // EUC-JP string (depending on environment)
char result[20];
substring_eucjp(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
จุดสำคัญ
setlocale(LC_ALL, "ja_JP.eucJP");
mbstowcs
wcstombs
6. วิธีการแบ่งสตริงในภาษา C
รหัสอักขระ | จำนวนไบต์ | วิธีการประมวลผลที่แนะนำ |
---|---|---|
ASCII | 1 ไบต์ | strncpy |
UTF-8 | 1-4 ไบต์ | mbstowcs wcstombs |
Shift_JIS | 1 or 2ไบต์ | mbstowcs wcstombs |
EUC-JP | 1 or 2ไบต์ | mbstowcs wcstombs |
- ถ้าเป็นเพียงตัวอักษร ASCII
strncpy
โอเค - UTF-8, Shift_JIS, EUC-JP ในกรณีของ
mbstowcs
/wcstombs
ใช้ - ตามสภาพแวดล้อม
setlocale(LC_ALL, \"...\");
กำหนดค่าอย่างเหมาะสม
6.1 strtok
การแบ่งสตริง
การประมวลผลการแบ่งสตริง การวิเคราะห์ข้อมูล CSV, การประมวลผลอาร์กิวเมนต์บรรทัดคำสั่ง, การวิเคราะห์ข้อมูลบันทึก เป็นต้น จำเป็นในหลายสถานการณ์。在ภาษา C มีวิธีใช้ฟังก์ชันไลบรารีมาตรฐาน เช่น strtok
และ strtok_r
หรือสร้างฟังก์ชันเอง
ในส่วนนี้、วิธีการแบ่งสตริงด้วยอักขระตัวคั่นที่กำหนดจะอธิบายรายละเอียด
ไวยากรณ์พื้นฐาน
strtok
คือฟังก์ชันที่แบ่งสตริงตามอักขระตัวคั่น (delimiter) ที่กำหนด
ตัวอย่างการใช้:คอมม่า ,
เพื่อแบ่งสตริง
char *strtok(char *str, const char *delim);
str
delim
- ค่ากลับ
- ข้อควรระวัง
strtok
'\0'
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,orange,grape"; // String to be split
char *token = strtok(str, ","); // Get the first token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, ","); // Get the next token
}
return 0;
}
strtok
ข้อควรระวัง
token: apple
token: banana
token: orange
token: grape
6.2 strtok_r
การแบ่งสตริงแบบปลอดภัยต่อเธรด
- เปลี่ยนข้อความต้นฉบับ
strtok
ตัวอักษรตัวคั่นถูกแทนที่ด้วย'\0'
ทำให้ข้อความต้นฉบับสูญหาย
- ไม่ปลอดภัยต่อเธรด
strtok
จึง
ไวยากรณ์พื้นฐาน
strtok_r
คือเวอร์ชันปลอดภัยต่อเธรดของ strtok
โดยบันทึกสถานะลงใน saveptr
ทำให้สามารถใช้ได้อย่างปลอดภัยในสภาพแวดล้อมหลายเธรด
ตัวอย่างการใช้:ช่องว่าง เพื่อแบ่งสตริง
char *strtok_r(char *str, const char *delim, char **saveptr);
str
delim
saveptr
strtok_r
ข้อดี
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World from C"; // String to be split
char *token;
char *saveptr; // Pointer to store internal state
token = strtok_r(str, " ", &saveptr); // Get the first token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok_r(NULL, " ", &saveptr); // Get the next token
}
return 0;
}
6.3 การแบ่งสตริงด้วยฟังก์ชันที่สร้างเอง(วิธีที่ไม่ใช้ strtok
)
- ปลอดภัยต่อเธรด
- สามารถประมวลผลหลายสตริงพร้อมกันได้
สเปคของฟังก์ชันที่สร้างเอง
strtok
จะเปลี่ยนสตริงต้นฉบับ ดังนั้นจึงสามารถสร้างฟังก์ชันของตนเองที่แบ่งสตริงโดยไม่เปลี่ยนแปลงได้
โค้ดการทำงาน
- อินพุต
const char *source
const char delim
char tokens[][50]
- การประมวลผล
source
delim
tokens
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
void split_string(const char *source, char delim, char tokens[][50], int *count) {
int i = 0, j = 0, token_index = 0;
while (source[i] != '\0') {
if (source[i] == delim) {
tokens[token_index][j] = '\0';
token_index++;
j = 0;
} else {
tokens[token_index][j] = source[i];
j++;
}
i++;
}
tokens[token_index][j] = '\0';
*count = token_index + 1;
}
int main() {
char text[] = "dog,cat,bird,fish";
char tokens[10][50]; // Can store up to 10 words
int count;
split_string(text, ',', tokens, &count);
for (int i = 0; i < count; i++) {
printf("Token: %s\n", tokens[i]);
}
return 0;
}
จุดสำคัญ
Token: dog
Token: cat
Token: bird
Token: fish
6.4 การประยุกต์การแบ่งสตริง (การประมวลผลข้อมูล CSV)
ต้นฉบับ
tokens
ตัวอย่างการวิเคราะห์ข้อมูล CSV
สามารถวิเคราะห์ข้อมูล CSV(คั่นด้วยคอมม่า)ด้วย strtok
ได้
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
int main() {
char csv[] = "Alice,24,Female\nBob,30,Male\nCharlie,28,Male"; // CSV data
char *line = strtok(csv, "\n"); // Process line by line
while (line != NULL) {
char *name = strtok(line, ",");
char *age = strtok(NULL, ",");
char *gender = strtok(NULL, ",");
printf("Name: %s, Age: %s, Gender: %s\n", name, age, gender);
line = strtok(NULL, "\n");
}
return 0;
}
6.5 สรุป
Name: Alice, Age: 24, Gender: Female
Name: Bob, Age: 30, Gender: Male
Name: Charlie, Age: 28, Gender: Male
สรุป
วิธี | ข้อดี | ข้อเสีย |
---|---|---|
strtok | สามารถแยกได้ง่าย | เปลี่ยนข้อความต้นฉบับ |
strtok_r | ปลอดภัยต่อเธรด | การใช้งานมีความซับซ้อนเล็กน้อย |
ฟังก์ชันที่สร้างเอง | อย่าเปลี่ยนข้อความต้นฉบับ | โค้ดจะยาวขึ้น |
การวิเคราะห์ CSV | สะดวกสำหรับการประมวลผลข้อมูล | โปรดระวังข้อจำกัดของ strtok |
7. ตัวอย่างการประยุกต์: วิธีการดึงข้อความก่อนและหลังอักขระเฉพาะ
- ถ้าเป็นการแบ่งแบบง่าย
strtok
- ถ้าใช้หลายเธรด
strtok_r
- ถ้าคุณไม่ต้องการเปลี่ยนต้นฉบับ ใช้ฟังก์ชันที่สร้างเอง
- สามารถนำไปใช้กับการวิเคราะห์ข้อมูล CSV ได้ด้วย
ในส่วนต่อไป จะอธิบายอย่างละเอียดเกี่ยวกับ 「ตัวอย่างการประยุกต์: วิธีการสกัดข้อความก่อนและหลังอักขระที่กำหนด」
7.1 strchr
เพื่อดึงสตริงก่อนอักขระเฉพาะ
ในการประมวลผลสตริง,การดึงข้อความก่อนและหลังอักขระหรือคีย์เวิร์ดเฉพาะมักจำเป็นต้องทำการดำเนินการนี้ ตัวอย่างเช่น กรณีต่อไปนี้อาจเกิดขึ้น.
- ดึงเฉพาะส่วนโดเมนจาก URL
- ดึงชื่อไฟล์จากพาธไฟล์
- ดึงข้อความก่อนและหลังแท็กหรือสัญลักษณ์เฉพาะ
ในภาษา C,strchr
และ strstr
สามารถใช้เพื่อทำให้การประมวลผลเช่นนี้สำเร็จได้ นอกจากนี้ หากต้องการการประมวลผลที่ยืดหยุ่นมากขึ้น การสร้างฟังก์ชันของตนเองก็เป็นวิธีที่มีประสิทธิภาพ.
ไวยากรณ์พื้นฐาน
strchr
เมื่อใช้ สามารถระบุตำแหน่งของ อักขระ (ที่พบเป็นครั้งแรก) ได้.
ตัวอย่างการใช้: ดึงชื่อไฟล์จากเส้นทางไฟล์
char *strchr(const char *str, int c);
str
c
char
strchr
เมื่อ c
พบ จะคืนที่อยู่ของมัน.
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
void get_filename(const char *path, char *filename) {
char *pos = strrchr(path, '/'); // Search for the last '/'
if (pos != NULL) {
strcpy(filename, pos + 1); // Copy from the character after '/'
} else {
strcpy(filename, path); // If no '/', copy the whole path
}
}
int main() {
char path[] = "/home/user/documents/report.txt";
char filename[50];
get_filename(path, filename);
printf("Filename: %s\n", filename);
return 0;
}
จุดสำคัญ
Filename: report.txt
7.2 strstr
เพื่อดึงสตริงหลังคีย์เวิร์ดเฉพาะ
strrchr
สามารถรับตำแหน่งของตัวอักษรเฉพาะที่ปรากฏครั้งสุดท้าย (/
)pos + 1
เฉพาะชื่อไฟล์
ไวยากรณ์พื้นฐาน
strstr
เมื่อใช้ สามารถค้นหา สตริงเฉพาะ (คีย์เวิร์ด) และดึงสตริงต่อจากตำแหน่งนั้นได้.
ตัวอย่างการใช้: ดึงโดเมนจาก URL
char *strstr(const char *haystack, const char *needle);
กองหญ้า
needle
strstr
เมื่อ needle
พบ จะคืนที่อยู่ของตำแหน่งนั้น.
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
void get_domain(const char *url, char *domain) {
char *pos = strstr(url, "://"); // Search for the position of "://"
if (pos != NULL) {
strcpy(domain, pos + 3); // Copy from the character after "://"
} else {
strcpy(domain, url); // If "://" is not found, copy the entire string
}
}
int main() {
char url[] = "https://www.example.com/page.html";
char domain[50];
get_domain(url, domain);
printf("Domain part: %s\n", domain);
return 0;
}
จุดสำคัญ
Domain part: www.example.com/page.html
7.3 strchr
เพื่อแยกส่วนก่อนและหลังอักขระเฉพาะ
strstr
"https://"
"http://"
"//"
pos + 3
://
ตัวอย่างการใช้: แยกชื่อผู้ใช้และโดเมนจากอีเมล
strchr
หากใช้ สามารถแยกและดึงสตริง ก่อนและหลังอักขระ ได้.
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
void split_email(const char *email, char *username, char *domain) {
char *pos = strchr(email, '@'); // Search for the position of '@'
if (pos != NULL) {
strncpy(username, email, pos - email); // Copy the part before '@'
username[pos - email] = '\0'; // Add null terminator
strcpy(domain, pos + 1); // Copy the part after '@'
}
}
int main() {
char email[] = "user@example.com";
char username[50], domain[50];
split_email(email, username, domain);
printf("Username: %s\n", username);
printf("Domain: %s\n", domain);
return 0;
}
จุดสำคัญ
Username: user
Domain: example.com
7.4 การประยุกต์: ดึงแอตทริบิวต์เฉพาะในแท็ก HTML
strchr
'@'
strncpy
strcpy
ตัวอย่างการใช้: ดึง URL จาก <a href="URL">
แม้ต้องการดึงแอตทริบิวต์เฉพาะจากแท็ก HTML ก็สามารถใช้ strstr
ได้.
ผลลัพธ์การทำงาน
#include <stdio.h>
#include <string.h>
void get_href(const char *html, char *url) {
char *start = strstr(html, "href=\""); // Search for the position of href="
if (start != NULL) {
start += 6; // Move past href="
char *end = strchr(start, '"'); // Search for the next "
if (end != NULL) {
strncpy(url, start, end - start);
url[end - start] = '\0'; // Add null terminator
}
}
}
int main() {
char html[] = "<a href=\"https://example.com\">Click Here</a>";
char url[100];
get_href(html, url);
printf("Extracted URL: %s\n", url);
return 0;
}
จุดสำคัญ
Extracted URL: https://example.com
7.5 สรุป
strstr
"href=\""
strchr
"
สรุป
เนื้อหาการดำเนินการ | ใช้ฟังก์ชัน | ข้อดี |
---|---|---|
ดึงค่าก่อนตัวอักษรเฉพาะ | strchr / strrchr | เรียบง่ายและเร็ว |
ดึงค่าหลังจากอักขระเฉพาะ | strstr | ค้นหาด้วยคำสำคัญได้ |
แยกก่อนและหลังตัวอักษรเฉพาะ | strchr + strncpy | เหมาะสำหรับการแยกชื่อผู้ใช้และโดเมน ฯลฯ |
การดึงคุณสมบัติของแท็ก HTML | strstr + strchr | สามารถนำไปใช้กับเว็บสกรีปปิ้งได้ |
8. สรุป
strchr
และstrstr
เมื่อใช้、 สามารถดึงค่าก่อนและหลังตัวอักษรหรือคีย์เวิร์ดที่กำหนดได้อย่างง่ายดาย- การจัดการเส้นทางไฟล์、การวิเคราะห์ URL、การแยกอีเมล ฯลฯ、มีประโยชน์ในหลายสถานการณ์
- สามารถนำไปใช้กับกระบวนการขั้นสูงเช่นการสแกนเว็บได้ด้วย
8.1 การทบทวนบทความ
ในบทความนี้ เราได้อธิบายวิธีการตัดสตริงใน C gengo ตั้งแต่พื้นฐานจนถึงการประยุกต์อย่างละเอียด ที่นี่เราจะทบทวนจุดสำคัญของแต่ละส่วนและจัดระเบียบวิธีที่เหมาะสมตามการใช้งาน。
8.2 วิธีที่เหมาะสมตามการใช้งาน
ส่วน | เนื้อหา | จุดสำคัญ |
---|---|---|
พื้นฐานของสตริงในภาษา C | ในภาษา C, สตริงจะถูกจัดการเป็นอาร์เรย์ของ และตัวอักขระสิ้นสุด มีความสำคัญ | เมื่อจัดการกับสตริง อย่าลืม |
การตัดออกด้วยไลบรารีมาตรฐาน | strncpy strchr | strncpy ตัวสิ้นสุด NULL ด้วยตนเอง |
การแยกโดยฟังก์ชันที่สร้างเอง | สร้างฟังก์ชัน ที่ยืดหยุ่น | malloc สามารถดึงสตริงย่อยที่มีความยาวเปลี่ยนแปลงได้ |
การประมวลผลตามรหัสตัวอักษร | วิธีรองรับ UTF-8, Shift_JIS, EUC-JP | mbstowcs wcstombs ตัวอักษรกว้างแปลงเป็นเรื่องปลอดภัย |
วิธีการแยกสตริง | strtok strtok_r | strtok การเปลี่ยนแปลงสตริงต้นฉบับ |
ดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด | strchr strstr | การดึงชื่อไฟล์, การวิเคราะห์ URL, การวิเคราะห์ HTML |
1. การตัดสตริงย่อย
2. การแบ่งสตริง
สถานการณ์ใช้งาน | วิธีที่เหมาะสมที่สุด |
---|---|
ต้องการรับสตริงที่มีความยาวคงที่ | strncpy or substring() |
อยากทำการตัดอย่างปลอดภัย | strncpy_s |
จัดการกับตัวอักษรหลายบิต (UTF-8, Shift_JIS, EUC-JP) | mbstowcs / wcstombs |
3. การดึงตัวอักษรก่อนและหลังอักขระที่กำหนด
สถานการณ์การใช้งาน | วิธีที่เหมาะสมที่สุด |
---|---|
อยากแยกสตริงอย่างง่าย | strtok |
อยากทำการแบ่งแบบ thread-safe | strtok_r |
ต้องการแบ่งโดยไม่เปลี่ยนแปลงสตริงต้นฉบับ | ฟังก์ชันที่สร้างเอง(split_string() ) |
8.3 ข้อควรระวังในการจัดการสตริงของภาษา C
สถานการณ์การใช้งาน | วิธีที่เหมาะสมที่สุด |
---|---|
ดึงชื่อไฟล์จากพาธไฟล์ | strrchr(path, '/') |
ดึงส่วนโดเมนจาก URL | strstr(url, "://") |
แยกชื่อผู้ใช้และโดเมนจากที่อยู่อีเมล | strchr(email, '@') |
ดึงค่าคุณสมบัติจากแท็ก HTML | strstr(tag, "href=\"") + strchr(tag, '"') |
1. การจัดการการสิ้นสุดด้วย null 'ตัวอย่างการคัดลอกสตริงอย่างปลอดภัย
'
อย่างเคร่งครัด
ตัวอย่างการคัดลอกสตริงอย่างปลอดภัย
'2. ระวังการ overflow ของบัฟเฟอร์
ในการจัดการสตริงของภาษา C การจัดการอักขระสิ้นสุด ‘\0’ อย่างเหมาะสมเป็นสิ่งสำคัญที่สุด โดยเฉพาะเมื่อใช้ strncpy
หรือ strchr
ควรระวังการเพิ่มอักขระ null ด้วยตนเอง。
3. การจัดการอักขระหลายไบต์ใช้ mbstowcs
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, 5);
dest[5] = '\0'; // Add null terminator for safety
printf("Substring: %s\n", dest);
return 0;
}
4. การจัดการขนาดบัฟเฟอร์
ในการทำงานกับสตริงในภาษา C จำเป็นต้องเขียนโค้ดอย่างระมัดระวังเพื่อไม่ให้เข้าถึงนอกขอบเขตของอาเรย์ โดยเฉพาะเมื่อใช้ strncpy
ควรควบคุมจำนวนไบต์ที่คัดลอกเป็นสิ่งสำคัญ。
ตัวอย่างการคัดลอกสตริงอย่างปลอดภัย
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, sizeof(dest) - 1);
dest[5] = '\0'; // Explicitly add null terminator
printf("Substring: %s\n", dest);
return 0;
}
8.4 เพื่อการเรียนรู้ต่อไป
เมื่อทำงานกับอักขระหลายไบต์เช่น UTF-8 หรือ Shift_JIS การใช้ strncpy
หรือ strlen
อย่างง่ายอาจทำงานไม่ถูกต้อง。
ดังนั้นเมื่อจัดการอักขระหลายไบต์ ควรแปลงเป็นสตริงกว้างด้วย mbstowcs
ก่อนแล้วจึงประมวลผลอย่างเหมาะสม。
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, ""); // Set the locale
char text[] = "こんにちは、世界!"; // UTF-8
wchar_t wtext[256];
mbstowcs(wtext, text, 256); // Convert to wide-character string
printf("Converted wide-character string: %ls\n", wtext);
return 0;
}
หัวข้อเพื่อการเรียนรู้เชิงลึก
ในการจัดการสตริง จำเป็นต้องคำนวณ ขนาดหน่วยความจำที่ต้องการ ล่วงหน้าและป้องกัน การ overflow ของบัฟเฟอร์ โดยเฉพาะเมื่อใช้ malloc
เพื่อจัดสรรหน่วยความจำแบบไดนามิก ควรทำความเข้าใจขนาดอย่างแม่นยำ。
8.5 สรุป
การจัดการสตริงในภาษา C เป็น ทักษะสำคัญที่ช่วยเพิ่มความปลอดภัยและความอ่านง่ายของโปรแกรม ตามบทความนี้ หากเรียนรู้หัวข้อเพิ่มเติมต่อไปนี้ จะทำให้สามารถจัดการสตริงขั้นสูงได้。
หัวข้อเพื่อการเรียนรู้เชิงลึก
- นิพจน์ปกติ (regex)
- การจัดการไฟล์(fgets, fscanf การประมวลผลสตริงโดยใช้)
- การจัดการหน่วยความจำ(malloc, realloc โดยใช้ การจัดการสตริงแบบไดนาม)
- การวิเคราะห์ข้อมูล (วิธีการวิเคราะห์ JSON, XML)
8.5 สรุป
- สตริงในภาษา C ถูกจัดการด้วยอาร์เรย์ของ
char
ดังนั้นตัวอักขระจบ'\0'
มีความสำคัญในการจัดการ - การตัดส่วนสตริง
strncpy
,substring()
,malloc
ใช้ - การแยกสตริงด้วย
strtok
/strtok_r
/ ใช้ฟังก์ชันที่สร้างขึ้นเอง - เมื่อคุณต้องการดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด
strchr
,strstr
ใช้ - เมื่อจัดการกับตัวอักษรหลายบิต (ภาษาญี่ปุ่น) ให้ใช้
mbstowcs
- ให้ใส่ใจในการจัดการสตริงอย่างปลอดภัย และระวังการเกิด buffer overflow
หากใช้เนื้อหาในบทความนี้ คุณจะสามารถทำการจัดการสตริงที่ใช้งานได้จริงในภาษา C การจัดการสตริงที่ใช้งานได้จริง ได้แล้ว หลังจากเข้าใจฟังก์ชันพื้นฐานแล้ว ลองสร้างฟังก์ชันของคุณเองและประยุกต์ใช้งานเพื่อเขียนโค้ดที่มีประสิทธิภาพมากขึ้น!