ชนิดเวกเตอร์ที่นำกลับมาใช้ได้
ห่อขนาดและความจุ
ชนิดเวกเตอร์ที่นำกลับมาใช้ได้ เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
จากโค้ดที่กระจัดกระจายสู่ชนิดข้อมูล
การส่งพอยน์เตอร์ จำนวนสมาชิก และความจุไปมาด้วยตัวแปรสามตัวแยกกันมีโอกาสเกิดข้อผิดพลาดได้ง่าย
ลองรวมสิ่งเหล่านี้ไว้ใน struct เดียว ซึ่งเป็นอาร์เรย์แบบไดนามิกที่นำกลับมาใช้ซ้ำได้ และมักเรียกว่าเวกเตอร์ โดยจะรวมข้อมูลกับข้อมูลกำกับการจัดการไว้ด้วยกัน
โครงสร้างเวกเตอร์
เวกเตอร์ต้องมีฟิลด์สามรายการ ได้แก่ พอยน์เตอร์ไปยังข้อมูล จำนวนสมาชิกที่ใช้งานอยู่ (len) และจำนวนสมาชิกที่รองรับได้ก่อนปรับขนาด (cap)
typedef struct {
int *data;
size_t len;
size_t cap;
} Vec;การเริ่มต้นเวกเตอร์
เวกเตอร์ว่างมีพอยน์เตอร์ข้อมูลเป็น NULL และมีความยาวกับความจุเป็นศูนย์ ฟังก์ชันเริ่มต้นขนาดเล็กช่วยให้เจตนาของโค้ดชัดเจน
void vec_init(Vec *v) {
v->data = NULL;
v->len = 0;
v->cap = 0;
}การดำเนินการเพิ่มสมาชิก
vec_push เพิ่มสมาชิกหนึ่งรายการต่อท้าย หากเวกเตอร์เต็ม จะเพิ่มความจุเป็นสองเท่าก่อน
ฟังก์ชันนี้คืนค่า 0 เมื่อสำเร็จ และคืนค่า -1 หากการจัดสรรหน่วยความจำล้มเหลว เพื่อให้ผู้เรียกจัดการต่อได้
int vec_push(Vec *v, int value) {
if (v->len == v->cap) {
size_t nc = v->cap ? v->cap * 2 : 4;
int *tmp = realloc(v->data, nc * sizeof(*v->data));
if (!tmp) return -1;
v->data = tmp;
v->cap = nc;
}
v->data[v->len++] = value;
return 0;
}การอ่านสมาชิกกลับมา
เนื่องจาก len ใช้ติดตามจำนวนสมาชิกที่ใช้งานอยู่ คุณจึงวนซ้ำตั้งแต่ 0 ถึง len - 1 ได้ ความจุอาจมากกว่านี้ แต่ช่องเหล่านั้นยังไม่ถือเป็นส่วนหนึ่งของข้อมูล
for (size_t i = 0; i < v->len; i++)
printf("%d\n", v->data[i]);การคืนหน่วยความจำของเวกเตอร์
เวกเตอร์เป็นเจ้าของบัฟเฟอร์บนฮีพ จึงต้องมีฟังก์ชันล้างข้อมูลที่สอดคล้องกัน หลังคืนหน่วยความจำแล้ว ให้รีเซ็ตฟิลด์ต่าง ๆ เพื่อไม่ให้ใช้โครงสร้างผิดวิธี
void vec_free(Vec *v) {
free(v->data);
v->data = NULL;
v->len = v->cap = 0;
}นำทุกอย่างมาประกอบกัน
โปรแกรมฉบับเต็มนี้สร้างเวกเตอร์ เพิ่มค่าห้าค่า แสดงค่าเหล่านั้น แล้วคืนหน่วยความจำอย่างเรียบร้อย
#include <stdio.h>
#include <stdlib.h>
typedef struct { int *data; size_t len, cap; } Vec;
int vec_push(Vec *v, int value) {
if (v->len == v->cap) {
size_t nc = v->cap ? v->cap * 2 : 4;
int *tmp = realloc(v->data, nc * sizeof(*v->data));
if (!tmp) return -1;
v->data = tmp; v->cap = nc;
}
v->data[v->len++] = value;
return 0;
}
int main(void) {
Vec v = {0};
for (int i = 0; i < 5; i++) vec_push(&v, i * 10);
for (size_t i = 0; i < v.len; i++) printf("%d\n", v.data[i]);
free(v.data);
return 0;
}การกำหนดค่าเป็นศูนย์ด้วย {0}
การเขียน Vec v = {0}; จะกำหนดค่าศูนย์ให้ทุกฟิลด์ รวมถึงกำหนดพอยน์เตอร์ข้อมูลเป็น NULL
นี่เป็นทางลัดที่สะดวก ทำให้เวกเตอร์พร้อมใช้กับ vec_push โดยไม่ต้องเรียกฟังก์ชันเริ่มต้นอย่างชัดเจน
Vec v = {0}; /* data=NULL, len=0, cap=0 */
vec_push(&v, 42);ฟังก์ชันช่วย get ที่ปลอดภัย
การใช้ดัชนีเลย len เป็นข้อผิดพลาด ฟังก์ชันเข้าถึงขนาดเล็กสามารถตรวจขอบเขตและแจ้งข้อผิดพลาดได้ โดยแลกกับความเร็วเล็กน้อยเพื่อความปลอดภัย
int vec_get(const Vec *v, size_t i, int *out) {
if (i >= v->len) return -1; /* out of range */
*out = v->data[i];
return 0;
}เหตุผลที่ต้องแยกติดตาม len และ cap
cap คือปริมาณหน่วยความจำที่จัดสรรไว้ ส่วน len คือปริมาณที่ใช้งานจริง
การมีความจุสำรองทำให้การเพิ่มสมาชิกส่วนใหญ่ไม่ต้องเรียก realloc การแยกสองค่านี้คือสิ่งที่ทำให้เวกเตอร์ทั้งรวดเร็วและยืดหยุ่น
ทำให้ชนิดข้อมูลใช้ได้ทั่วไป
เวกเตอร์นี้เก็บข้อมูลชนิด int หากต้องการเก็บชนิดอื่น คุณสามารถเปลี่ยนชนิดของสมาชิก หรือเก็บ void * พร้อมขนาดสมาชิกได้
รูปแบบการทำงาน ได้แก่ การเริ่มต้น การเพิ่มสมาชิก และการคืนหน่วยความจำ ยังคงเหมือนเดิมไม่ว่าคุณจะเก็บข้อมูลชนิดใด
typedef struct {
double *data;
size_t len, cap;
} DVec; /* same shape, different element type */ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับชนิดเวกเตอร์ของคุณ
ทบทวน
เวกเตอร์รวมพอยน์เตอร์ข้อมูล len และ cap ไว้ใน struct เดียว
vec_push จะเพิ่มความจุเป็นสองเท่าเมื่อเต็ม ส่วน vec_free จะคืนบัฟเฟอร์และรีเซ็ตฟิลด์ และ {0} ใช้เริ่มต้นค่าอย่างเรียบร้อย รูปแบบที่นำกลับมาใช้ซ้ำได้นี้ดีกว่าการจัดการตัวแปรที่กระจัดกระจาย บทถัดไปคือการคืนหน่วยความจำอย่างถูกต้องและหลีกเลี่ยงการรั่วไหล
เรียนรู้ C ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 39
- บทเรียน
- 144
คำถามที่พบบ่อย
บทเรียน “ชนิดเวกเตอร์ที่นำกลับมาใช้ได้” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ชนิดเวกเตอร์ที่นำกลับมาใช้ได้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ชนิดเวกเตอร์ที่นำกลับมาใช้ได้”
ห่อขนาดและความจุ คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “ชนิดเวกเตอร์ที่นำกลับมาใช้ได้” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- จัดสรรอาร์เรย์
- ขยายด้วย realloc
- ชนิดเวกเตอร์ที่นำกลับมาใช้ได้
- คืนหน่วยความจำและหลีกเลี่ยงการรั่วไหล