ไวยากรณ์:
char* strcpy (char*ปลายทาง_ที่ตั้ง, const char*source_string);ทำความเข้าใจกับ strcpy():
จุดประสงค์เดียวของฟังก์ชัน strcpy() คือการคัดลอกสตริงจากต้นทางไปยังปลายทาง ตอนนี้ ให้เราดูไวยากรณ์ด้านบนของฟังก์ชัน strcpy() ฟังก์ชัน strcpy() สามารถรับพารามิเตอร์ได้สองค่า -
- ถ่าน * ปลายทาง
- อักขระ const * source
ซอร์สเป็นค่าคงที่ที่นี่เพื่อให้แน่ใจว่าฟังก์ชัน strcpy() ไม่สามารถเปลี่ยนสตริงต้นทางได้ ฟังก์ชัน strcpy() คัดลอกอักขระทั้งหมด (รวมถึงอักขระ NULL ที่ส่วนท้ายของสตริง) จากสตริงต้นทางไปยังปลายทาง เมื่อการคัดลอกเสร็จสมบูรณ์จากต้นทางไปยังปลายทาง ฟังก์ชัน strcpy() จะส่งคืนที่อยู่ของปลายทางกลับไปยังฟังก์ชันผู้เรียก
จุดสำคัญที่ควรสังเกตที่นี่คือ ฟังก์ชัน strcpy() ไม่ได้ต่อท้ายสตริงต้นทางกับสตริงปลายทาง มันค่อนข้างจะแทนที่เนื้อหาของปลายทางด้วยเนื้อหาของสตริงต้นทาง
นอกจากนี้ ฟังก์ชัน strcpy() จะไม่ทำการตรวจสอบใดๆ เพื่อให้แน่ใจว่าขนาดของปลายทางนั้นมากกว่าสตริงต้นทาง มันเป็นความรับผิดชอบของโปรแกรมเมอร์โดยสมบูรณ์
ตัวอย่าง:
ตอนนี้ เราจะเห็นหลายตัวอย่างเพื่อทำความเข้าใจฟังก์ชัน strcpy():
- strcpy() – การทำงานปกติ (example1.c)
- strcpy() – กรณีที่-1 (example2.c)
- strcpy() – กรณีที่ 2 (example3.c)
- strcpy() – กรณีที่-3 (example4.c)
- strcpy() – เวอร์ชันที่กำหนดโดยผู้ใช้ (example5.c)
- strcpy() - เวอร์ชันที่กำหนดโดยผู้ใช้ Optimized (example6.c)
strcpy() – การทำงานปกติ (example1.c):
โปรแกรมตัวอย่างนี้แสดงวิธีการดำเนินการคัดลอกสตริงปกติโดยใช้ฟังก์ชัน strcpy() ในภาษาการเขียนโปรแกรม C โปรดทราบว่าความยาวของสตริงปลายทางคือ 30 (อักขระปลายทาง_str[30]; ) ซึ่งมากกว่าความยาวของสตริงต้นทาง (ความยาว 18 รวมอักขระ NULL) เพื่อให้ปลายทางสามารถรองรับอักขระทั้งหมดจาก สตริงต้นทาง
#รวม
#รวม
intหลัก()
{
charsource_str[] = 'www.linuxhint.com';
charปลายทาง_str[30];
printf ('ก่อนที่จะเรียกใช้ฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
strcpy (ปลายทาง_str,source_str);
printf ('หลังจากรันฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
กลับ 0;
}
strcpy() – กรณีที่-1 (example2.c):
จุดประสงค์ของโปรแกรมตัวอย่างนี้คือเพื่ออธิบายให้ชัดเจนว่าเกิดอะไรขึ้นเมื่อความยาวของสตริงปลายทางน้อยกว่าความยาวของสตริงต้นทาง ในกรณีดังกล่าว ตำแหน่งปลายทางจะมีช่องว่าง/ไบต์ไม่เพียงพอเพื่อรองรับอักขระทั้งหมด (รวมถึงอักขระ NULL) จากสตริงต้นทาง สองสิ่งที่คุณควรจำไว้เสมอ:
- ฟังก์ชัน strcpy() จะไม่ตรวจสอบว่าปลายทางมีพื้นที่เพียงพอหรือไม่
- นี่อาจเป็นอันตรายในซอฟต์แวร์ฝังตัวเนื่องจาก strcpy() จะแทนที่พื้นที่หน่วยความจำที่อยู่นอกขอบเขตของปลายทาง
มาดูตัวอย่างโปรแกรมกัน เราได้ประกาศ source_str และเริ่มต้นเป็น www.linuxhint.com ซึ่งจะใช้หน่วยความจำ 18 ไบต์ในการจัดเก็บ รวมถึงอักขระ Null ที่ส่วนท้ายของสตริง จากนั้น เราได้ประกาศอาร์เรย์อักขระอื่น เช่น destination_str ที่มีขนาดเพียง 5 ดังนั้น destination_str ไม่สามารถเก็บสตริงต้นทางที่มีขนาดรวม 18 ไบต์ได้
แต่ถึงกระนั้น เรากำลังเรียกใช้ฟังก์ชัน strcpy() เพื่อคัดลอกสตริงต้นทางไปยังสตริงปลายทาง จากผลลัพธ์ด้านล่าง เราจะเห็นว่า strcpy() ไม่บ่นเลย ในกรณีนี้ ฟังก์ชัน strcpy() จะเริ่มคัดลอกอักขระจากสตริงต้นทาง (จนกว่าจะพบอักขระ NULL ในสตริงต้นทาง) ไปยังที่อยู่ปลายทาง (แม้ว่าขอบเขตปลายทางจะเกิน) นั่นหมายความว่าฟังก์ชัน strcpy() ไม่ได้ทำการตรวจสอบขอบเขตสำหรับอาร์เรย์ปลายทาง ในที่สุด ฟังก์ชัน strcpy() จะเขียนทับที่อยู่หน่วยความจำที่ไม่ได้จัดสรรให้กับอาร์เรย์ปลายทาง นี่คือเหตุผลที่ฟังก์ชัน strcpy() จะลงเอยด้วยการเขียนทับตำแหน่งหน่วยความจำที่อาจจัดสรรให้กับตัวแปรอื่น
ในตัวอย่างนี้ เราจะเห็นได้จากผลลัพธ์ด้านล่าง ว่าฟังก์ชัน strcpy() จะเขียนทับสตริงต้นทางเอง โปรแกรมเมอร์ควรระมัดระวังกับพฤติกรรมดังกล่าวเสมอ
#รวม#รวม
intหลัก()
{
charsource_str[] = 'www.linuxhint.com';
charปลายทาง_str[5];
printf ('ก่อนที่จะเรียกใช้ฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
strcpy (ปลายทาง_str,source_str);
printf ('หลังจากรันฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
//printf('ที่อยู่แหล่งที่มา = %u (0x%x) ', &source_str[0], &source_str[0]);
//printf('ที่อยู่ปลายทาง = %u (0x%x) ', &destination_str[0], &destination_str[0]);
กลับ 0;
}
strcpy() – กรณีที่ 2 (example3.c):
โปรแกรมนี้แสดงสถานการณ์เมื่อขนาดสตริงปลายทางมากกว่าขนาดสตริงต้นทางและสตริงปลายทางถูกเตรียมใช้งานด้วยค่าบางอย่างแล้ว ในตัวอย่างนี้ เราได้เริ่มต้น:
- source_str ถึง www.linuxhint.com [ขนาด = 17+1 = 18]
- ปลายทาง_str ถึง I_AM_A_DESTINATION_STRING [ขนาด = 25+1 = 26]
ฟังก์ชัน strcpy() จะคัดลอกอักขระทั้งหมด 17 ตัวและอักขระ NULL จากสตริงต้นทางไปยังสตริงปลายทาง แต่จะไม่แทนที่/เปลี่ยนไบต์ที่เหลือ (ไบต์ 19 เป็น 26 หนึ่งไบต์ตาม) ในอาร์เรย์ปลายทาง เราใช้ for loop เพื่อวนซ้ำบนอาร์เรย์ปลายทางและพิมพ์อาร์เรย์ทั้งหมดเพื่อพิสูจน์ว่าไบต์-19 ถึง 26 ไม่เปลี่ยนแปลงในอาร์เรย์ปลายทาง นั่นคือเหตุผลที่เราเห็นผลลัพธ์สุดท้ายเป็น:
#รวม#รวม
/* โปรแกรมนี้แสดงสถานการณ์เมื่อ:
ขนาดสตริงปลายทาง > ขนาดสตริงต้นทาง
และเรารันฟังก์ชัน strcpy() เพื่อคัดลอก
สตริงต้นทางไปยังปลายทาง
หมายเหตุ: ขนาดสตริงปลายทางควรเสมอ
มากกว่าหรือเท่ากับสตริงต้นทาง
* /
intหลัก()
{
charsource_str[] = 'www.linuxhint.com';
charปลายทาง_str[26] = 'I_AM_A_DESTINATION_STRING';
printf ('ก่อนที่จะเรียกใช้ฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
strcpy (ปลายทาง_str,source_str);
printf ('หลังจากรันฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
/* พิมพ์สตริงปลายทางโดยใช้ for loop*/
printf ('พิมพ์อักขระสตริงปลายทางโดย char :NSNS');
printf ('NSสตริงปลายทาง = ');
สำหรับ(intผม=0;ผม<25;ผม++)
{
printf ('% ค',ปลายทาง_str[ผม]);
}
printf ('NSNS');
กลับ 0;
}
strcpy() – กรณีที่-3 (example4.c):
เราได้พิจารณาโปรแกรมนี้เป็นตัวอย่างเพื่อแสดงให้เห็นว่าเราไม่ควรเรียก strcpy() ด้วยสตริงตามตัวอักษรเป็นปลายทาง ซึ่งจะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนดไว้ และในที่สุด โปรแกรมก็จะหยุดทำงาน
#รวม#รวม
intหลัก()
{
charsource_str[] = 'www.linuxhint.com';
printf ('ก่อนที่จะเรียกใช้ฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
/* ห้ามเรียก strcpy() โดยใช้สตริงตามตัวอักษรเป็นปลายทาง
โปรแกรมจะพัง
* /
strcpy ('destination_str',source_str);
printf ('หลังจากรันฟังก์ชัน strcpy() :NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
กลับ 0;
}
strcpy() – เวอร์ชันที่กำหนดโดยผู้ใช้ (example5.c):
ในโปรแกรมตัวอย่างนี้ เราได้แสดงวิธีเขียนฟังก์ชัน strcpy() เวอร์ชันที่ผู้ใช้กำหนด
#รวมchar *strcpy_user_defined(char *ปลายทาง, const char *src);
/* ฟังก์ชัน strcpy() เวอร์ชันที่ผู้ใช้กำหนด */
char *strcpy_user_defined(char *ปลายทาง, const char *src)
{
char *dest_backup=ปลายทาง;
ในขณะที่(*src! = ' 0') /* วนซ้ำจนกว่าจะพบ ' '*/
{
*ปลายทาง= *src; /* คัดลอกถ่านต้นทางไปยังปลายทาง */
src++; /* เพิ่มตัวชี้แหล่งที่มา */
ปลายทาง++; /* เพิ่มตัวชี้ปลายทาง */
}
*ปลายทาง= ' 0'; /* ใส่ ' ' ที่ปลายทางอย่างชัดเจน*/
กลับdest_backup;
}
intหลัก()
{
charsource_str[] = 'www.linuxhint.com';
charปลายทาง_str[30];
printf ('ก่อนที่จะเรียกใช้ฟังก์ชันคัดลอกสตริงที่ผู้ใช้กำหนด:NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
/* เรียกฟังก์ชันคัดลอกสตริงที่ผู้ใช้กำหนด */
strcpy_user_defined(ปลายทาง_str,source_str);
printf ('หลังจากรันฟังก์ชันคัดลอกสตริงที่ผู้ใช้กำหนด:NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
กลับ 0;
}
strcpy() - เวอร์ชันที่กำหนดโดยผู้ใช้ Optimized (example6.c):
ในโปรแกรมตัวอย่างนี้ เราจะเพิ่มประสิทธิภาพเวอร์ชันที่ผู้ใช้กำหนดของ strcpy()
#รวมchar *strcpy_user_defined(char *ปลายทาง, const char *src);
/* ฟังก์ชัน strcpy() ที่ผู้ใช้กำหนดเวอร์ชันที่ปรับให้เหมาะสม */
char *strcpy_user_defined(char *ปลายทาง, const char *src)
{
char *dest_backup=ปลายทาง;
ในขณะที่(*ปลายทาง++ = *src++)
;
กลับdest_backup;
}
intหลัก()
{
charsource_str[] = 'www.linuxhint.com';
charปลายทาง_str[30];
printf ('ก่อนที่จะเรียกใช้ฟังก์ชันคัดลอกสตริงที่ผู้ใช้กำหนด:NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
/* เรียกฟังก์ชันคัดลอกสตริงที่ผู้ใช้กำหนด */
strcpy_user_defined(ปลายทาง_str,source_str);
printf ('หลังจากรันฟังก์ชันคัดลอกสตริงที่ผู้ใช้กำหนด:NSNS');
printf ('NSสตริงต้นทาง = %sNS',source_str);
printf ('NSสตริงปลายทาง = %sNSNS',ปลายทาง_str);
กลับ 0;
}
บทสรุป :
ฟังก์ชัน strcpy() เป็นฟังก์ชันไลบรารีที่ได้รับความนิยมและมีประโยชน์มากในการคัดลอกสตริงในภาษาการเขียนโปรแกรม C ส่วนใหญ่จะใช้เพื่อคัดลอกสตริงจากตำแหน่งหนึ่งไปยังอีกตำแหน่งหนึ่ง อย่างไรก็ตาม เราต้องการย้ำข้อเท็จจริงที่ว่าฟังก์ชัน strcpy() ไม่ได้ทำการตรวจสอบขอบเขตสำหรับอาร์เรย์ปลายทาง ซึ่งอาจนำไปสู่ข้อบกพร่องของซอฟต์แวร์ที่ร้ายแรงหากละเลย เป็นความรับผิดชอบของโปรแกรมเมอร์เสมอที่จะต้องตรวจสอบให้แน่ใจว่าอาร์เรย์ปลายทางมีพื้นที่เพียงพอสำหรับเก็บอักขระทั้งหมดจากสตริงต้นทางรวมถึงอักขระ NULL