คู่มือเต็มการตัดสตริงใน C | ฟังก์ชันมาตรฐาน, ฟังก์ชันผู้สร้าง, รองรับมัลติบายต์

目次

1. บทนำ

การจัดการสตริงในภาษา C เป็นหนึ่งในทักษะสำคัญสำหรับการเรียนรู้การเขียนโปรแกรม โดยเฉพาะ การตัดสตริง(การสกัดส่วนของสตริง)มักใช้บ่อยเมื่อทำการประมวลผลข้อมูลหรือแปลงรูปแบบ

ในบทความนี้ เราจะอธิบายอย่างละเอียดเกี่ยวกับ วิธีการตัดสตริงในภาษา C รวมถึง การใช้ฟังก์ชันไลบรารีมาตรฐาน, การสร้างฟังก์ชันของตนเอง, การรองรับอักขระหลายไบต์ (ภาษาญี่ปุ่น), วิธีการแบ่งสตริง เป็นต้น อีกทั้งยังแนะนำตัวอย่างการประยุกต์ใช้และการจัดการข้อผิดพลาด ดังนั้นกรุณาอ่านจนจบ

สิ่งที่คุณจะได้เรียนรู้ในบทความนี้

โดยการอ่านบทความนี้ คุณจะสามารถเรียนรู้ทักษะต่อไปนี้

  • แนวคิดพื้นฐานของสตริงในภาษา C และตัวอักขระจบ มีบทบาท
  • strncpystrchrฟังก์ชันไลบรารีมาตรฐานที่ใช้ในการตัดสตริงย่อย
  • ฟังก์ชันที่สร้างขึ้นเอง
  • พิจารณาอักขระหลายบิต (ภาษาญี่ปุ่น)
  • strtokวิธีการแบ่งสตริง
  • วิธีการดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด

เราจะอธิบายพร้อมตัวอย่างโค้ดเพื่อให้ผู้เริ่มต้นเข้าใจง่าย

ทำไมการตัดสตริงในภาษา C จึงสำคัญ?

ภาษา C จะจัดการสตริงเป็น อาเรย์ (อาเรย์ของชนิด char) ดังนั้นจึงไม่สามารถดึงส่วนของสตริงได้อย่างง่ายดายเหมือนภาษาระดับสูงอื่น ๆ (เช่น Python หรือ JavaScript) ดังนั้นการเลือกวิธีที่เหมาะสมในสถานการณ์ต่อไปนี้จึงสำคัญ

1. การประมวลผลข้อมูลเข้า

เช่น เมื่อวิเคราะห์ข้อมูลเช่นล็อกหรือไฟล์ CSV จำเป็นต้องสกัดข้อมูลเฉพาะบางส่วน

2. การค้นหาคำสำคัญเฉพาะ

การค้นหาคำสำคัญในสตริงและดึงข้อมูลก่อนและหลังเป็นสิ่งจำเป็นสำหรับฟังก์ชันการค้นหาและการสกัดข้อมูล

3. การเพิ่มความปลอดภัยของโปรแกรม

โดยการใช้ฟังก์ชันเช่น strncpy อย่างเหมาะสม สามารถป้องกัน การโอเวอร์ฟลว์ของบัฟเฟอร์ (การเขียนข้อมูลเกินขนาดบัฟเฟอร์) ได้ ซึ่งสำคัญเพื่อหลีกเลี่ยงความเสี่ยงด้านความปลอดภัย.

โครงสร้างของบทความนี้

ในบทความนี้ เราจะอธิบายตามลำดับต่อไปนี้

  1. C ภาษาโปรแกรม C คืออะไร? แนวคิดพื้นฐานและความสำคัญของอักขระจบสตริง
  2. วิธีตัดสตริงย่อยในภาษา C【ฉบับไลบรารีมาตรฐาน】
  3. วิธีตัดสตริงย่อยในภาษา C【ส่วนที่เขียนฟังก์ชันเอง】
  4. วิธีการตัดสตริงตามรหัสอักขระ
  5. วิธีการแบ่งสตริงด้วยภาษา C
  6. ตัวอย่างการใช้งาน: วิธีดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด
  7. สรุป
  8. 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" จะถูกจัดเก็บในหน่วยความจำดังต่อไปนี้

ดัชนี012345
ข้อความHello\0

ในภาษา C อักขระพิเศษที่บ่งบอกจุดสิ้นสุดของสตริง (null character '\0') จะถูกเพิ่มโดยอัตโนมัติที่ส่วนท้าย ดังนั้นความยาวของสตริงจะเป็น 「จำนวนอักขระจริง + 1」

2.2 ความสำคัญของอักขระสิ้นสุด(อักขระนัล '

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' นับจำนวนตัวอักษรจนถึงตัวอักษร null
  • sizeof(str)
年収訴求

3. วิธีการตัดสตริงย่อยในภาษา C 【ส่วนของไลบรารีมาตรฐาน】

  1. สตริงในภาษา C คือ char แสดงด้วยอาร์เรย์
  2. อักขระจบ (อักขระศูนย์ '\0') บ่งบอกจุดสิ้นสุดของสตริง ดังนั้นจึงต้องรวมไว้เสมอ
  3. เพื่อรับความยาวของสตริง strlen ใช้
  4. หากไม่ได้กำหนดสตริงด้วยวิธีที่เหมาะสม อาจเกิดข้อผิดพลาดที่ไม่คาดคิดได้

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

  1. อักขระศูนย์ '\0' ต้องเพิ่มด้วยตนเองstrncpyn'\0' ไม่เพิ่มอัตโนมัติ dest[n] = '\0';
  2. ระวังการล้นบัฟเฟอร์destn

โครงสร้างพื้นฐานของ strncpy_s

strncpy_s เป็นเวอร์ชันที่เสริมความปลอดภัยของ strncpy เพื่อป้องกันการโอเวอร์ฟลอว์ของบัฟเฟอร์

ตัวอย่างการใช้งาน

errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
  • dest
  • destszdest
  • 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

  • ขนาดบัฟเฟอร์ () เพื่อกำหนด ทำให้สามารถคัดลอกได้อย่างปลอดภัย。
  • destszn

อย่างไรก็ตาม strncpy_s ถูกเพิ่มในมาตรฐาน C11 ดังนั้นจึงต้องระวังว่าในบางสภาพแวดล้อมอาจไม่สามารถใช้ได้

โครงสร้างพื้นฐานของ strchr

strchr เมื่อใช้สามารถหาตำแหน่งของอักขระที่กำหนดและดึงสตริงจนถึงส่วนนั้น

ตัวอย่างการใช้งาน

char *strchr(const char *str, int c);
  • str
  • cchar

จุดสำคัญ

#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 - strstrncpy

โครงสร้างพื้นฐานของ 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 สรุป

  • strstrneedle
  • NULLneedlehaystack

4. วิธีการตัดส่วนย่อยของสตริงใน C-gengo 【Jisaku kansū hen】

  1. strncpy เมื่อใช้ strncpy สามารถคัดลอกสตริงย่อยได้อย่างปลอดภัย แต่ต้องเพิ่มอักขระศูนย์ (null character) ด้วยตนเอง。
  2. strncpy_s คือ destsz สามารถกำหนดได้ ทำให้ความปลอดภัยเพิ่มขึ้น.
  3. strchr ถ้าใช้ จะได้ส่วนของสตริงจนถึงตัวอักษรที่กำหนด。
  4. 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
  • เนื้อหาการประมวลผล
  • startlengthdest
  • '\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

  • forlength
  • '\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)

  • mbstowcswchar_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
  • wcsncpywcstombs

5. วิธีการตัดสตริงตามรหัสอักขระ

  1. substring ถ้าสร้างขึ้นเอง จะสามารถดึง substring ได้อย่างยืดหยุ่น。
  2. การจัดสรรหน่วยความจำแบบไดนามิก (malloc) เมื่อใช้, สามารถดึง substring ที่มีขนาดเปลี่ยนแปลงได้。
  3. เมื่อจัดการกับตัวอักษรหลายไบต์ (ภาษาญี่ปุ่น) ให้ใช้ 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, "");
  • mbstowcswchar_twcsncpy
  • 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 เพื่อประมวลผลอย่างถูกต้อง ตั้งค่า。
  • mbstowcswcstombs

คุณลักษณะของ 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");
  • mbstowcswcstombs

6. วิธีการแบ่งสตริงในภาษา C

รหัสอักขระจำนวนไบต์วิธีการประมวลผลที่แนะนำ
ASCII1 ไบต์strncpy
UTF-81-4 ไบต์mbstowcswcstombs
Shift_JIS1 or 2ไบต์mbstowcswcstombs
EUC-JP1 or 2ไบต์mbstowcswcstombs
  • ถ้าเป็นเพียงตัวอักษร 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 การแบ่งสตริงแบบปลอดภัยต่อเธรด

  1. เปลี่ยนข้อความต้นฉบับ
  • strtokตัวอักษรตัวคั่นถูกแทนที่ด้วย '\0' ทำให้ข้อความต้นฉบับสูญหาย
  1. ไม่ปลอดภัยต่อเธรด
  • 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
  • delimtokens

ผลลัพธ์การทำงาน

#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
  • cchar

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เหมาะสำหรับการแยกชื่อผู้ใช้และโดเมน ฯลฯ
การดึงคุณสมบัติของแท็ก HTMLstrstr + strchrสามารถนำไปใช้กับเว็บสกรีปปิ้งได้

8. สรุป

  • strchr และ strstr เมื่อใช้、 สามารถดึงค่าก่อนและหลังตัวอักษรหรือคีย์เวิร์ดที่กำหนดได้อย่างง่ายดาย
  • การจัดการเส้นทางไฟล์、การวิเคราะห์ URL、การแยกอีเมล ฯลฯ、มีประโยชน์ในหลายสถานการณ์
  • สามารถนำไปใช้กับกระบวนการขั้นสูงเช่นการสแกนเว็บได้ด้วย

8.1 การทบทวนบทความ

ในบทความนี้ เราได้อธิบายวิธีการตัดสตริงใน C gengo ตั้งแต่พื้นฐานจนถึงการประยุกต์อย่างละเอียด ที่นี่เราจะทบทวนจุดสำคัญของแต่ละส่วนและจัดระเบียบวิธีที่เหมาะสมตามการใช้งาน。

8.2 วิธีที่เหมาะสมตามการใช้งาน

ส่วนเนื้อหาจุดสำคัญ
พื้นฐานของสตริงในภาษา Cในภาษา C, สตริงจะถูกจัดการเป็นอาร์เรย์ของ และตัวอักขระสิ้นสุด มีความสำคัญเมื่อจัดการกับสตริง อย่าลืม
การตัดออกด้วยไลบรารีมาตรฐานstrncpystrchrstrncpyตัวสิ้นสุด NULL ด้วยตนเอง
การแยกโดยฟังก์ชันที่สร้างเองสร้างฟังก์ชัน ที่ยืดหยุ่นmallocสามารถดึงสตริงย่อยที่มีความยาวเปลี่ยนแปลงได้
การประมวลผลตามรหัสตัวอักษรวิธีรองรับ UTF-8, Shift_JIS, EUC-JPmbstowcswcstombsตัวอักษรกว้างแปลงเป็นเรื่องปลอดภัย
วิธีการแยกสตริงstrtokstrtok_rstrtokการเปลี่ยนแปลงสตริงต้นฉบับ
ดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนดstrchrstrstrการดึงชื่อไฟล์, การวิเคราะห์ URL, การวิเคราะห์ HTML

1. การตัดสตริงย่อย

2. การแบ่งสตริง

สถานการณ์ใช้งานวิธีที่เหมาะสมที่สุด
ต้องการรับสตริงที่มีความยาวคงที่strncpy or substring()
อยากทำการตัดอย่างปลอดภัยstrncpy_s
จัดการกับตัวอักษรหลายบิต (UTF-8, Shift_JIS, EUC-JP)mbstowcs / wcstombs

3. การดึงตัวอักษรก่อนและหลังอักขระที่กำหนด

สถานการณ์การใช้งานวิธีที่เหมาะสมที่สุด
อยากแยกสตริงอย่างง่ายstrtok
อยากทำการแบ่งแบบ thread-safestrtok_r
ต้องการแบ่งโดยไม่เปลี่ยนแปลงสตริงต้นฉบับฟังก์ชันที่สร้างเอง(split_string()

8.3 ข้อควรระวังในการจัดการสตริงของภาษา C

สถานการณ์การใช้งานวิธีที่เหมาะสมที่สุด
ดึงชื่อไฟล์จากพาธไฟล์strrchr(path, '/')
ดึงส่วนโดเมนจาก URLstrstr(url, "://")
แยกชื่อผู้ใช้และโดเมนจากที่อยู่อีเมลstrchr(email, '@')
ดึงค่าคุณสมบัติจากแท็ก HTMLstrstr(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 เป็น ทักษะสำคัญที่ช่วยเพิ่มความปลอดภัยและความอ่านง่ายของโปรแกรม ตามบทความนี้ หากเรียนรู้หัวข้อเพิ่มเติมต่อไปนี้ จะทำให้สามารถจัดการสตริงขั้นสูงได้。

หัวข้อเพื่อการเรียนรู้เชิงลึก

  1. นิพจน์ปกติ (regex)
  2. การจัดการไฟล์(fgets, fscanf การประมวลผลสตริงโดยใช้)
  3. การจัดการหน่วยความจำ(malloc, realloc โดยใช้ การจัดการสตริงแบบไดนาม)
  4. การวิเคราะห์ข้อมูล (วิธีการวิเคราะห์ JSON, XML)

8.5 สรุป

  1. สตริงในภาษา C ถูกจัดการด้วยอาร์เรย์ของ char ดังนั้นตัวอักขระจบ '\0' มีความสำคัญในการจัดการ
  2. การตัดส่วนสตริง strncpy, substring(), malloc ใช้
  3. การแยกสตริงด้วย strtok / strtok_r / ใช้ฟังก์ชันที่สร้างขึ้นเอง
  4. เมื่อคุณต้องการดึงตัวอักษรก่อนและหลังตัวอักษรที่กำหนด strchr, strstr ใช้
  5. เมื่อจัดการกับตัวอักษรหลายบิต (ภาษาญี่ปุ่น) ให้ใช้ mbstowcs
  6. ให้ใส่ใจในการจัดการสตริงอย่างปลอดภัย และระวังการเกิด buffer overflow

หากใช้เนื้อหาในบทความนี้ คุณจะสามารถทำการจัดการสตริงที่ใช้งานได้จริงในภาษา C การจัดการสตริงที่ใช้งานได้จริง ได้แล้ว หลังจากเข้าใจฟังก์ชันพื้นฐานแล้ว ลองสร้างฟังก์ชันของคุณเองและประยุกต์ใช้งานเพื่อเขียนโค้ดที่มีประสิทธิภาพมากขึ้น!