คู่มือฉบับย่อ C ++
C ++ เป็นภาษาการเขียนโปรแกรมรูปแบบอิสระที่พิมพ์แบบสแตติกคอมไพล์ใช้งานทั่วไปพิจารณาตัวพิมพ์เล็กและใหญ่ซึ่งสนับสนุนการเขียนโปรแกรมเชิงขั้นตอนเชิงวัตถุและแบบทั่วไป
C ++ ถือได้ว่าเป็นไฟล์ middle-level ภาษาเนื่องจากประกอบด้วยคุณลักษณะภาษาระดับสูงและระดับต่ำ
C ++ ได้รับการพัฒนาโดย Bjarne Stroustrup เริ่มต้นในปี 1979 ที่ Bell Labs ใน Murray Hill รัฐนิวเจอร์ซีย์เพื่อเพิ่มประสิทธิภาพให้กับภาษา C และเดิมชื่อ C กับ Classes แต่ต่อมาได้เปลี่ยนชื่อเป็น C ++ ในปี 1983
C ++ เป็นส่วนเหนือของ C และโปรแกรม C ทางกฎหมายใด ๆ ก็เป็นโปรแกรม C ++ ที่ถูกกฎหมาย
Note - ภาษาโปรแกรมกล่าวกันว่าใช้การพิมพ์แบบคงที่เมื่อทำการตรวจสอบประเภทในระหว่างเวลาคอมไพล์เมื่อเทียบกับรันไทม์
การเขียนโปรแกรมเชิงวัตถุ
C ++ รองรับการเขียนโปรแกรมเชิงวัตถุอย่างสมบูรณ์รวมถึงเสาหลักทั้งสี่ของการพัฒนาเชิงวัตถุ -
- Encapsulation
- การซ่อนข้อมูล
- Inheritance
- Polymorphism
ไลบรารีมาตรฐาน
C ++ มาตรฐานประกอบด้วยสามส่วนที่สำคัญ -
ภาษาหลักที่ให้ส่วนประกอบทั้งหมดรวมถึงตัวแปรประเภทข้อมูลและตัวอักษร ฯลฯ
ไลบรารีมาตรฐาน C ++ มีชุดฟังก์ชันมากมายที่จัดการไฟล์สตริงและอื่น ๆ
Standard Template Library (STL) ให้ชุดวิธีการที่หลากหลายในการจัดการโครงสร้างข้อมูล ฯลฯ
มาตรฐาน ANSI
มาตรฐาน ANSI เป็นความพยายามที่จะตรวจสอบให้แน่ใจว่า C ++ สามารถพกพาได้ โค้ดที่คุณเขียนสำหรับคอมไพเลอร์ของ Microsoft จะคอมไพล์โดยไม่มีข้อผิดพลาดโดยใช้คอมไพเลอร์บน Mac, UNIX, Windows box หรือ Alpha
มาตรฐาน ANSI มีความเสถียรมาระยะหนึ่งแล้วและผู้ผลิตคอมไพเลอร์ C ++ รายใหญ่ทั้งหมดสนับสนุนมาตรฐาน ANSI
การเรียนรู้ C ++
สิ่งที่สำคัญที่สุดในขณะเรียนรู้ C ++ คือการเน้นแนวคิด
จุดประสงค์ของการเรียนรู้ภาษาโปรแกรมคือการเป็นโปรแกรมเมอร์ที่ดีขึ้น นั่นคือจะมีประสิทธิภาพมากขึ้นในการออกแบบและใช้ระบบใหม่และการดูแลระบบเก่า
C ++ รองรับรูปแบบการเขียนโปรแกรมที่หลากหลาย คุณสามารถเขียนในรูปแบบของ Fortran, C, Smalltalk และอื่น ๆ ในภาษาใดก็ได้ แต่ละสไตล์สามารถบรรลุจุดมุ่งหมายได้อย่างมีประสิทธิภาพในขณะที่ยังคงประสิทธิภาพของรันไทม์และพื้นที่
การใช้ C ++
C ++ ถูกใช้โดยโปรแกรมเมอร์หลายแสนคนในทุกโดเมนของแอปพลิเคชัน
C ++ ถูกใช้อย่างมากในการเขียนไดรเวอร์อุปกรณ์และซอฟต์แวร์อื่น ๆ ที่อาศัยการจัดการฮาร์ดแวร์โดยตรงภายใต้ข้อ จำกัด แบบเรียลไทม์
C ++ ถูกใช้อย่างกว้างขวางในการสอนและการวิจัยเนื่องจากมีความสะอาดเพียงพอสำหรับการสอนแนวคิดพื้นฐานที่ประสบความสำเร็จ
ใครก็ตามที่ใช้ Apple Macintosh หรือพีซีที่ใช้ Windows ได้ใช้ C ++ ทางอ้อมเนื่องจากอินเทอร์เฟซผู้ใช้หลักของระบบเหล่านี้เขียนด้วย C ++
การตั้งค่าสภาพแวดล้อมท้องถิ่น
หากคุณยังเต็มใจที่จะตั้งค่าสภาพแวดล้อมของคุณสำหรับ C ++ คุณจำเป็นต้องมีสองโปรแกรมต่อไปนี้ในคอมพิวเตอร์ของคุณ
แก้ไขข้อความ
สิ่งนี้จะใช้ในการพิมพ์โปรแกรมของคุณ ตัวอย่างของตัวแก้ไขบางตัว ได้แก่ Windows Notepad, OS Edit command, Brief, Epsilon, EMACS และ vim หรือ vi
ชื่อและเวอร์ชันของโปรแกรมแก้ไขข้อความอาจแตกต่างกันไปตามระบบปฏิบัติการต่างๆ ตัวอย่างเช่น Notepad จะใช้กับ Windows และสามารถใช้ vim หรือ vi บน windows ได้เช่นเดียวกับ Linux หรือ UNIX
ไฟล์ที่คุณสร้างด้วยโปรแกรมแก้ไขของคุณเรียกว่าไฟล์ต้นฉบับและสำหรับ C ++ โดยทั่วไปไฟล์เหล่านี้จะถูกตั้งชื่อด้วยนามสกุล. cpp, .cp หรือ. c
ควรมีโปรแกรมแก้ไขข้อความเพื่อเริ่มการเขียนโปรแกรม C ++ ของคุณ
คอมไพเลอร์ C ++
นี่คือคอมไพเลอร์ C ++ จริงซึ่งจะใช้ในการคอมไพล์ซอร์สโค้ดของคุณลงในโปรแกรมปฏิบัติการขั้นสุดท้าย
คอมไพเลอร์ C ++ ส่วนใหญ่ไม่สนใจว่าคุณจะให้ส่วนขยายใดกับซอร์สโค้ดของคุณ แต่ถ้าคุณไม่ระบุเป็นอย่างอื่นหลายคนจะใช้.
คอมไพเลอร์ที่ใช้บ่อยและฟรีที่มีอยู่คือคอมไพเลอร์ GNU C / C ++ มิฉะนั้นคุณสามารถมีคอมไพเลอร์จาก HP หรือ Solaris ได้หากคุณมีระบบปฏิบัติการที่เกี่ยวข้อง
การติดตั้ง GNU C / C ++ Compiler
การติดตั้ง UNIX / Linux
หากคุณกำลังใช้ Linux or UNIX จากนั้นตรวจสอบว่ามีการติดตั้ง GCC ในระบบของคุณหรือไม่โดยป้อนคำสั่งต่อไปนี้จากบรรทัดคำสั่ง -
$ g++ -v
หากคุณติดตั้ง GCC ควรพิมพ์ข้อความดังต่อไปนี้ -
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr .......
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
หากไม่ได้ติดตั้ง GCC คุณจะต้องติดตั้งด้วยตัวเองโดยใช้คำแนะนำโดยละเอียดที่มีอยู่ที่ https://gcc.gnu.org/install/
การติดตั้ง Mac OS X
หากคุณใช้ Mac OS X วิธีที่ง่ายที่สุดในการรับ GCC คือดาวน์โหลดสภาพแวดล้อมการพัฒนา Xcode จากเว็บไซต์ของ Apple และทำตามคำแนะนำในการติดตั้งอย่างง่าย
Xcode ใช้ได้ในขณะนี้ที่developer.apple.com/technologies/tools/
การติดตั้ง Windows
ในการติดตั้ง GCC บน Windows คุณต้องติดตั้ง MinGW ในการติดตั้ง MinGW ให้ไปที่โฮมเพจ MinGW www.mingw.orgและไปที่ลิงค์ไปยังหน้าดาวน์โหลด MinGW ดาวน์โหลดเวอร์ชันล่าสุดของโปรแกรมติดตั้ง MinGW ซึ่งควรมีชื่อว่า MinGW- <version> .exe
ในขณะติดตั้ง MinGW อย่างน้อยคุณต้องติดตั้ง gcc-core, gcc-g ++, binutils และรันไทม์ MinGW แต่คุณอาจต้องการติดตั้งเพิ่มเติม
เพิ่มไดเร็กทอรีย่อย bin ของการติดตั้ง MinGW ของคุณไปยังไฟล์ PATH ตัวแปรสภาพแวดล้อมเพื่อให้คุณสามารถระบุเครื่องมือเหล่านี้บนบรรทัดคำสั่งโดยใช้ชื่อง่าย ๆ
เมื่อการติดตั้งเสร็จสมบูรณ์คุณจะสามารถเรียกใช้ gcc, g ++, ar, ranlib, dlltool และเครื่องมือ GNU อื่น ๆ จากบรรทัดคำสั่งของ Windows
เมื่อเราพิจารณาโปรแกรม C ++ สามารถกำหนดเป็นชุดของวัตถุที่สื่อสารผ่านการเรียกใช้วิธีการของกันและกัน ตอนนี้ให้เราพิจารณาคร่าวๆว่าคลาสวัตถุวิธีการและตัวแปรทันทีหมายถึงอะไร
Object- วัตถุมีสถานะและพฤติกรรม ตัวอย่าง: สุนัขมีสถานะ - สีชื่อสายพันธุ์และพฤติกรรมเช่นการกระดิกการเห่าการกิน วัตถุคือตัวอย่างของการเรียน.
Class - คลาสสามารถกำหนดเป็นแม่แบบ / พิมพ์เขียวที่อธิบายพฤติกรรม / ระบุว่าวัตถุของประเภทสนับสนุน
Methods- โดยพื้นฐานแล้ววิธีการคือพฤติกรรม คลาสสามารถมีหลายวิธี มันอยู่ในเมธอดที่เขียนลอจิกข้อมูลจะถูกจัดการและดำเนินการทั้งหมด
Instance Variables- แต่ละออบเจ็กต์มีชุดตัวแปรอินสแตนซ์เฉพาะ สถานะของวัตถุถูกสร้างขึ้นโดยค่าที่กำหนดให้กับตัวแปรอินสแตนซ์เหล่านี้
โครงสร้างโปรแกรม C ++
ให้เราดูที่รหัสที่ง่ายที่จะพิมพ์คำว่าHello World
#include <iostream>
using namespace std;
// main() is where program execution begins.
int main() {
cout << "Hello World"; // prints Hello World
return 0;
}
ให้เราดูส่วนต่างๆของโปรแกรมข้างต้น -
ภาษา C ++ กำหนดส่วนหัวหลายส่วนซึ่งมีข้อมูลที่จำเป็นหรือเป็นประโยชน์ต่อโปรแกรมของคุณ สำหรับโปรแกรมนี้ส่วนหัว<iostream> มันจำเป็น.
เส้น using namespace std;บอกให้คอมไพเลอร์ใช้เนมสเปซมาตรฐาน Namespaces เป็นส่วนเสริมล่าสุดของ C ++
บรรทัดถัดไป '// main() is where program execution begins.'เป็นความคิดเห็นบรรทัดเดียวที่มีอยู่ใน C ++ ความคิดเห็นบรรทัดเดียวเริ่มต้นด้วย // และหยุดที่ท้ายบรรทัด
เส้น int main() เป็นฟังก์ชันหลักที่เริ่มการทำงานของโปรแกรม
บรรทัดถัดไป cout << "Hello World"; ทำให้ข้อความ "Hello World" ปรากฏบนหน้าจอ
บรรทัดถัดไป return 0; ยุติฟังก์ชัน main () และส่งคืนค่า 0 ให้กับกระบวนการเรียก
คอมไพล์และรันโปรแกรม C ++
มาดูวิธีการบันทึกไฟล์คอมไพล์และรันโปรแกรม โปรดทำตามขั้นตอนด้านล่าง -
เปิดโปรแกรมแก้ไขข้อความและเพิ่มรหัสตามด้านบน
บันทึกไฟล์เป็น: hello.cpp
เปิดพรอมต์คำสั่งและไปที่ไดเร็กทอรีที่คุณบันทึกไฟล์
พิมพ์ 'g ++ hello.cpp' แล้วกด Enter เพื่อรวบรวมรหัสของคุณ หากไม่มีข้อผิดพลาดในโค้ดของคุณพรอมต์คำสั่งจะนำคุณไปยังบรรทัดถัดไปและจะสร้างไฟล์ปฏิบัติการ a.out
ตอนนี้พิมพ์ 'a.out' เพื่อเรียกใช้โปรแกรมของคุณ
คุณจะเห็น 'Hello World' พิมพ์อยู่บนหน้าต่าง
$ g++ hello.cpp
$ ./a.out
Hello World
ตรวจสอบให้แน่ใจว่า g ++ อยู่ในเส้นทางของคุณและคุณกำลังเรียกใช้ในไดเร็กทอรีที่มีไฟล์ hello.cpp
คุณสามารถคอมไพล์โปรแกรม C / C ++ โดยใช้ makefile สำหรับรายละเอียดเพิ่มเติมคุณสามารถตรวจสอบ'Makefile Tutorial' ของเรา
อัฒภาคและบล็อกใน C ++
ใน C ++ อัฒภาคเป็นตัวยุติคำสั่ง นั่นคือแต่ละคำสั่งจะต้องลงท้ายด้วยอัฒภาค ระบุจุดสิ้นสุดของเอนทิตีตรรกะหนึ่ง
ตัวอย่างเช่นต่อไปนี้เป็นข้อความที่แตกต่างกันสามแบบ -
x = y;
y = y + 1;
add(x, y);
บล็อกคือชุดของคำสั่งที่เชื่อมต่อกันทางตรรกะซึ่งล้อมรอบด้วยเครื่องหมายปีกกาเปิดและปิด ตัวอย่างเช่น -
{
cout << "Hello World"; // prints Hello World
return 0;
}
C ++ ไม่รู้จักท้ายบรรทัดเป็นเทอร์มิเนเตอร์ ด้วยเหตุนี้จึงไม่สำคัญว่าคุณจะใส่คำสั่งไว้ที่ใด ตัวอย่างเช่น -
x = y;
y = y + 1;
add(x, y);
เหมือนกับ
x = y; y = y + 1; add(x, y);
ตัวระบุ C ++
ตัวระบุ C ++ คือชื่อที่ใช้ในการระบุตัวแปรฟังก์ชันคลาสโมดูลหรือรายการอื่น ๆ ที่ผู้ใช้กำหนดเอง ตัวระบุเริ่มต้นด้วยตัวอักษร A ถึง Z หรือ a ถึง z หรือขีดล่าง (_) ตามด้วยตัวอักษรศูนย์หรือมากกว่าขีดล่างและตัวเลข (0 ถึง 9)
C ++ ไม่อนุญาตให้ใช้อักขระเครื่องหมายวรรคตอนเช่น @, $ และ% ภายในตัวระบุ C ++ เป็นภาษาโปรแกรมที่คำนึงถึงขนาดตัวพิมพ์ ด้วยประการฉะนี้Manpower และ manpower เป็นตัวระบุสองตัวที่แตกต่างกันใน C ++
นี่คือตัวอย่างบางส่วนของตัวระบุที่ยอมรับได้ -
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
คำหลัก C ++
รายการต่อไปนี้แสดงคำสงวนใน C ++ ห้ามใช้คำสงวนเหล่านี้เป็นค่าคงที่หรือตัวแปรหรือชื่อตัวระบุอื่น ๆ
asm | อื่น | ใหม่ | นี้ |
อัตโนมัติ | enum | ตัวดำเนินการ | โยน |
บูล | ชัดเจน | เอกชน | จริง |
หยุดพัก | ส่งออก | มีการป้องกัน | ลอง |
กรณี | ภายนอก | สาธารณะ | typedef |
จับ | เท็จ | ลงทะเบียน | typeid |
ถ่าน | ลอย | reinterpret_cast | ชื่อ |
ชั้นเรียน | สำหรับ | กลับ | สหภาพแรงงาน |
const | เพื่อน | สั้น | ไม่ได้ลงนาม |
const_cast | ไปที่ | ลงนาม | โดยใช้ |
ดำเนินการต่อ | ถ้า | ขนาดของ | เสมือน |
ค่าเริ่มต้น | อินไลน์ | คงที่ | เป็นโมฆะ |
ลบ | int | static_cast | ระเหย |
ทำ | ยาว | โครงสร้าง | wchar_t |
สองเท่า | ไม่แน่นอน | สวิตซ์ | ในขณะที่ |
dynamic_cast | เนมสเปซ | แม่แบบ |
Trigraphs
อักขระสองสามตัวมีการแทนค่าอื่นเรียกว่าลำดับตรีโกณมิติ ตรีโกณมิติคือลำดับอักขระสามตัวที่แสดงถึงอักขระตัวเดียวและลำดับจะขึ้นต้นด้วยเครื่องหมายคำถามสองตัวเสมอ
Trigraphs จะขยายได้ทุกที่ที่ปรากฏรวมทั้งภายในตัวอักษรสตริงและตัวอักษรในความคิดเห็นและในคำสั่งของตัวประมวลผลล่วงหน้า
ต่อไปนี้เป็นลำดับตรีโกณมิติที่ใช้บ่อยที่สุด -
Trigraph | เปลี่ยน |
---|---|
?? = | # |
?? / | \ |
?? ' | ^ |
?? ( | [ |
??) | ] |
??! | | |
?? < | { |
??> | } |
?? - | ~ |
คอมไพเลอร์ทั้งหมดไม่รองรับทริกกราฟและไม่แนะนำให้ใช้เนื่องจากลักษณะที่สับสน
ช่องว่างใน C ++
บรรทัดที่มีเฉพาะช่องว่างซึ่งอาจมีข้อคิดเห็นเรียกว่าบรรทัดว่างและคอมไพเลอร์ C ++ จะละเว้นโดยสิ้นเชิง
Whitespace เป็นคำที่ใช้ใน C ++ เพื่ออธิบายช่องว่างแท็บอักขระขึ้นบรรทัดใหม่และข้อคิดเห็น ช่องว่างแยกส่วนหนึ่งของคำสั่งออกจากอีกส่วนหนึ่งและช่วยให้คอมไพเลอร์ระบุตำแหน่งที่องค์ประกอบหนึ่งในคำสั่งเช่น int สิ้นสุดลงและองค์ประกอบถัดไปเริ่มต้น
คำชี้แจง 1
int age;
ในข้อความข้างต้นจะต้องมีอักขระช่องว่างอย่างน้อยหนึ่งอักขระ (โดยปกติจะเป็นช่องว่าง) ระหว่าง int และอายุเพื่อให้คอมไพเลอร์สามารถแยกแยะได้
คำชี้แจง 2
fruit = apples + oranges; // Get the total fruit
ในข้อความข้างต้น 2 ไม่จำเป็นต้องใช้อักขระเว้นวรรคระหว่างผลไม้และ = หรือระหว่าง = และแอปเปิ้ลแม้ว่าคุณจะมีอิสระที่จะรวมบางส่วนหากคุณต้องการเพื่อจุดประสงค์ในการอ่าน
ความคิดเห็นของโปรแกรมเป็นข้อความอธิบายที่คุณสามารถรวมไว้ในรหัส C ++ ความคิดเห็นเหล่านี้ช่วยให้ทุกคนที่อ่านซอร์สโค้ด ภาษาโปรแกรมทั้งหมดอนุญาตให้แสดงความคิดเห็นบางรูปแบบ
C ++ รองรับความคิดเห็นแบบบรรทัดเดียวและหลายบรรทัด อักขระทั้งหมดที่มีอยู่ในข้อคิดเห็นใด ๆ จะถูกละเว้นโดยคอมไพเลอร์ C ++
ความคิดเห็น C ++ ขึ้นต้นด้วย / * และลงท้ายด้วย * / ตัวอย่างเช่น -
/* This is a comment */
/* C++ comments can also
* span multiple lines
*/
ความคิดเห็นยังสามารถขึ้นต้นด้วย // ขยายไปจนสุดบรรทัด ตัวอย่างเช่น -
#include <iostream>
using namespace std;
main() {
cout << "Hello World"; // prints Hello World
return 0;
}
เมื่อคอมไพล์โค้ดด้านบนแล้วจะไม่สนใจ // prints Hello World และปฏิบัติการขั้นสุดท้ายจะให้ผลลัพธ์ดังต่อไปนี้ -
Hello World
ภายใน a / * และ * / comment อักขระ // ไม่มีความหมายพิเศษ ภายใน // ความคิดเห็น / * และ * / ไม่มีความหมายพิเศษ ดังนั้นคุณสามารถ "ซ้อน" ความคิดเห็นประเภทหนึ่งในอีกประเภทหนึ่งได้ ตัวอย่างเช่น -
/* Comment out printing of Hello World:
cout << "Hello World"; // prints Hello World
*/
ในขณะที่เขียนโปรแกรมด้วยภาษาใด ๆ คุณจำเป็นต้องใช้ตัวแปรต่างๆเพื่อจัดเก็บข้อมูลต่างๆ ตัวแปรไม่ใช่อะไรเลยนอกจากตำแหน่งหน่วยความจำที่สงวนไว้เพื่อเก็บค่า ซึ่งหมายความว่าเมื่อคุณสร้างตัวแปรคุณจะสงวนพื้นที่ในหน่วยความจำไว้
คุณอาจต้องการจัดเก็บข้อมูลประเภทข้อมูลต่างๆเช่นอักขระอักขระแบบกว้างจำนวนเต็มจุดลอยตัวจุดลอยตัวคู่บูลีนเป็นต้นตามประเภทข้อมูลของตัวแปรระบบปฏิบัติการจะจัดสรรหน่วยความจำและตัดสินใจว่าจะจัดเก็บอะไรใน หน่วยความจำที่สงวนไว้
ประเภทในตัวดั้งเดิม
C ++ เสนอโปรแกรมเมอร์ประเภทข้อมูลในตัวและประเภทข้อมูลที่กำหนดโดยผู้ใช้ ตารางต่อไปนี้แสดงประเภทข้อมูล C ++ พื้นฐานเจ็ดประเภท -
ประเภท | คำสำคัญ |
---|---|
บูลีน | บูล |
ตัวละคร | ถ่าน |
จำนวนเต็ม | int |
จุดลอยตัว | ลอย |
จุดลอยตัวคู่ | สองเท่า |
ไร้ค่า | เป็นโมฆะ |
ตัวอักษรกว้าง | wchar_t |
สามารถแก้ไขประเภทพื้นฐานได้หลายประเภทโดยใช้ตัวปรับแต่งประเภทเหล่านี้อย่างน้อยหนึ่งประเภท -
- signed
- unsigned
- short
- long
ตารางต่อไปนี้แสดงประเภทตัวแปรจำนวนหน่วยความจำที่ใช้ในการจัดเก็บค่าในหน่วยความจำและค่าสูงสุดและต่ำสุดคือเท่าใดซึ่งสามารถเก็บไว้ในตัวแปรประเภทดังกล่าวได้
ประเภท | ความกว้างบิตทั่วไป | ช่วงทั่วไป |
---|---|---|
ถ่าน | 1 ไบต์ | -127 ถึง 127 หรือ 0 ถึง 255 |
ถ่านที่ไม่ได้ลงนาม | 1 ไบต์ | 0 ถึง 255 |
ลงนามถ่าน | 1 ไบต์ | -127 ถึง 127 |
int | 4 ไบต์ | -2147483648 ถึง 2147483647 |
int ที่ไม่ได้ลงนาม | 4 ไบต์ | 0 ถึง 4294967295 |
ลงนาม int | 4 ไบต์ | -2147483648 ถึง 2147483647 |
int สั้น ๆ | 2 ไบต์ | -32768 ถึง 32767 |
int สั้นที่ไม่ได้ลงนาม | 2 ไบต์ | 0 ถึง 65,535 |
ลงนามสั้น int | 2 ไบต์ | -32768 ถึง 32767 |
int ยาว | 8 ไบต์ | -2,147,483,648 ถึง 2,147,483,647 |
ลงนามยาว int | 8 ไบต์ | เช่นเดียวกับ int ยาว |
int ยาวที่ไม่ได้ลงนาม | 8 ไบต์ | 0 ถึง 4,294,967,295 |
int ยาวยาว | 8 ไบต์ | - (2 ^ 63) ถึง (2 ^ 63) -1 |
int ยาวยาวที่ไม่ได้ลงนาม | 8 ไบต์ | 0 ถึง 18,446,744,073,709,551,615 |
ลอย | 4 ไบต์ | |
สองเท่า | 8 ไบต์ | |
คู่ยาว | 12 ไบต์ | |
wchar_t | 2 หรือ 4 ไบต์ | อักขระกว้าง 1 ตัว |
ขนาดของตัวแปรอาจแตกต่างจากที่แสดงในตารางด้านบนขึ้นอยู่กับคอมไพเลอร์และคอมพิวเตอร์ที่คุณใช้
ต่อไปนี้เป็นตัวอย่างซึ่งจะสร้างขนาดข้อมูลที่ถูกต้องในคอมพิวเตอร์ของคุณ
#include <iostream>
using namespace std;
int main() {
cout << "Size of char : " << sizeof(char) << endl;
cout << "Size of int : " << sizeof(int) << endl;
cout << "Size of short int : " << sizeof(short int) << endl;
cout << "Size of long int : " << sizeof(long int) << endl;
cout << "Size of float : " << sizeof(float) << endl;
cout << "Size of double : " << sizeof(double) << endl;
cout << "Size of wchar_t : " << sizeof(wchar_t) << endl;
return 0;
}
ตัวอย่างนี้ใช้ endlซึ่งจะแทรกอักขระขึ้นบรรทัดใหม่หลังทุกบรรทัดและ << โอเปอเรเตอร์จะถูกใช้เพื่อส่งผ่านค่าหลายค่าไปยังหน้าจอ เรายังใช้sizeof() ตัวดำเนินการเพื่อรับขนาดของข้อมูลประเภทต่างๆ
เมื่อรวบรวมและดำเนินการโค้ดด้านบนจะให้ผลลัพธ์ต่อไปนี้ซึ่งอาจแตกต่างกันไปในแต่ละเครื่อง -
Size of char : 1
Size of int : 4
Size of short int : 2
Size of long int : 4
Size of float : 4
Size of double : 8
Size of wchar_t : 4
การประกาศ typedef
คุณสามารถสร้างชื่อใหม่สำหรับประเภทที่มีอยู่โดยใช้ typedef. ต่อไปนี้เป็นไวยากรณ์ง่ายๆในการกำหนดประเภทใหม่โดยใช้ typedef -
typedef type newname;
ตัวอย่างเช่นต่อไปนี้จะบอกคอมไพเลอร์ว่าฟุตเป็นชื่ออื่นสำหรับ int -
typedef int feet;
ตอนนี้การประกาศต่อไปนี้ถูกต้องตามกฎหมายและสร้างตัวแปรจำนวนเต็มที่เรียกว่าระยะทาง -
feet distance;
ประเภทแจกแจง
ประเภทที่แจกแจงประกาศชื่อชนิดที่เป็นทางเลือกและชุดของตัวระบุศูนย์หรือมากกว่าที่สามารถใช้เป็นค่าของชนิด ตัวแจงนับแต่ละตัวเป็นค่าคงที่ซึ่งเป็นชนิดของการแจงนับ
การสร้างการแจงนับจำเป็นต้องใช้คีย์เวิร์ด enum. รูปแบบทั่วไปของประเภทการแจงนับคือ -
enum enum-name { list of names } var-list;
ในที่นี้ enum-name คือชื่อประเภทของการแจงนับ รายชื่อจะคั่นด้วยจุลภาค
ตัวอย่างเช่นรหัสต่อไปนี้กำหนดการแจกแจงสีที่เรียกว่าสีและตัวแปร c ของชนิดสี สุดท้าย c กำหนดค่าเป็น "สีน้ำเงิน"
enum color { red, green, blue } c;
c = blue;
ตามค่าเริ่มต้นค่าของชื่อแรกคือ 0 ชื่อที่สองมีค่า 1 และค่าที่สามมีค่า 2 เป็นต้น แต่คุณสามารถตั้งชื่อเป็นค่าเฉพาะได้โดยการเพิ่มตัวเริ่มต้น ตัวอย่างเช่นในการแจงนับต่อไปนี้green จะมีค่า 5
enum color { red, green = 5, blue };
ที่นี่ blue จะมีค่าเป็น 6 เนื่องจากแต่ละชื่อจะมีค่ามากกว่าหนึ่งชื่อที่นำหน้า
ตัวแปรช่วยให้เรามีพื้นที่จัดเก็บที่มีชื่อซึ่งโปรแกรมของเราสามารถจัดการได้ ตัวแปรแต่ละตัวใน C ++ มีประเภทเฉพาะซึ่งกำหนดขนาดและรูปแบบของหน่วยความจำของตัวแปร ช่วงของค่าที่สามารถเก็บไว้ในหน่วยความจำนั้น และชุดของการดำเนินการที่สามารถนำไปใช้กับตัวแปร
ชื่อของตัวแปรสามารถประกอบด้วยตัวอักษรตัวเลขและอักขระขีดล่าง ต้องขึ้นต้นด้วยตัวอักษรหรือขีดล่าง อักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กมีความแตกต่างกันเนื่องจาก C ++ เป็นตัวพิมพ์เล็ก - ใหญ่ -
ประเภทพื้นฐานของตัวแปรใน C ++ มีดังต่อไปนี้ตามที่อธิบายไว้ในบทสุดท้าย -
ซีเนียร์ No | ประเภทและคำอธิบาย |
---|---|
1 | bool เก็บค่าเป็นจริงหรือเท็จ |
2 | char โดยทั่วไปเป็นอ็อกเต็ตเดี่ยว (หนึ่งไบต์) นี่คือประเภทจำนวนเต็ม |
3 | int ขนาดของจำนวนเต็มที่เป็นธรรมชาติที่สุดสำหรับเครื่อง |
4 | float ค่าทศนิยมที่มีความแม่นยำเดียว |
5 | double ค่าทศนิยมที่มีความแม่นยำสองเท่า |
6 | void แสดงถึงการไม่มีประเภท |
7 | wchar_t ประเภทอักขระแบบกว้าง |
C ++ ยังอนุญาตให้กำหนดตัวแปรประเภทอื่น ๆ อีกมากมายซึ่งเราจะกล่าวถึงในบทต่อ ๆ ไปเช่น Enumeration, Pointer, Array, Reference, Data structures, และ Classes.
ส่วนต่อไปนี้จะกล่าวถึงวิธีการกำหนดประกาศและใช้ตัวแปรประเภทต่างๆ
นิยามตัวแปรใน C ++
นิยามตัวแปรจะบอกคอมไพลเลอร์ว่าจะสร้างหน่วยเก็บข้อมูลสำหรับตัวแปรได้ที่ไหนและเท่าใด นิยามตัวแปรระบุชนิดข้อมูลและมีรายการตัวแปรประเภทนั้นอย่างน้อยหนึ่งรายการดังนี้ -
type variable_list;
ที่นี่ type ต้องเป็นประเภทข้อมูล C ++ ที่ถูกต้องรวมถึง char, w_char, int, float, double, bool หรือวัตถุที่ผู้ใช้กำหนดเองเป็นต้นและ variable_listอาจประกอบด้วยชื่อตัวบ่งชี้อย่างน้อยหนึ่งชื่อโดยคั่นด้วยเครื่องหมายจุลภาค การประกาศที่ถูกต้องบางส่วนแสดงไว้ที่นี่ -
int i, j, k;
char c, ch;
float f, salary;
double d;
เส้น int i, j, k;ทั้งประกาศและกำหนดตัวแปร i, j และ k; ซึ่งสั่งให้คอมไพเลอร์สร้างตัวแปรชื่อ i, j และ k ประเภท int
ตัวแปรสามารถเริ่มต้นได้ (กำหนดค่าเริ่มต้น) ในการประกาศ initializer ประกอบด้วยเครื่องหมายเท่ากับตามด้วยนิพจน์คงที่ดังนี้ -
type variable_name = value;
ตัวอย่างบางส่วน ได้แก่ -
extern int d = 3, f = 5; // declaration of d and f.
int d = 3, f = 5; // definition and initializing d and f.
byte z = 22; // definition and initializes z.
char x = 'x'; // the variable x has the value 'x'.
สำหรับนิยามที่ไม่มีตัวเริ่มต้น: ตัวแปรที่มีระยะเวลาการจัดเก็บแบบคงที่จะเริ่มต้นโดยปริยายด้วย NULL (ไบต์ทั้งหมดมีค่า 0) ไม่ได้กำหนดค่าเริ่มต้นของตัวแปรอื่น ๆ ทั้งหมด
การประกาศตัวแปรใน C ++
การประกาศตัวแปรให้การรับรองกับคอมไพลเลอร์ว่ามีตัวแปรหนึ่งตัวที่มีอยู่ในประเภทและชื่อที่กำหนดเพื่อให้คอมไพลเลอร์ดำเนินการรวบรวมต่อไปโดยไม่ต้องการรายละเอียดทั้งหมดเกี่ยวกับตัวแปร การประกาศตัวแปรมีความหมายในช่วงเวลาของการคอมไพล์เท่านั้นคอมไพเลอร์ต้องการนิยามตัวแปรจริงในขณะที่เชื่อมโยงโปรแกรม
การประกาศตัวแปรมีประโยชน์เมื่อคุณใช้หลายไฟล์และคุณกำหนดตัวแปรของคุณในไฟล์ใดไฟล์หนึ่งซึ่งจะพร้อมใช้งานในขณะที่เชื่อมโยงโปรแกรม คุณจะใช้externคีย์เวิร์ดเพื่อประกาศตัวแปร ณ ที่ใด ๆ แม้ว่าคุณจะสามารถประกาศตัวแปรได้หลายครั้งในโปรแกรม C ++ แต่สามารถกำหนดได้เพียงครั้งเดียวในไฟล์ฟังก์ชันหรือบล็อกโค้ด
ตัวอย่าง
ลองใช้ตัวอย่างต่อไปนี้ที่มีการประกาศตัวแปรที่ด้านบน แต่ถูกกำหนดไว้ภายในฟังก์ชันหลัก -
#include <iostream>
using namespace std;
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main () {
// Variable definition:
int a, b;
int c;
float f;
// actual initialization
a = 10;
b = 20;
c = a + b;
cout << c << endl ;
f = 70.0/3.0;
cout << f << endl ;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
30
23.3333
แนวคิดเดียวกันนี้ใช้กับการประกาศฟังก์ชันที่คุณระบุชื่อฟังก์ชันในขณะที่ประกาศและสามารถกำหนดนิยามที่แท้จริงได้จากที่อื่น ตัวอย่างเช่น -
// function declaration
int func();
int main() {
// function call
int i = func();
}
// function definition
int func() {
return 0;
}
Lvalues และ Rvalues
มีสองประเภทของนิพจน์ใน C ++ -
lvalue- นิพจน์ที่อ้างถึงตำแหน่งหน่วยความจำเรียกว่านิพจน์ "lvalue" ค่า lvalue อาจปรากฏเป็นด้านซ้ายหรือด้านขวาของงาน
rvalue- คำว่า rvalue หมายถึงค่าข้อมูลที่เก็บไว้ที่ที่อยู่บางส่วนในหน่วยความจำ rvalue คือนิพจน์ที่ไม่สามารถกำหนดค่าได้ซึ่งหมายความว่า rvalue อาจปรากฏทางด้านขวา แต่ไม่ใช่ด้านซ้ายของงาน
ตัวแปรคือ lvalues ดังนั้นจึงอาจปรากฏทางด้านซ้ายมือของงาน ตัวอักษรตัวเลขเป็นค่า r จึงไม่สามารถกำหนดได้และจะไม่ปรากฏทางด้านซ้ายมือ ต่อไปนี้เป็นคำสั่งที่ถูกต้อง -
int g = 20;
แต่สิ่งต่อไปนี้ไม่ใช่คำสั่งที่ถูกต้องและจะสร้างข้อผิดพลาดเวลาคอมไพล์ -
10 = 20;
ขอบเขตคือขอบเขตของโปรแกรมและกล่าวอย่างกว้าง ๆ มีสามตำแหน่งที่สามารถประกาศตัวแปรได้ -
ภายในฟังก์ชันหรือบล็อกซึ่งเรียกว่าตัวแปรท้องถิ่น
ในนิยามของพารามิเตอร์ฟังก์ชันซึ่งเรียกว่าพารามิเตอร์ทางการ
นอกฟังก์ชันทั้งหมดซึ่งเรียกว่าตัวแปรส่วนกลาง
เราจะเรียนรู้ว่าอะไรคือฟังก์ชันและพารามิเตอร์ของมันในบทต่อ ๆ ไป ที่นี่ให้เราอธิบายว่าตัวแปรท้องถิ่นและทั่วโลกคืออะไร
ตัวแปรท้องถิ่น
ตัวแปรที่ประกาศภายในฟังก์ชันหรือบล็อกเป็นตัวแปรภายใน สามารถใช้ได้โดยคำสั่งที่อยู่ในฟังก์ชันหรือบล็อกโค้ดนั้นเท่านั้น ตัวแปรท้องถิ่นไม่รู้จักฟังก์ชันภายนอกตัวเอง ต่อไปนี้เป็นตัวอย่างการใช้ตัวแปรท้องถิ่น -
#include <iostream>
using namespace std;
int main () {
// Local variable declaration:
int a, b;
int c;
// actual initialization
a = 10;
b = 20;
c = a + b;
cout << c;
return 0;
}
ตัวแปรส่วนกลาง
ตัวแปรส่วนกลางถูกกำหนดไว้นอกฟังก์ชันทั้งหมดโดยปกติจะอยู่ด้านบนของโปรแกรม ตัวแปรส่วนกลางจะคงคุณค่าไว้ตลอดอายุของโปรแกรมของคุณ
ฟังก์ชันใด ๆ สามารถเข้าถึงตัวแปรส่วนกลางได้ นั่นคือตัวแปรส่วนกลางพร้อมใช้งานตลอดทั้งโปรแกรมของคุณหลังจากการประกาศ ต่อไปนี้เป็นตัวอย่างการใช้ตัวแปรส่วนกลางและท้องถิ่น -
#include <iostream>
using namespace std;
// Global variable declaration:
int g;
int main () {
// Local variable declaration:
int a, b;
// actual initialization
a = 10;
b = 20;
g = a + b;
cout << g;
return 0;
}
โปรแกรมสามารถมีชื่อเดียวกันสำหรับตัวแปรโลคัลและโกลบอล แต่ค่าของตัวแปรโลคัลภายในฟังก์ชันจะใช้ค่ากำหนด ตัวอย่างเช่น -
#include <iostream>
using namespace std;
// Global variable declaration:
int g = 20;
int main () {
// Local variable declaration:
int g = 10;
cout << g;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
10
การเริ่มต้นตัวแปรท้องถิ่นและทั่วโลก
เมื่อกำหนดตัวแปรภายในระบบจะไม่เริ่มต้นคุณต้องเตรียมข้อมูลเบื้องต้นด้วยตนเอง ระบบจะเริ่มต้นตัวแปรส่วนกลางโดยอัตโนมัติเมื่อคุณกำหนดตัวแปรดังต่อไปนี้ -
ประเภทข้อมูล | Initializer |
---|---|
int | 0 |
ถ่าน | '\ 0' |
ลอย | 0 |
สองเท่า | 0 |
ตัวชี้ | NULL |
เป็นการฝึกเขียนโปรแกรมที่ดีในการเริ่มต้นตัวแปรอย่างเหมาะสมมิฉะนั้นบางครั้งโปรแกรมอาจให้ผลลัพธ์ที่ไม่คาดคิด
ค่าคงที่หมายถึงค่าคงที่ซึ่งโปรแกรมอาจไม่เปลี่ยนแปลงและถูกเรียกใช้ literals.
ค่าคงที่สามารถเป็นชนิดข้อมูลพื้นฐานใดก็ได้และสามารถแบ่งออกเป็นเลขจำนวนเต็มตัวเลขจุดลอยตัวอักขระสตริงและค่าบูลีน
อีกครั้งค่าคงที่ได้รับการปฏิบัติเช่นเดียวกับตัวแปรทั่วไปยกเว้นว่าค่าของพวกเขาไม่สามารถแก้ไขได้หลังจากนิยามแล้ว
ตัวอักษรจำนวนเต็ม
ลิเทอรัลจำนวนเต็มสามารถเป็นค่าคงที่ทศนิยมฐานแปดหรือฐานสิบหก คำนำหน้าระบุฐานหรือรัศมี: 0x หรือ 0X สำหรับเลขฐานสิบหก, 0 สำหรับฐานแปดและไม่มีอะไรเป็นทศนิยม
ลิเทอรัลจำนวนเต็มยังสามารถมีส่วนต่อท้ายที่รวมกันของ U และ L สำหรับไม่ได้ลงนามและยาวตามลำดับ คำต่อท้ายสามารถเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กและสามารถเรียงลำดับอย่างไรก็ได้
นี่คือตัวอย่างบางส่วนของตัวอักษรจำนวนเต็ม -
212 // Legal
215u // Legal
0xFeeL // Legal
078 // Illegal: 8 is not an octal digit
032UU // Illegal: cannot repeat a suffix
ต่อไปนี้เป็นตัวอย่างอื่น ๆ ของตัวอักษรจำนวนเต็มประเภทต่างๆ -
85 // decimal
0213 // octal
0x4b // hexadecimal
30 // int
30u // unsigned int
30l // long
30ul // unsigned long
Floating-point Literals
ลิเทอรัลจุดลอยตัวมีส่วนจำนวนเต็มจุดทศนิยมส่วนเศษส่วนและส่วนเลขชี้กำลัง คุณสามารถแสดงลิเทอรัลจุดลอยตัวได้ทั้งในรูปแบบทศนิยมหรือรูปแบบเลขชี้กำลัง
ในขณะที่แสดงโดยใช้รูปแบบทศนิยมคุณต้องใส่จุดทศนิยมเลขชี้กำลังหรือทั้งสองอย่างและในขณะที่แสดงโดยใช้รูปแบบเลขชี้กำลังคุณต้องรวมส่วนจำนวนเต็มส่วนเศษส่วนหรือทั้งสองอย่าง เลขชี้กำลังที่ลงชื่อถูกนำมาใช้โดย e หรือ E
นี่คือตัวอย่างบางส่วนของตัวอักษรทศนิยม -
3.14159 // Legal
314159E-5L // Legal
510E // Illegal: incomplete exponent
210f // Illegal: no decimal or exponent
.e55 // Illegal: missing integer or fraction
ตัวอักษรบูลีน
มีลิเทอรัลบูลีนสองตัวและเป็นส่วนหนึ่งของคีย์เวิร์ด C ++ มาตรฐาน -
ค่าของ true เป็นตัวแทนของความจริง
ค่าของ false เป็นตัวแทนของเท็จ
คุณไม่ควรพิจารณาค่าของจริงเท่ากับ 1 และค่าของเท็จเท่ากับ 0
ตัวอักษร
ตามตัวอักษรอยู่ในเครื่องหมายคำพูดเดี่ยว ถ้าลิเทอรัลขึ้นต้นด้วย L (ตัวพิมพ์ใหญ่เท่านั้น) แสดงว่าลิเทอรัลเป็นอักขระแบบกว้าง (เช่น L'x ') และควรเก็บไว้ในwchar_tประเภทของตัวแปร มิฉะนั้นจะเป็นอักขระตามตัวอักษรแคบ (เช่น 'x') และสามารถเก็บไว้ในตัวแปรง่ายๆของchar ประเภท.
อักขระลิเทอรัลอาจเป็นอักขระธรรมดา (เช่น 'x'), ลำดับการหลีก (เช่น '\ t') หรืออักขระสากล (เช่น '\ u02C0')
มีอักขระบางตัวใน C ++ เมื่อนำหน้าด้วยแบ็กสแลชซึ่งจะมีความหมายพิเศษและใช้แทนเช่น newline (\ n) หรือ tab (\ t) ที่นี่คุณมีรายการรหัสลำดับการหลบหนีดังกล่าว -
ลำดับการหลบหนี | ความหมาย |
---|---|
\\ | \ อักขระ |
\ ' | 'ตัวละคร |
\ " | "ตัวละคร |
\? | เหรอ? ตัวละคร |
\ ก | แจ้งเตือนหรือกระดิ่ง |
\ b | Backspace |
\ ฉ | ฟีดรูปแบบ |
\ n | ขึ้นบรรทัดใหม่ |
\ r | การกลับรถ |
\ t | แท็บแนวนอน |
\ v | แท็บแนวตั้ง |
\ ooo | เลขฐานแปดหนึ่งถึงสามหลัก |
\ xhh . . | เลขฐานสิบหกของตัวเลขตั้งแต่หนึ่งหลักขึ้นไป |
ต่อไปนี้เป็นตัวอย่างเพื่อแสดงอักขระลำดับการหลีกเลี่ยงไม่กี่ตัว -
#include <iostream>
using namespace std;
int main() {
cout << "Hello\tWorld\n\n";
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Hello World
ตัวอักษรสตริง
ตัวอักษรสตริงอยู่ในเครื่องหมายคำพูดคู่ สตริงประกอบด้วยอักขระที่คล้ายกับตัวอักษรอักขระ: อักขระธรรมดาลำดับการหลีกและอักขระสากล
คุณสามารถแบ่งบรรทัดยาวออกเป็นหลายบรรทัดโดยใช้ตัวอักษรสตริงและแยกออกโดยใช้ช่องว่าง
นี่คือตัวอย่างบางส่วนของตัวอักษรสตริง ทั้งสามรูปแบบเป็นสตริงที่เหมือนกัน
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
การกำหนดค่าคงที่
มีสองวิธีง่ายๆใน C ++ ในการกำหนดค่าคงที่ -
การใช้ #define พรีโปรเซสเซอร์
การใช้ const คำสำคัญ.
#define พรีโปรเซสเซอร์
ต่อไปนี้เป็นรูปแบบที่จะใช้ #define preprocessor เพื่อกำหนดค่าคงที่ -
#define identifier value
ตัวอย่างต่อไปนี้อธิบายโดยละเอียด -
#include <iostream>
using namespace std;
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main() {
int area;
area = LENGTH * WIDTH;
cout << area;
cout << NEWLINE;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
50
คีย์เวิร์ด const
คุณสามารถใช้ได้ const คำนำหน้าเพื่อประกาศค่าคงที่ด้วยประเภทเฉพาะดังนี้ -
const type variable = value;
ตัวอย่างต่อไปนี้อธิบายโดยละเอียด -
#include <iostream>
using namespace std;
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
int area;
area = LENGTH * WIDTH;
cout << area;
cout << NEWLINE;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
50
โปรดทราบว่าการเขียนโปรแกรมเป็นวิธีที่ดีในการกำหนดค่าคงที่ในตัวพิมพ์ใหญ่
C ++ อนุญาตให้ char, int, และ doubleชนิดข้อมูลที่มีตัวปรับแต่งอยู่ข้างหน้า ตัวปรับแต่งใช้เพื่อเปลี่ยนความหมายของประเภทพื้นฐานเพื่อให้ตรงกับความต้องการของสถานการณ์ต่างๆ
ตัวปรับเปลี่ยนประเภทข้อมูลแสดงอยู่ที่นี่ -
- signed
- unsigned
- long
- short
ตัวปรับเปลี่ยน signed, unsigned, long, และ shortสามารถนำไปใช้กับประเภทฐานจำนวนเต็ม นอกจากนี้signed และ unsigned สามารถนำไปใช้กับถ่านและ long สามารถใช้กับ double
ตัวปรับเปลี่ยน signed และ unsigned ยังสามารถใช้เป็นคำนำหน้าได้ long หรือ shortตัวดัดแปลง ตัวอย่างเช่น,unsigned long int.
C ++ อนุญาตให้ใช้สัญกรณ์ชวเลขสำหรับการประกาศ unsigned, short, หรือ longจำนวนเต็ม คุณสามารถใช้คำunsigned, short, หรือ long, ไม่มี int. มันบอกเป็นนัยโดยอัตโนมัติint. ตัวอย่างเช่นสองคำสั่งต่อไปนี้ทั้งสองประกาศตัวแปรจำนวนเต็มที่ไม่ได้ลงชื่อ
unsigned x;
unsigned int y;
เพื่อให้เข้าใจถึงความแตกต่างระหว่างวิธีที่ตัวแก้ไขจำนวนเต็มเซ็นและไม่ได้ลงชื่อถูกตีความโดย C ++ คุณควรเรียกใช้โปรแกรมสั้น ๆ ต่อไปนี้ -
#include <iostream>
using namespace std;
/* This program shows the difference between
* signed and unsigned integers.
*/
int main() {
short int i; // a signed short integer
short unsigned int j; // an unsigned short integer
j = 50000;
i = j;
cout << i << " " << j;
return 0;
}
เมื่อเรียกใช้โปรแกรมนี้ผลลัพธ์ต่อไปนี้คือ -
-15536 50000
ผลลัพธ์ข้างต้นเป็นเพราะรูปแบบบิตที่แสดง 50,000 เป็นจำนวนเต็มแบบสั้นที่ไม่ได้ลงชื่อถูกตีความเป็น -15,536 โดยย่อ
พิมพ์ Qualifiers ใน C ++
ตัวระบุประเภทจะให้ข้อมูลเพิ่มเติมเกี่ยวกับตัวแปรที่นำหน้า
ซีเนียร์ No | รอบคัดเลือกและความหมาย |
---|---|
1 | const วัตถุประเภท const โปรแกรมของคุณไม่สามารถเปลี่ยนแปลงได้ในระหว่างการดำเนินการ |
2 | volatile ตัวปรับแต่ง volatile บอกคอมไพเลอร์ว่าอาจมีการเปลี่ยนแปลงค่าของตัวแปรในรูปแบบที่โปรแกรมไม่ได้ระบุไว้อย่างชัดเจน |
3 | restrict ตัวชี้ที่ผ่านการรับรองโดย restrictในขั้นต้นเป็นวิธีเดียวที่วัตถุที่ชี้ให้สามารถเข้าถึงได้ เฉพาะ C99 เท่านั้นที่เพิ่มคุณสมบัติใหม่ที่เรียกว่าข้อ จำกัด |
คลาสหน่วยเก็บข้อมูลกำหนดขอบเขต (การมองเห็น) และอายุการใช้งานของตัวแปรและ / หรือฟังก์ชันภายในโปรแกรม C ++ ตัวระบุเหล่านี้นำหน้าประเภทที่แก้ไข มีคลาสพื้นที่เก็บข้อมูลต่อไปนี้ซึ่งสามารถใช้ในโปรแกรม C ++
- auto
- register
- static
- extern
- mutable
คลาสการจัดเก็บอัตโนมัติ
auto คลาสหน่วยเก็บเป็นคลาสหน่วยเก็บเริ่มต้นสำหรับตัวแปรโลคัลทั้งหมด
{
int mount;
auto int month;
}
ตัวอย่างข้างต้นกำหนดตัวแปรสองตัวที่มีคลาสการจัดเก็บเดียวกันโดยอัตโนมัติสามารถใช้ได้ภายในฟังก์ชันเท่านั้นเช่นตัวแปรโลคัล
ลงทะเบียนคลาสพื้นที่เก็บข้อมูล
registerคลาสการจัดเก็บใช้เพื่อกำหนดตัวแปรโลคัลที่ควรเก็บไว้ในรีจิสเตอร์แทนแรม ซึ่งหมายความว่าตัวแปรมีขนาดสูงสุดเท่ากับขนาดรีจิสเตอร์ (โดยปกติคือคำเดียว) และไม่สามารถใช้ตัวดำเนินการ unary '&' ได้ (เนื่องจากไม่มีตำแหน่งหน่วยความจำ)
{
register int miles;
}
ควรใช้รีจิสเตอร์สำหรับตัวแปรที่ต้องการการเข้าถึงอย่างรวดเร็วเช่นตัวนับ นอกจากนี้ควรสังเกตว่าการกำหนด 'register' ไม่ได้หมายความว่าตัวแปรจะถูกเก็บไว้ในรีจิสเตอร์ หมายความว่าอาจถูกเก็บไว้ในรีจิสเตอร์ขึ้นอยู่กับฮาร์ดแวร์และข้อ จำกัด ในการใช้งาน
คลาสการจัดเก็บแบบคงที่
staticคลาสหน่วยเก็บข้อมูลสั่งให้คอมไพลเลอร์เก็บตัวแปรโลคัลไว้ในช่วงอายุการใช้งานของโปรแกรมแทนที่จะสร้างและทำลายทุกครั้งที่เข้ามาและออกนอกขอบเขต ดังนั้นการทำให้ตัวแปรโลคัลเป็นแบบคงที่จะช่วยให้สามารถรักษาค่าระหว่างการเรียกใช้ฟังก์ชันได้
ตัวปรับแต่งแบบคงที่อาจนำไปใช้กับตัวแปรส่วนกลาง เมื่อดำเนินการเสร็จสิ้นจะทำให้ขอบเขตของตัวแปรนั้นถูก จำกัด ไว้ที่ไฟล์ที่มีการประกาศ
ใน C ++ เมื่อใช้สแตติกกับสมาชิกข้อมูลคลาสจะทำให้อ็อบเจ็กต์ทั้งหมดในคลาสแบ่งใช้สมาชิกได้เพียงสำเนาเดียว
#include <iostream>
// Function declaration
void func(void);
static int count = 10; /* Global variable */
main() {
while(count--) {
func();
}
return 0;
}
// Function definition
void func( void ) {
static int i = 5; // local static variable
i++;
std::cout << "i is " << i ;
std::cout << " and count is " << count << std::endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
i is 6 and count is 9
i is 7 and count is 8
i is 8 and count is 7
i is 9 and count is 6
i is 10 and count is 5
i is 11 and count is 4
i is 12 and count is 3
i is 13 and count is 2
i is 14 and count is 1
i is 15 and count is 0
คลาสพื้นที่เก็บข้อมูลภายนอก
externคลาสการจัดเก็บใช้เพื่ออ้างอิงถึงตัวแปรส่วนกลางที่ทุกไฟล์โปรแกรมสามารถมองเห็นได้ เมื่อคุณใช้ 'extern' ตัวแปรจะไม่สามารถเริ่มต้นได้เนื่องจากทั้งหมดที่ทำคือชี้ชื่อตัวแปรไปยังที่เก็บข้อมูลที่ได้กำหนดไว้ก่อนหน้านี้
เมื่อคุณมีไฟล์หลายไฟล์และคุณกำหนดตัวแปรหรือฟังก์ชันส่วนกลางซึ่งจะใช้ในไฟล์อื่นด้วยจากนั้นexternจะถูกใช้ในไฟล์อื่นเพื่ออ้างอิงตัวแปรหรือฟังก์ชันที่กำหนดไว้ เพื่อความเข้าใจexternใช้เพื่อประกาศตัวแปรส่วนกลางหรือฟังก์ชันในไฟล์อื่น
ตัวปรับแต่งภายนอกมักใช้เมื่อมีไฟล์สองไฟล์ขึ้นไปที่แชร์ตัวแปรส่วนกลางหรือฟังก์ชันเดียวกันตามที่อธิบายไว้ด้านล่าง
ไฟล์แรก: main.cpp
#include <iostream>
int count ;
extern void write_extern();
main() {
count = 5;
write_extern();
}
ไฟล์ที่สอง: support.cpp
#include <iostream>
extern int count;
void write_extern(void) {
std::cout << "Count is " << count << std::endl;
}
ที่นี่มีการใช้คีย์เวิร์ดภายนอกเพื่อประกาศจำนวนในไฟล์อื่น ตอนนี้รวบรวมสองไฟล์ดังต่อไปนี้ -
$g++ main.cpp support.cpp -o write
นี้จะผลิต write โปรแกรมปฏิบัติการลองรัน write และตรวจสอบผลลัพธ์ดังนี้ -
$./write
5
คลาสพื้นที่จัดเก็บที่ไม่แน่นอน
mutableตัวระบุใช้กับคลาสออบเจ็กต์เท่านั้นซึ่งจะกล่าวถึงต่อไปในบทช่วยสอนนี้ อนุญาตให้สมาชิกของอ็อบเจ็กต์แทนที่ฟังก์ชันสมาชิก const นั่นคือสมาชิกที่เปลี่ยนแปลงได้สามารถแก้ไขได้โดยฟังก์ชันสมาชิก const
ตัวดำเนินการคือสัญลักษณ์ที่บอกให้คอมไพเลอร์ดำเนินการจัดการทางคณิตศาสตร์หรือตรรกะเฉพาะ C ++ อุดมไปด้วยตัวดำเนินการในตัวและมีตัวดำเนินการประเภทต่อไปนี้ -
- ตัวดำเนินการเลขคณิต
- ตัวดำเนินการเชิงสัมพันธ์
- ตัวดำเนินการทางตรรกะ
- ตัวดำเนินการ Bitwise
- ผู้ดำเนินการมอบหมาย
- ตัวดำเนินการอื่น ๆ
บทนี้จะตรวจสอบเลขคณิตเชิงสัมพันธ์ตรรกะบิตการกำหนดและตัวดำเนินการอื่น ๆ ทีละรายการ
ตัวดำเนินการเลขคณิต
มีตัวดำเนินการทางคณิตศาสตร์ต่อไปนี้ที่รองรับโดยภาษา C ++ -
สมมติว่าตัวแปร A ถือ 10 และตัวแปร B ถือ 20 จากนั้น -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
+ | เพิ่มสองตัวถูกดำเนินการ | A + B จะให้ 30 |
- | ลบตัวถูกดำเนินการที่สองจากตัวแรก | A - B จะให้ -10 |
* | คูณตัวถูกดำเนินการทั้งสอง | A * B จะให้ 200 |
/ | หารเศษด้วยตัวเศษ | B / A จะให้ 2 |
% | ตัวดำเนินการโมดูลัสและส่วนที่เหลือหลังจากการหารจำนวนเต็ม | B% A จะให้ 0 |
++ | ตัวดำเนินการที่เพิ่มขึ้นเพิ่มค่าจำนวนเต็มทีละตัว | A ++ จะให้ 11 |
- | ตัวดำเนินการลดลงลดค่าจำนวนเต็มทีละหนึ่ง | A-- จะให้ 9 |
Relational Operators
There are following relational operators supported by C++ language
Assume variable A holds 10 and variable B holds 20, then −
Show Examples
Operator | Description | Example |
---|---|---|
== | Checks if the values of two operands are equal or not, if yes then condition becomes true. | (A == B) is not true. |
!= | Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. | (A != B) is true. |
> | Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. | (A > B) is not true. |
< | Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. | (A < B) is true. |
>= | Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. | (A >= B) is not true. |
<= | Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. | (A <= B) is true. |
Logical Operators
There are following logical operators supported by C++ language.
Assume variable A holds 1 and variable B holds 0, then −
Show Examples
Operator | Description | Example |
---|---|---|
&& | Called Logical AND operator. If both the operands are non-zero, then condition becomes true. | (A && B) is false. |
|| | Called Logical OR Operator. If any of the two operands is non-zero, then condition becomes true. | (A || B) is true. |
! | Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true, then Logical NOT operator will make false. | !(A && B) is true. |
Bitwise Operators
Bitwise operator works on bits and perform bit-by-bit operation. The truth tables for &, |, and ^ are as follows −
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Assume if A = 60; and B = 13; now in binary format they will be as follows −
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
The Bitwise operators supported by C++ language are listed in the following table. Assume variable A holds 60 and variable B holds 13, then −
Show Examples
Operator | Description | Example |
---|---|---|
& | Binary AND Operator copies a bit to the result if it exists in both operands. | (A & B) will give 12 which is 0000 1100 |
| | Binary OR Operator copies a bit if it exists in either operand. | (A | B) will give 61 which is 0011 1101 |
^ | Binary XOR Operator copies the bit if it is set in one operand but not both. | (A ^ B) will give 49 which is 0011 0001 |
~ | Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. | (~A ) will give -61 which is 1100 0011 in 2's complement form due to a signed binary number. |
<< | Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. | A << 2 will give 240 which is 1111 0000 |
>> | Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. | A >> 2 will give 15 which is 0000 1111 |
ผู้ดำเนินการมอบหมาย
มีตัวดำเนินการกำหนดดังต่อไปนี้ที่สนับสนุนโดยภาษา C ++ -
แสดงตัวอย่าง
ตัวดำเนินการ | คำอธิบาย | ตัวอย่าง |
---|---|---|
= | ตัวดำเนินการกำหนดง่ายกำหนดค่าจากตัวถูกดำเนินการด้านขวาไปยังตัวถูกดำเนินการด้านซ้าย | C = A + B จะกำหนดค่า A + B ให้เป็น C |
+ = | เพิ่มและกำหนดตัวดำเนินการเพิ่มตัวถูกดำเนินการด้านขวาไปยังตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C + = A เทียบเท่ากับ C = C + A |
- = | ตัวดำเนินการลบและกำหนดมันจะลบตัวถูกดำเนินการด้านขวาออกจากตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C - = A เทียบเท่ากับ C = C - A |
* = | ตัวดำเนินการคูณและการกำหนดมันจะคูณตัวถูกดำเนินการด้านขวากับตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C * = A เทียบเท่ากับ C = C * A |
/ = | ตัวดำเนินการหารและกำหนดมันแบ่งตัวถูกดำเนินการด้านซ้ายกับตัวถูกดำเนินการด้านขวาและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C / = A เทียบเท่ากับ C = C / A |
% = | โมดูลัสและตัวดำเนินการกำหนดมันใช้โมดูลัสโดยใช้ตัวถูกดำเนินการสองตัวและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย | C% = A เทียบเท่ากับ C = C% A |
<< = | กะซ้ายและตัวดำเนินการกำหนด | C << = 2 เหมือนกับ C = C << 2 |
>> = | กะขวาและตัวดำเนินการกำหนด | C >> = 2 เหมือนกับ C = C >> 2 |
& = | ตัวดำเนินการกำหนด Bitwise AND | C & = 2 เหมือนกับ C = C & 2 |
^ = | Bitwise เอกสิทธิ์เฉพาะหรือตัวดำเนินการกำหนด | C ^ = 2 เหมือนกับ C = C ^ 2 |
| = | Bitwise รวม OR และตัวดำเนินการกำหนด | C | = 2 เหมือนกับ C = C | 2 |
ตัวดำเนินการอื่น ๆ
ตารางต่อไปนี้แสดงตัวดำเนินการอื่น ๆ ที่ C ++ รองรับ
ซีเนียร์ No | ตัวดำเนินการและคำอธิบาย |
---|---|
1 | sizeof ตัวดำเนินการ sizeofส่งคืนขนาดของตัวแปร ตัวอย่างเช่น sizeof (a) โดยที่ 'a' เป็นจำนวนเต็มและจะส่งกลับ 4 |
2 | Condition ? X : Y ผู้ประกอบการที่มีเงื่อนไข (?) ถ้าเงื่อนไขเป็นจริงจะส่งคืนค่า X มิฉะนั้นจะส่งกลับค่า Y |
3 | , ตัวดำเนินการลูกน้ำทำให้ลำดับของการดำเนินการถูกดำเนินการ ค่าของนิพจน์ลูกน้ำทั้งหมดคือค่าของนิพจน์สุดท้ายของรายการที่คั่นด้วยเครื่องหมายจุลภาค |
4 | . (dot) and -> (arrow) ตัวดำเนินการสมาชิกใช้เพื่ออ้างอิงสมาชิกแต่ละคนของคลาสโครงสร้างและสหภาพแรงงาน |
5 | Cast ตัวดำเนินการแคสต์จะแปลงข้อมูลประเภทหนึ่งเป็นอีกประเภทหนึ่ง ตัวอย่างเช่น int (2.2000) จะคืนค่า 2 |
6 | & ตัวดำเนินการชี้และส่งกลับที่อยู่ของตัวแปร ตัวอย่างเช่น & a; จะให้ที่อยู่จริงของตัวแปร |
7 | * ตัวดำเนินการตัวชี้ *คือตัวชี้ไปยังตัวแปร ตัวอย่างเช่น * var; จะชี้ไปที่ตัวแปร var |
ลำดับความสำคัญของตัวดำเนินการใน C ++
ลำดับความสำคัญของตัวดำเนินการกำหนดการจัดกลุ่มคำศัพท์ในนิพจน์ สิ่งนี้มีผลต่อวิธีการประเมินนิพจน์ ตัวดำเนินการบางอย่างมีลำดับความสำคัญสูงกว่าผู้อื่น ตัวอย่างเช่นตัวดำเนินการคูณมีลำดับความสำคัญสูงกว่าตัวดำเนินการบวก -
ตัวอย่างเช่น x = 7 + 3 * 2; ที่นี่ x ถูกกำหนดให้เป็น 13 ไม่ใช่ 20 เนื่องจากตัวดำเนินการ * มีลำดับความสำคัญสูงกว่า + ดังนั้นจึงได้รับการคูณด้วย 3 * 2 ก่อนแล้วจึงเพิ่มเป็น 7
ที่นี่ตัวดำเนินการที่มีลำดับความสำคัญสูงสุดจะปรากฏที่ด้านบนสุดของตารางตัวดำเนินการที่มีค่าต่ำสุดจะปรากฏที่ด้านล่าง ภายในนิพจน์ตัวดำเนินการที่มีลำดับความสำคัญสูงกว่าจะได้รับการประเมินก่อน
แสดงตัวอย่าง
ประเภท | ตัวดำเนินการ | ความสัมพันธ์ |
---|---|---|
Postfix | () [] ->. ++ - - | จากซ้ายไปขวา |
ยูนารี | + -! ~ ++ - - (type) * & sizeof | จากขวาไปซ้าย |
หลายหลาก | * /% | จากซ้ายไปขวา |
สารเติมแต่ง | + - | จากซ้ายไปขวา |
กะ | << >> | จากซ้ายไปขวา |
เชิงสัมพันธ์ | <<=>> = | จากซ้ายไปขวา |
ความเท่าเทียมกัน | ==! = | จากซ้ายไปขวา |
Bitwise AND | & | จากซ้ายไปขวา |
Bitwise XOR | ^ | จากซ้ายไปขวา |
Bitwise หรือ | | | จากซ้ายไปขวา |
ตรรกะ AND | && | จากซ้ายไปขวา |
ตรรกะหรือ | || | จากซ้ายไปขวา |
เงื่อนไข | ?: | จากขวาไปซ้าย |
การมอบหมายงาน | = + = - = * = / =% = >> = << = & = ^ = | = | จากขวาไปซ้าย |
จุลภาค | , | จากซ้ายไปขวา |
อาจมีสถานการณ์เมื่อคุณต้องดำเนินการบล็อกรหัสหลาย ๆ ครั้ง โดยทั่วไปคำสั่งจะดำเนินการตามลำดับ: คำสั่งแรกในฟังก์ชันจะถูกเรียกใช้งานก่อนตามด้วยคำสั่งที่สองและอื่น ๆ
ภาษาโปรแกรมจัดเตรียมโครงสร้างการควบคุมต่างๆที่ช่วยให้เส้นทางการดำเนินการซับซ้อนมากขึ้น
คำสั่งวนซ้ำช่วยให้เราดำเนินการคำสั่งหรือกลุ่มของคำสั่งได้หลายครั้งและต่อไปนี้เป็นคำสั่งทั่วไปจากคำสั่งลูปในภาษาโปรแกรมส่วนใหญ่ -
ภาษาโปรแกรม C ++ จัดเตรียมลูปประเภทต่อไปนี้เพื่อจัดการกับข้อกำหนดการวนซ้ำ
ซีเนียร์ No | ประเภทห่วงและคำอธิบาย |
---|---|
1 | ในขณะที่วนซ้ำ ทำซ้ำคำสั่งหรือกลุ่มของคำสั่งในขณะที่เงื่อนไขที่กำหนดเป็นจริง จะทดสอบเงื่อนไขก่อนที่จะดำเนินการร่างกายลูป |
2 | สำหรับห่วง เรียกใช้ลำดับของคำสั่งหลาย ๆ ครั้งและย่อโค้ดที่จัดการตัวแปรลูป |
3 | ทำ ... ในขณะที่วนซ้ำ เช่นเดียวกับคำสั่ง 'while' ยกเว้นว่าจะทดสอบเงื่อนไขที่ส่วนท้ายของตัวห่วง |
4 | ลูปที่ซ้อนกัน คุณสามารถใช้ลูปหนึ่งหรือหลายวงในลูป 'while', 'for' หรือ 'do.. while' |
คำสั่งควบคุมลูป
คำสั่งควบคุมแบบวนซ้ำเปลี่ยนการดำเนินการจากลำดับปกติ เมื่อการดำเนินการออกจากขอบเขตอ็อบเจ็กต์อัตโนมัติทั้งหมดที่สร้างขึ้นในขอบเขตนั้นจะถูกทำลาย
C ++ สนับสนุนคำสั่งควบคุมต่อไปนี้
ซีเนียร์ No | คำชี้แจงและคำอธิบายการควบคุม |
---|---|
1 | คำสั่งทำลาย ยุติไฟล์ loop หรือ switch คำสั่งและโอนการดำเนินการไปยังคำสั่งทันทีตามลูปหรือสวิตช์ |
2 | ดำเนินการต่อ ทำให้ลูปข้ามส่วนที่เหลือของร่างกายและทดสอบสภาพของมันใหม่ทันทีก่อนที่จะย้ำอีกครั้ง |
3 | คำสั่ง goto การควบคุมการถ่ายโอนไปยังคำสั่งที่มีป้ายกำกับ แม้ว่าจะไม่แนะนำให้ใช้คำสั่ง goto ในโปรแกรมของคุณ |
ห่วงไม่มีที่สิ้นสุด
ลูปจะกลายเป็นลูปไม่มีที่สิ้นสุดหากเงื่อนไขไม่เคยเป็นเท็จ forloop ถูกใช้เพื่อจุดประสงค์นี้ เนื่องจากไม่จำเป็นต้องใช้นิพจน์สามนิพจน์ที่สร้างลูป 'for' คุณจึงสามารถสร้างการวนซ้ำแบบไม่มีที่สิ้นสุดได้โดยปล่อยให้นิพจน์เงื่อนไขว่างเปล่า
#include <iostream>
using namespace std;
int main () {
for( ; ; ) {
printf("This loop will run forever.\n");
}
return 0;
}
เมื่อไม่มีนิพจน์เงื่อนไขจะถือว่าเป็นจริง คุณอาจมีนิพจน์การเริ่มต้นและการเพิ่มขึ้น แต่โปรแกรมเมอร์ C ++ มักใช้โครงสร้าง 'for (;;)' เพื่อแสดงถึงการวนซ้ำที่ไม่มีที่สิ้นสุด
NOTE - คุณสามารถยุติการวนซ้ำที่ไม่มีที่สิ้นสุดได้โดยกดปุ่ม Ctrl + C
โครงสร้างการตัดสินใจกำหนดให้โปรแกรมเมอร์ระบุเงื่อนไขอย่างน้อยหนึ่งเงื่อนไขที่จะประเมินหรือทดสอบโดยโปรแกรมพร้อมกับคำสั่งหรือคำสั่งที่จะดำเนินการหากเงื่อนไขถูกกำหนดให้เป็นจริงและเป็นทางเลือกที่จะดำเนินการคำสั่งอื่น ๆ หากเงื่อนไข ถูกกำหนดให้เป็นเท็จ
ต่อไปนี้เป็นรูปแบบทั่วไปของโครงสร้างการตัดสินใจทั่วไปที่พบในภาษาโปรแกรมส่วนใหญ่ -
ภาษาโปรแกรม C ++ จัดเตรียมประเภทของคำสั่งประกอบการตัดสินใจดังต่อไปนี้
ซีเนียร์ No | คำชี้แจงและคำอธิบาย |
---|---|
1 | ถ้าคำสั่ง คำสั่ง 'if' ประกอบด้วยนิพจน์บูลีนตามด้วยหนึ่งคำสั่งหรือมากกว่า |
2 | if ... else คำสั่ง คำสั่ง 'if' สามารถตามด้วยคำสั่ง 'else' ซึ่งจะเรียกใช้เมื่อนิพจน์บูลีนเป็นเท็จ |
3 | สลับคำสั่ง คำสั่ง 'สวิตช์' ช่วยให้สามารถทดสอบตัวแปรเพื่อความเท่าเทียมกับรายการค่าได้ |
4 | คำสั่ง if ซ้อนกัน คุณสามารถใช้คำสั่ง 'if' หรือ 'else if' ในอีกคำสั่ง 'if' หรือ 'else if' |
5 | คำสั่งสวิตช์ที่ซ้อนกัน คุณสามารถใช้คำสั่ง 'สวิตช์' หนึ่งคำสั่งภายในคำสั่ง 'สวิตช์' อื่น |
เดอะ? : ผู้ปฏิบัติงาน
เราได้ครอบคลุมตัวดำเนินการตามเงื่อนไข“? :”ในบทก่อนหน้าซึ่งสามารถใช้เพื่อแทนที่if...elseงบ มีรูปแบบทั่วไปดังต่อไปนี้ -
Exp1 ? Exp2 : Exp3;
Exp1, Exp2 และ Exp3 เป็นนิพจน์ สังเกตการใช้และตำแหน่งของลำไส้ใหญ่
ค่าของ "?" นิพจน์ถูกกำหนดเช่นนี้: Exp1 ถูกประเมิน ถ้าเป็นจริง Exp2 จะถูกประเมินและกลายเป็นค่าของ "?" ทั้งหมด นิพจน์. ถ้า Exp1 เป็นเท็จระบบจะประเมิน Exp3 และค่าของมันจะกลายเป็นค่าของนิพจน์
ฟังก์ชันคือกลุ่มของคำสั่งที่ทำงานร่วมกัน ทุกโปรแกรม C ++ มีอย่างน้อยหนึ่งฟังก์ชันซึ่งก็คือmain()และโปรแกรมที่ไม่สำคัญทั้งหมดสามารถกำหนดฟังก์ชันเพิ่มเติมได้
คุณสามารถแบ่งรหัสของคุณออกเป็นฟังก์ชันแยกกันได้ การแบ่งรหัสของคุณระหว่างฟังก์ชันต่างๆนั้นขึ้นอยู่กับคุณ แต่ในทางตรรกะแล้วการแบ่งมักจะเป็นเช่นนั้นแต่ละฟังก์ชันจะทำงานเฉพาะ
ฟังก์ชั่น declarationบอกคอมไพเลอร์เกี่ยวกับชื่อของฟังก์ชันชนิดการส่งคืนและพารามิเตอร์ ฟังก์ชั่นdefinition ให้ตัวจริงของฟังก์ชั่น
ไลบรารีมาตรฐาน C ++ มีฟังก์ชันในตัวมากมายที่โปรแกรมของคุณสามารถเรียกใช้ได้ ตัวอย่างเช่นฟังก์ชันstrcat() เพื่อเชื่อมสองสตริงฟังก์ชัน memcpy() เพื่อคัดลอกตำแหน่งหน่วยความจำหนึ่งไปยังตำแหน่งอื่นและฟังก์ชันอื่น ๆ อีกมากมาย
ฟังก์ชั่นเป็นที่รู้จักด้วยชื่อต่างๆเช่นเมธอดหรือรูทีนย่อยหรือโพรซีเดอร์เป็นต้น
การกำหนดฟังก์ชัน
รูปแบบทั่วไปของนิยามฟังก์ชัน C ++ มีดังนี้ -
return_type function_name( parameter list ) {
body of the function
}
นิยามฟังก์ชัน C ++ ประกอบด้วยส่วนหัวของฟังก์ชันและเนื้อหาของฟังก์ชัน นี่คือส่วนทั้งหมดของฟังก์ชัน -
Return Type- ฟังก์ชันอาจส่งคืนค่า return_typeคือชนิดข้อมูลของค่าที่ฟังก์ชันส่งกลับ ฟังก์ชันบางอย่างดำเนินการตามที่ต้องการโดยไม่ส่งคืนค่า ในกรณีนี้ return_type คือคีย์เวิร์ดvoid.
Function Name- นี่คือชื่อจริงของฟังก์ชัน ชื่อฟังก์ชันและรายการพารามิเตอร์ประกอบกันเป็นลายเซ็นฟังก์ชัน
Parameters- พารามิเตอร์เปรียบเสมือนตัวยึด เมื่อเรียกใช้ฟังก์ชันคุณจะส่งค่าไปยังพารามิเตอร์ ค่านี้เรียกว่าพารามิเตอร์หรืออาร์กิวเมนต์จริง รายการพารามิเตอร์หมายถึงประเภทลำดับและจำนวนของพารามิเตอร์ของฟังก์ชัน พารามิเตอร์เป็นทางเลือก นั่นคือฟังก์ชันอาจไม่มีพารามิเตอร์
Function Body - เนื้อความของฟังก์ชันประกอบด้วยชุดของคำสั่งที่กำหนดสิ่งที่ฟังก์ชันทำ
ตัวอย่าง
ต่อไปนี้เป็นซอร์สโค้ดสำหรับฟังก์ชันที่เรียกว่า max(). ฟังก์ชันนี้รับสองพารามิเตอร์ num1 และ num2 และส่งกลับค่าที่ใหญ่ที่สุดของทั้งสอง -
// function returning the max between two numbers
int max(int num1, int num2) {
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
การประกาศฟังก์ชัน
ฟังก์ชั่น declarationบอกคอมไพเลอร์เกี่ยวกับชื่อฟังก์ชันและวิธีเรียกใช้ฟังก์ชัน สามารถกำหนดเนื้อหาที่แท้จริงของฟังก์ชันแยกกันได้
การประกาศฟังก์ชันมีส่วนต่างๆดังนี้ -
return_type function_name( parameter list );
สำหรับฟังก์ชันที่กำหนดไว้ข้างต้น max () ต่อไปนี้คือการประกาศฟังก์ชัน -
int max(int num1, int num2);
ชื่อพารามิเตอร์ไม่สำคัญในการประกาศฟังก์ชันจำเป็นต้องระบุประเภทเท่านั้นดังนั้นต่อไปนี้จึงเป็นการประกาศที่ถูกต้อง -
int max(int, int);
ต้องมีการประกาศฟังก์ชันเมื่อคุณกำหนดฟังก์ชันในไฟล์ต้นฉบับหนึ่งไฟล์และคุณเรียกใช้ฟังก์ชันนั้นในไฟล์อื่น ในกรณีนี้คุณควรประกาศฟังก์ชันที่ด้านบนของไฟล์ที่เรียกใช้ฟังก์ชัน
เรียกใช้ฟังก์ชัน
ในขณะที่สร้างฟังก์ชัน C ++ คุณให้คำจำกัดความว่าฟังก์ชันนี้มีไว้ทำอะไร ในการใช้ฟังก์ชันคุณจะต้องเรียกใช้หรือเรียกใช้ฟังก์ชันนั้น
เมื่อโปรแกรมเรียกใช้ฟังก์ชันการควบคุมโปรแกรมจะถูกโอนไปยังฟังก์ชันที่เรียก ฟังก์ชันที่เรียกว่าทำงานตามที่กำหนดไว้และเมื่อคำสั่ง return ถูกเรียกใช้งานหรือเมื่อถึงวงเล็บปีกกาปิดฟังก์ชันสิ้นสุดฟังก์ชันจะส่งคืนการควบคุมโปรแกรมกลับไปยังโปรแกรมหลัก
ในการเรียกใช้ฟังก์ชันคุณเพียงแค่ส่งพารามิเตอร์ที่ต้องการพร้อมกับชื่อฟังก์ชันและหากฟังก์ชันส่งคืนค่าคุณก็สามารถจัดเก็บค่าที่ส่งคืนได้ ตัวอย่างเช่น -
#include <iostream>
using namespace std;
// function declaration
int max(int num1, int num2);
int main () {
// local variable declaration:
int a = 100;
int b = 200;
int ret;
// calling a function to get max value.
ret = max(a, b);
cout << "Max value is : " << ret << endl;
return 0;
}
// function returning the max between two numbers
int max(int num1, int num2) {
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
ฉันเก็บฟังก์ชัน max () ไว้พร้อมกับฟังก์ชัน main () และรวบรวมซอร์สโค้ด ในขณะที่รันไฟล์ปฏิบัติการขั้นสุดท้ายจะให้ผลลัพธ์ดังนี้ -
Max value is : 200
อาร์กิวเมนต์ของฟังก์ชัน
ถ้าฟังก์ชันจะใช้อาร์กิวเมนต์ฟังก์ชันจะต้องประกาศตัวแปรที่ยอมรับค่าของอาร์กิวเมนต์ ตัวแปรเหล่านี้เรียกว่าformal parameters ของฟังก์ชัน
พารามิเตอร์ที่เป็นทางการทำงานเหมือนกับตัวแปรท้องถิ่นอื่น ๆ ภายในฟังก์ชันและถูกสร้างขึ้นเมื่อเข้าสู่ฟังก์ชันและถูกทำลายเมื่อออก
ในขณะเรียกใช้ฟังก์ชันมีสองวิธีที่สามารถส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชัน -
ซีเนียร์ No | ประเภทการโทรและคำอธิบาย |
---|---|
1 | โทรตามค่า วิธีนี้คัดลอกค่าที่แท้จริงของอาร์กิวเมนต์ลงในพารามิเตอร์ที่เป็นทางการของฟังก์ชัน ในกรณีนี้การเปลี่ยนแปลงที่เกิดขึ้นกับพารามิเตอร์ภายในฟังก์ชันจะไม่มีผลกับอาร์กิวเมนต์ |
2 | โทรตามตัวชี้ วิธีนี้คัดลอกที่อยู่ของอาร์กิวเมนต์ลงในพารามิเตอร์ที่เป็นทางการ ภายในฟังก์ชันนี้จะใช้แอดเดรสเพื่อเข้าถึงอาร์กิวเมนต์จริงที่ใช้ในการโทร ซึ่งหมายความว่าการเปลี่ยนแปลงที่เกิดขึ้นกับพารามิเตอร์มีผลต่ออาร์กิวเมนต์ |
3 | โทรตามข้อมูลอ้างอิง วิธีนี้คัดลอกการอ้างอิงของอาร์กิวเมนต์ลงในพารามิเตอร์ที่เป็นทางการ ภายในฟังก์ชันจะใช้การอ้างอิงเพื่อเข้าถึงอาร์กิวเมนต์จริงที่ใช้ในการโทร ซึ่งหมายความว่าการเปลี่ยนแปลงที่เกิดขึ้นกับพารามิเตอร์มีผลต่ออาร์กิวเมนต์ |
โดยค่าเริ่มต้น C ++ จะใช้ call by valueเพื่อส่งผ่านข้อโต้แย้ง โดยทั่วไปหมายความว่าโค้ดภายในฟังก์ชันไม่สามารถเปลี่ยนแปลงอาร์กิวเมนต์ที่ใช้เรียกฟังก์ชันและตัวอย่างที่กล่าวถึงข้างต้นในขณะที่เรียกฟังก์ชัน max () ก็ใช้วิธีการเดียวกัน
ค่าเริ่มต้นสำหรับพารามิเตอร์
เมื่อคุณกำหนดฟังก์ชันคุณสามารถระบุค่าเริ่มต้นสำหรับพารามิเตอร์สุดท้ายแต่ละตัวได้ ค่านี้จะถูกใช้หากอาร์กิวเมนต์ที่เกี่ยวข้องเว้นว่างไว้เมื่อเรียกใช้ฟังก์ชัน
ทำได้โดยใช้ตัวดำเนินการกำหนดและกำหนดค่าสำหรับอาร์กิวเมนต์ในนิยามฟังก์ชัน หากไม่ส่งค่าสำหรับพารามิเตอร์นั้นเมื่อฟังก์ชันถูกเรียกใช้ค่าที่กำหนดดีฟอลต์จะถูกใช้ แต่หากระบุค่าไว้ค่าดีฟอลต์นี้จะถูกละเว้นและใช้ค่าที่ผ่านแทน ลองพิจารณาตัวอย่างต่อไปนี้ -
#include <iostream>
using namespace std;
int sum(int a, int b = 20) {
int result;
result = a + b;
return (result);
}
int main () {
// local variable declaration:
int a = 100;
int b = 200;
int result;
// calling a function to add the values.
result = sum(a, b);
cout << "Total value is :" << result << endl;
// calling a function again as follows.
result = sum(a);
cout << "Total value is :" << result << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Total value is :300
Total value is :120
โดยปกติเมื่อเราทำงานกับ Numbers เราจะใช้ชนิดข้อมูลดั้งเดิมเช่น int, short, long, float และ double เป็นต้นประเภทข้อมูลตัวเลขค่าที่เป็นไปได้และช่วงตัวเลขได้รับการอธิบายในขณะที่พูดถึงประเภทข้อมูล C ++
การกำหนดตัวเลขใน C ++
คุณได้กำหนดตัวเลขไว้แล้วในตัวอย่างต่างๆที่ให้ไว้ในบทก่อนหน้านี้ นี่คืออีกตัวอย่างรวมเพื่อกำหนดประเภทต่างๆของตัวเลขใน C ++ -
#include <iostream>
using namespace std;
int main () {
// number definition:
short s;
int i;
long l;
float f;
double d;
// number assignments;
s = 10;
i = 1000;
l = 1000000;
f = 230.47;
d = 30949.374;
// number printing;
cout << "short s :" << s << endl;
cout << "int i :" << i << endl;
cout << "long l :" << l << endl;
cout << "float f :" << f << endl;
cout << "double d :" << d << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
short s :10
int i :1000
long l :1000000
float f :230.47
double d :30949.4
การดำเนินการทางคณิตศาสตร์ใน C ++
นอกจากฟังก์ชันต่างๆที่คุณสามารถสร้างได้แล้ว C ++ ยังมีฟังก์ชันที่มีประโยชน์บางอย่างที่คุณสามารถใช้ได้อีกด้วย ฟังก์ชันเหล่านี้มีอยู่ในไลบรารี C และ C ++ มาตรฐานและเรียกว่าbuilt-inฟังก์ชั่น. นี่คือฟังก์ชันที่สามารถรวมไว้ในโปรแกรมของคุณแล้วใช้งานได้
C ++ มีชุดการดำเนินการทางคณิตศาสตร์ที่หลากหลายซึ่งสามารถดำเนินการกับตัวเลขต่างๆ ตารางต่อไปนี้แสดงรายการฟังก์ชันทางคณิตศาสตร์ในตัวที่มีประโยชน์ซึ่งมีอยู่ใน C ++
ในการใช้ฟังก์ชันเหล่านี้คุณต้องรวมไฟล์ส่วนหัวทางคณิตศาสตร์ <cmath>.
ซีเนียร์ No | ฟังก์ชั่นและวัตถุประสงค์ |
---|---|
1 | double cos(double); ฟังก์ชันนี้ใช้มุม (เป็นคู่) และส่งกลับโคไซน์ |
2 | double sin(double); ฟังก์ชันนี้ใช้มุม (เป็นคู่) และส่งกลับไซน์ |
3 | double tan(double); ฟังก์ชันนี้รับมุม (เป็นคู่) และส่งกลับแทนเจนต์ |
4 | double log(double); ฟังก์ชันนี้รับจำนวนและส่งกลับบันทึกธรรมชาติของตัวเลขนั้น |
5 | double pow(double, double); ตัวแรกคือตัวเลขที่คุณต้องการเพิ่มและตัวที่สองคือพลังที่คุณต้องการเพิ่ม t |
6 | double hypot(double, double); ถ้าคุณส่งฟังก์ชันนี้ไปด้วยความยาวสองด้านของสามเหลี่ยมมุมฉากฟังก์ชันนี้จะส่งกลับค่าความยาวของด้านตรงข้ามมุมฉาก |
7 | double sqrt(double); คุณส่งผ่านฟังก์ชันนี้ไปจำนวนหนึ่งและให้ค่ารากที่สอง |
8 | int abs(int); ฟังก์ชันนี้จะส่งคืนค่าสัมบูรณ์ของจำนวนเต็มที่ส่งผ่านไป |
9 | double fabs(double); ฟังก์ชันนี้จะส่งคืนค่าสัมบูรณ์ของเลขฐานสิบใด ๆ ที่ส่งผ่านไป |
10 | double floor(double); ค้นหาจำนวนเต็มซึ่งน้อยกว่าหรือเท่ากับอาร์กิวเมนต์ที่ส่งผ่านไป |
ต่อไปนี้เป็นตัวอย่างง่ายๆเพื่อแสดงการดำเนินการทางคณิตศาสตร์บางส่วน -
#include <iostream>
#include <cmath>
using namespace std;
int main () {
// number definition:
short s = 10;
int i = -1000;
long l = 100000;
float f = 230.47;
double d = 200.374;
// mathematical operations;
cout << "sin(d) :" << sin(d) << endl;
cout << "abs(i) :" << abs(i) << endl;
cout << "floor(d) :" << floor(d) << endl;
cout << "sqrt(f) :" << sqrt(f) << endl;
cout << "pow( d, 2) :" << pow(d, 2) << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
sign(d) :-0.634939
abs(i) :1000
floor(d) :200
sqrt(f) :15.1812
pow( d, 2 ) :40149.7
ตัวเลขสุ่มใน C ++
มีหลายกรณีที่คุณต้องการสร้างหมายเลขสุ่ม มีสองฟังก์ชันที่คุณต้องรู้เกี่ยวกับการสร้างตัวเลขแบบสุ่ม ประการแรกคือrand()ฟังก์ชันนี้จะส่งคืนหมายเลขสุ่มหลอกเท่านั้น วิธีแก้ปัญหานี้คือโทรไปที่ไฟล์srand() ฟังก์ชัน
ต่อไปนี้เป็นตัวอย่างง่ายๆในการสร้างตัวเลขสุ่มสองสามตัว ตัวอย่างนี้ใช้ประโยชน์จากไฟล์time() ฟังก์ชั่นเพื่อรับจำนวนวินาทีในเวลาระบบของคุณเพื่อสุ่มเมล็ดฟังก์ชั่น Rand () -
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
int i,j;
// set the seed
srand( (unsigned)time( NULL ) );
/* generate 10 random numbers. */
for( i = 0; i < 10; i++ ) {
// generate actual random number
j = rand();
cout <<" Random Number : " << j << endl;
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Random Number : 1748144778
Random Number : 630873888
Random Number : 2134540646
Random Number : 219404170
Random Number : 902129458
Random Number : 920445370
Random Number : 1319072661
Random Number : 257938873
Random Number : 1256201101
Random Number : 580322989
C ++ มีโครงสร้างข้อมูล the arrayซึ่งเก็บคอลเลกชันตามลำดับขนาดคงที่ขององค์ประกอบประเภทเดียวกัน อาร์เรย์ใช้ในการจัดเก็บชุดข้อมูล แต่มักจะมีประโยชน์มากกว่าที่จะคิดว่าอาร์เรย์เป็นชุดของตัวแปรประเภทเดียวกัน
แทนที่จะประกาศตัวแปรเดี่ยวเช่น number0, number1, ... และ number99 คุณประกาศตัวแปรอาร์เรย์หนึ่งตัวเช่นตัวเลขและใช้ตัวเลข [0], ตัวเลข [1] และ ... , ตัวเลข [99] เพื่อแสดง ตัวแปรแต่ละตัว องค์ประกอบเฉพาะในอาร์เรย์ถูกเข้าถึงโดยดัชนี
อาร์เรย์ทั้งหมดประกอบด้วยตำแหน่งหน่วยความจำที่อยู่ติดกัน ที่อยู่ต่ำสุดสอดคล้องกับองค์ประกอบแรกและที่อยู่สูงสุดขององค์ประกอบสุดท้าย
การประกาศอาร์เรย์
ในการประกาศอาร์เรย์ใน C ++ โปรแกรมเมอร์ระบุประเภทขององค์ประกอบและจำนวนองค์ประกอบที่อาร์เรย์ต้องการดังนี้ -
type arrayName [ arraySize ];
สิ่งนี้เรียกว่าอาร์เรย์มิติเดียว arraySize ต้องเป็นค่าคงที่จำนวนเต็มมากกว่าศูนย์และ typeสามารถเป็นประเภทข้อมูล C ++ ที่ถูกต้องได้ ตัวอย่างเช่นในการประกาศอาร์เรย์ 10 องค์ประกอบที่เรียกว่า balance of type double ให้ใช้คำสั่งนี้ -
double balance[10];
การเริ่มต้นอาร์เรย์
คุณสามารถเริ่มต้นองค์ประกอบอาร์เรย์ C ++ ทีละรายการหรือใช้คำสั่งเดียวดังนี้ -
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
จำนวนค่าระหว่างวงเล็บปีกกา {} ต้องไม่เกินจำนวนองค์ประกอบที่เราประกาศสำหรับอาร์เรย์ระหว่างวงเล็บเหลี่ยม [] ต่อไปนี้เป็นตัวอย่างในการกำหนดองค์ประกอบเดียวของอาร์เรย์ -
หากคุณละเว้นขนาดของอาร์เรย์อาร์เรย์ที่ใหญ่พอที่จะรองรับการเริ่มต้นจะถูกสร้างขึ้น ดังนั้นถ้าคุณเขียน -
double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};
คุณจะสร้างอาร์เรย์เหมือนกับที่คุณทำในตัวอย่างก่อนหน้านี้
balance[4] = 50.0;
คำสั่งข้างต้นกำหนดองค์ประกอบหมายเลข 5 thในอาร์เรย์เป็นค่า 50.0 อาร์เรย์มี 4 THดัชนีจะเป็น 5 วันคือองค์ประกอบสุดท้ายเพราะอาร์เรย์ทั้งหมดมี 0 เป็นดัชนีขององค์ประกอบแรกของพวกเขาที่เรียกว่าดัชนียังฐาน ต่อไปนี้คือการแสดงภาพของอาร์เรย์เดียวกันที่เรากล่าวถึงข้างต้น -
การเข้าถึงองค์ประกอบอาร์เรย์
องค์ประกอบถูกเข้าถึงโดยการสร้างดัชนีชื่ออาร์เรย์ ทำได้โดยการวางดัชนีขององค์ประกอบไว้ในวงเล็บเหลี่ยมหลังชื่อของอาร์เรย์ ตัวอย่างเช่น -
double salary = balance[9];
ข้อความข้างต้นจะใช้เวลา 10 วันองค์ประกอบจากอาร์เรย์และกำหนดค่าให้กับตัวแปรเงินเดือน ต่อไปนี้เป็นตัวอย่างซึ่งจะใช้แนวคิดทั้งสามที่กล่าวถึงข้างต้น ได้แก่ การประกาศการมอบหมายและการเข้าถึงอาร์เรย์ -
#include <iostream>
using namespace std;
#include <iomanip>
using std::setw;
int main () {
int n[ 10 ]; // n is an array of 10 integers
// initialize elements of array n to 0
for ( int i = 0; i < 10; i++ ) {
n[ i ] = i + 100; // set element at location i to i + 100
}
cout << "Element" << setw( 13 ) << "Value" << endl;
// output each array element's value
for ( int j = 0; j < 10; j++ ) {
cout << setw( 7 )<< j << setw( 13 ) << n[ j ] << endl;
}
return 0;
}
โปรแกรมนี้ใช้ประโยชน์จากไฟล์ setw()เพื่อจัดรูปแบบผลลัพธ์ เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Element Value
0 100
1 101
2 102
3 103
4 104
5 105
6 106
7 107
8 108
9 109
อาร์เรย์ใน C ++
อาร์เรย์มีความสำคัญต่อ C ++ และควรมีรายละเอียดเพิ่มเติมมากมาย มีแนวคิดสำคัญบางประการดังต่อไปนี้ซึ่งควรชัดเจนสำหรับโปรแกรมเมอร์ C ++ -
ซีเนียร์ No | แนวคิดและคำอธิบาย |
---|---|
1 | อาร์เรย์หลายมิติ C ++ รองรับอาร์เรย์หลายมิติ รูปแบบที่ง่ายที่สุดของอาร์เรย์หลายมิติคืออาร์เรย์สองมิติ |
2 | ชี้ไปที่อาร์เรย์ คุณสามารถสร้างตัวชี้ไปยังองค์ประกอบแรกของอาร์เรย์ได้โดยระบุชื่ออาร์เรย์โดยไม่ต้องมีดัชนีใด ๆ |
3 | การส่งอาร์เรย์ไปยังฟังก์ชัน คุณสามารถส่งผ่านไปยังฟังก์ชันตัวชี้ไปยังอาร์เรย์ได้โดยระบุชื่ออาร์เรย์โดยไม่มีดัชนี |
4 | ส่งคืนอาร์เรย์จากฟังก์ชัน C ++ อนุญาตให้ฟังก์ชันส่งคืนอาร์เรย์ |
C ++ มีการแสดงสตริงสองประเภทดังต่อไปนี้ -
- สตริงอักขระสไตล์ C
- ประเภทคลาสสตริงที่แนะนำด้วย Standard C ++
สตริงอักขระสไตล์ C
สตริงอักขระสไตล์ C มาจากภาษา C และยังคงได้รับการสนับสนุนภายใน C ++ สตริงนี้เป็นอาร์เรย์หนึ่งมิติของอักขระซึ่งถูกยกเลิกโดย anullอักขระ '\ 0' ดังนั้นสตริงที่สิ้นสุดด้วย null จึงมีอักขระที่ประกอบด้วยสตริงตามด้วย anull.
การประกาศและการเริ่มต้นต่อไปนี้จะสร้างสตริงที่ประกอบด้วยคำว่า "สวัสดี" ในการเก็บอักขระ null ที่ท้ายอาร์เรย์ขนาดของอาร์เรย์อักขระที่มีสตริงจะมากกว่าจำนวนอักขระในคำว่า "Hello"
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
หากคุณปฏิบัติตามกฎของการเริ่มต้นอาร์เรย์คุณสามารถเขียนข้อความข้างต้นได้ดังนี้ -
char greeting[] = "Hello";
ต่อไปนี้เป็นการนำเสนอหน่วยความจำของสตริงที่กำหนดไว้ด้านบนใน C / C ++ -
จริงๆแล้วคุณไม่ได้วางอักขระ null ที่ส่วนท้ายของค่าคงที่ของสตริง คอมไพเลอร์ C ++ จะวาง '\ 0' ไว้ที่ท้ายสตริงโดยอัตโนมัติเมื่อเริ่มต้นอาร์เรย์ ให้เราลองพิมพ์สตริงที่กล่าวถึงข้างต้น -
#include <iostream>
using namespace std;
int main () {
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << "Greeting message: ";
cout << greeting << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Greeting message: Hello
C ++ รองรับฟังก์ชันหลากหลายที่จัดการกับสตริงที่สิ้นสุดด้วย null -
ซีเนียร์ No | ฟังก์ชั่นและวัตถุประสงค์ |
---|---|
1 | strcpy(s1, s2); คัดลอกสตริง s2 ลงในสตริง s1 |
2 | strcat(s1, s2); เชื่อมสตริง s2 เข้ากับส่วนท้ายของสตริง s1 |
3 | strlen(s1); ส่งกลับความยาวของสตริง s1 |
4 | strcmp(s1, s2); ส่งคืน 0 ถ้า s1 และ s2 เหมือนกัน น้อยกว่า 0 ถ้า s1 <s2; มากกว่า 0 ถ้า s1> s2 |
5 | strchr(s1, ch); ส่งกลับตัวชี้ไปยังอักขระ ch ที่เกิดขึ้นครั้งแรกในสตริง s1 |
6 | strstr(s1, s2); ส่งกลับตัวชี้ไปยังสตริง s2 ที่เกิดขึ้นครั้งแรกในสตริง s1 |
ตัวอย่างต่อไปนี้ใช้ประโยชน์จากฟังก์ชันที่กล่าวถึงข้างต้น -
#include <iostream>
#include <cstring>
using namespace std;
int main () {
char str1[10] = "Hello";
char str2[10] = "World";
char str3[10];
int len ;
// copy str1 into str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
// concatenates str1 and str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
// total lenghth of str1 after concatenation
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
strcpy( str3, str1) : Hello
strcat( str1, str2): HelloWorld
strlen(str1) : 10
คลาสสตริงใน C ++
ไลบรารี C ++ มาตรฐานจัดเตรียมไฟล์ stringประเภทคลาสที่รองรับการดำเนินการทั้งหมดที่กล่าวมาข้างต้นนอกจากนี้ยังมีฟังก์ชันอื่น ๆ อีกมากมาย ให้เราตรวจสอบตัวอย่างต่อไปนี้ -
#include <iostream>
#include <string>
using namespace std;
int main () {
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
// copy str1 into str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// concatenates str1 and str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// total length of str3 after concatenation
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
str3 : Hello
str1 + str2 : HelloWorld
str3.size() : 10
ตัวชี้ C ++ นั้นง่ายและสนุกในการเรียนรู้ งาน C ++ บางงานทำได้ง่ายกว่าด้วยพอยน์เตอร์และงาน C ++ อื่น ๆ เช่นการจัดสรรหน่วยความจำแบบไดนามิกจะไม่สามารถทำได้หากไม่มี
ดังที่คุณทราบทุกตัวแปรคือตำแหน่งหน่วยความจำและตำแหน่งหน่วยความจำทุกแห่งจะมีที่อยู่ที่กำหนดไว้ซึ่งสามารถเข้าถึงได้โดยใช้ตัวดำเนินการเครื่องหมายและ (&) ซึ่งหมายถึงที่อยู่ในหน่วยความจำ พิจารณาสิ่งต่อไปนี้ซึ่งจะพิมพ์ที่อยู่ของตัวแปรที่กำหนด -
#include <iostream>
using namespace std;
int main () {
int var1;
char var2[10];
cout << "Address of var1 variable: ";
cout << &var1 << endl;
cout << "Address of var2 variable: ";
cout << &var2 << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Address of var1 variable: 0xbfebd5c0
Address of var2 variable: 0xbfebd5b6
พอยน์เตอร์คืออะไร?
ก pointerเป็นตัวแปรที่มีค่าเป็นที่อยู่ของตัวแปรอื่น เช่นเดียวกับตัวแปรหรือค่าคงที่คุณต้องประกาศตัวชี้ก่อนจึงจะสามารถใช้งานได้ รูปแบบทั่วไปของการประกาศตัวแปรพอยน์เตอร์คือ -
type *var-name;
ที่นี่ typeเป็นประเภทฐานของตัวชี้ ต้องเป็นประเภท C ++ ที่ถูกต้องและvar-nameคือชื่อของตัวแปรพอยน์เตอร์ เครื่องหมายดอกจันที่คุณใช้เพื่อประกาศตัวชี้เป็นเครื่องหมายดอกจันเดียวกับที่คุณใช้ในการคูณ อย่างไรก็ตามในคำสั่งนี้จะใช้เครื่องหมายดอกจันเพื่อกำหนดตัวแปรเป็นตัวชี้ ต่อไปนี้เป็นการประกาศตัวชี้ที่ถูกต้อง -
int *ip; // pointer to an integer
double *dp; // pointer to a double
float *fp; // pointer to a float
char *ch // pointer to character
ชนิดข้อมูลจริงของค่าของพอยน์เตอร์ทั้งหมดไม่ว่าจะเป็นจำนวนเต็มจำนวนทศนิยมอักขระหรืออื่น ๆ จะเหมือนกันเป็นเลขฐานสิบหกแบบยาวที่แสดงแอดเดรสหน่วยความจำ ความแตกต่างเพียงอย่างเดียวระหว่างพอยน์เตอร์ของชนิดข้อมูลที่แตกต่างกันคือชนิดข้อมูลของตัวแปรหรือค่าคงที่ที่ตัวชี้ชี้ไป
การใช้พอยน์เตอร์ใน C ++
มีการดำเนินการที่สำคัญบางอย่างซึ่งเราจะดำเนินการกับพอยน์เตอร์บ่อยมาก (a) เรากำหนดตัวแปรตัวชี้ (b) กำหนดที่อยู่ของตัวแปรให้กับตัวชี้ (c)ในที่สุดก็เข้าถึงค่าตามที่อยู่ที่มีอยู่ในตัวแปรตัวชี้ สิ่งนี้ทำได้โดยใช้ตัวดำเนินการยูนารี * ที่ส่งคืนค่าของตัวแปรที่อยู่ตามที่อยู่ที่ระบุโดยตัวถูกดำเนินการ ตัวอย่างต่อไปนี้ใช้ประโยชน์จากการดำเนินการเหล่านี้ -
#include <iostream>
using namespace std;
int main () {
int var = 20; // actual variable declaration.
int *ip; // pointer variable
ip = &var; // store address of var in pointer variable
cout << "Value of var variable: ";
cout << var << endl;
// print the address stored in ip pointer variable
cout << "Address stored in ip variable: ";
cout << ip << endl;
// access the value at the address available in pointer
cout << "Value of *ip variable: ";
cout << *ip << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20
พอยน์เตอร์ใน C ++
พอยน์เตอร์มีแนวคิดมากมาย แต่ใช้งานง่ายและมีความสำคัญต่อการเขียนโปรแกรม C ++ มาก มีแนวคิดตัวชี้ที่สำคัญต่อไปนี้ซึ่งควรชัดเจนสำหรับโปรแกรมเมอร์ C ++ -
ซีเนียร์ No | แนวคิดและคำอธิบาย |
---|---|
1 | ตัวชี้ Null C ++ สนับสนุนตัวชี้โมฆะซึ่งเป็นค่าคงที่ที่มีค่าเป็นศูนย์ที่กำหนดไว้ในไลบรารีมาตรฐานหลายตัว |
2 | ตัวชี้เลขคณิต มีตัวดำเนินการทางคณิตศาสตร์สี่ตัวที่สามารถใช้กับพอยน์เตอร์ได้: ++, -, +, - |
3 | พอยน์เตอร์เทียบกับอาร์เรย์ มีความสัมพันธ์ใกล้ชิดระหว่างพอยน์เตอร์และอาร์เรย์ |
4 | อาร์เรย์ของพอยน์เตอร์ คุณสามารถกำหนดอาร์เรย์เพื่อเก็บพอยน์เตอร์ได้หลายตัว |
5 | ชี้ไปที่ตัวชี้ C ++ ช่วยให้คุณมีตัวชี้บนตัวชี้และอื่น ๆ |
6 | การส่งตัวชี้ไปยังฟังก์ชัน การส่งผ่านอาร์กิวเมนต์โดยการอ้างอิงหรือตามแอดเดรสทำให้อาร์กิวเมนต์ที่ส่งผ่านถูกเปลี่ยนในฟังก์ชันการโทรโดยฟังก์ชันที่เรียก |
7 | กลับตัวชี้จากฟังก์ชัน C ++ ช่วยให้ฟังก์ชันส่งกลับตัวชี้ไปยังตัวแปรโลคัลตัวแปรคงที่และหน่วยความจำที่จัดสรรแบบไดนามิกเช่นกัน |
ตัวแปรอ้างอิงคือนามแฝงนั่นคือชื่ออื่นสำหรับตัวแปรที่มีอยู่แล้ว เมื่อเริ่มต้นการอ้างอิงด้วยตัวแปรแล้วอาจใช้ชื่อตัวแปรหรือชื่ออ้างอิงเพื่ออ้างถึงตัวแปร
การอ้างอิงเทียบกับตัวชี้
การอ้างอิงมักสับสนกับตัวชี้ แต่ความแตกต่างที่สำคัญสามประการระหว่างการอ้างอิงและตัวชี้คือ -
คุณไม่สามารถมีการอ้างอิง NULL คุณต้องสามารถสันนิษฐานได้เสมอว่าข้อมูลอ้างอิงเชื่อมต่อกับส่วนจัดเก็บข้อมูลที่ถูกต้องตามกฎหมาย
เมื่อเริ่มต้นการอ้างอิงไปยังอ็อบเจ็กต์แล้วจะไม่สามารถเปลี่ยนเป็นการอ้างถึงอ็อบเจ็กต์อื่นได้ ตัวชี้สามารถชี้ไปที่วัตถุอื่นได้ตลอดเวลา
การอ้างอิงต้องเริ่มต้นเมื่อสร้างขึ้น พอยน์เตอร์สามารถเริ่มต้นได้ตลอดเวลา
การสร้างการอ้างอิงใน C ++
คิดว่าชื่อตัวแปรเป็นป้ายกำกับที่ติดกับตำแหน่งของตัวแปรในหน่วยความจำ จากนั้นคุณสามารถคิดว่าการอ้างอิงเป็นป้ายกำกับที่สองที่ติดอยู่กับตำแหน่งหน่วยความจำนั้น ดังนั้นคุณสามารถเข้าถึงเนื้อหาของตัวแปรผ่านชื่อตัวแปรดั้งเดิมหรือการอ้างอิง ตัวอย่างเช่นสมมติว่าเรามีตัวอย่างต่อไปนี้ -
int i = 17;
เราสามารถประกาศตัวแปรอ้างอิงสำหรับ i ได้ดังนี้
int& r = i;
อ่าน & ในประกาศเหล่านี้เป็น reference. ดังนั้นอ่านการประกาศครั้งแรกว่า "r คือการอ้างอิงจำนวนเต็มเริ่มต้นเป็น i" และอ่านการประกาศครั้งที่สองเป็น "s เป็นการอ้างอิงสองครั้งที่เริ่มต้นเป็น d" ตัวอย่างต่อไปนี้ใช้การอ้างอิงเกี่ยวกับ int และ double -
#include <iostream>
using namespace std;
int main () {
// declare simple variables
int i;
double d;
// declare reference variables
int& r = i;
double& s = d;
i = 5;
cout << "Value of i : " << i << endl;
cout << "Value of i reference : " << r << endl;
d = 11.7;
cout << "Value of d : " << d << endl;
cout << "Value of d reference : " << s << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์เข้าด้วยกันและเรียกใช้งานโค้ดจะได้ผลลัพธ์ดังนี้
Value of i : 5
Value of i reference : 5
Value of d : 11.7
Value of d reference : 11.7
การอ้างอิงมักจะใช้สำหรับรายการอาร์กิวเมนต์ของฟังก์ชันและค่าที่ส่งคืนของฟังก์ชัน ดังนั้นต่อไปนี้เป็นสองเรื่องสำคัญที่เกี่ยวข้องกับการอ้างอิง C ++ ซึ่งควรชัดเจนสำหรับโปรแกรมเมอร์ C ++ -
ซีเนียร์ No | แนวคิดและคำอธิบาย |
---|---|
1 | การอ้างอิงเป็นพารามิเตอร์ C ++ รองรับการส่งผ่านการอ้างอิงเป็นพารามิเตอร์ฟังก์ชันปลอดภัยกว่าพารามิเตอร์ |
2 | อ้างอิงเป็นค่าส่งคืน คุณสามารถส่งคืนการอ้างอิงจากฟังก์ชัน C ++ เหมือนกับข้อมูลประเภทอื่น ๆ |
ไลบรารีมาตรฐาน C ++ ไม่มีประเภทวันที่ที่เหมาะสม C ++ สืบทอดโครงสร้างและฟังก์ชันสำหรับการจัดการวันที่และเวลาจาก C ในการเข้าถึงฟังก์ชันและโครงสร้างที่เกี่ยวข้องกับวันที่และเวลาคุณจะต้องรวมไฟล์ส่วนหัว <ctime> ในโปรแกรม C ++ ของคุณ
มีสี่ประเภทที่เกี่ยวข้องกับเวลา: clock_t, time_t, size_tและ tm. ประเภท - clock_t, size_t และ time_t สามารถแสดงเวลาและวันที่ของระบบเป็นจำนวนเต็มบางประเภท
ประเภทโครงสร้าง tm ถือวันที่และเวลาในรูปแบบของโครงสร้าง C โดยมีองค์ประกอบดังต่อไปนี้ -
struct tm {
int tm_sec; // seconds of minutes from 0 to 61
int tm_min; // minutes of hour from 0 to 59
int tm_hour; // hours of day from 0 to 24
int tm_mday; // day of month from 1 to 31
int tm_mon; // month of year from 0 to 11
int tm_year; // year since 1900
int tm_wday; // days since sunday
int tm_yday; // days since January 1st
int tm_isdst; // hours of daylight savings time
}
ต่อไปนี้เป็นฟังก์ชั่นสำคัญที่เราใช้ขณะทำงานกับวันที่และเวลาใน C หรือ C ++ ฟังก์ชันทั้งหมดนี้เป็นส่วนหนึ่งของไลบรารี C และ C ++ มาตรฐานและคุณสามารถตรวจสอบรายละเอียดได้โดยใช้การอ้างอิงถึงไลบรารีมาตรฐาน C ++ ที่ระบุด้านล่าง
ซีเนียร์ No | ฟังก์ชั่นและวัตถุประสงค์ |
---|---|
1 | time_t time(time_t *time); สิ่งนี้จะส่งคืนเวลาปฏิทินปัจจุบันของระบบตามจำนวนวินาทีที่ผ่านไปนับตั้งแต่วันที่ 1 มกราคม 1970 ถ้าระบบไม่มีเวลาจะส่งคืน. 1 |
2 | char *ctime(const time_t *time); ผลตอบแทนนี้ตัวชี้ไปยังสตริงของรูปแบบชั่วโมงวันเดือนปี: นาที: วินาทีปี \ n \ 0 |
3 | struct tm *localtime(const time_t *time); สิ่งนี้จะส่งคืนตัวชี้ไปที่ tm โครงสร้างแทนเวลาท้องถิ่น |
4 | clock_t clock(void); ส่งคืนค่าที่ใกล้เคียงกับระยะเวลาที่โปรแกรมการโทรกำลังทำงานอยู่ ค่า. 1 จะถูกส่งกลับหากไม่มีเวลา |
5 | char * asctime ( const struct tm * time ); สิ่งนี้จะส่งกลับตัวชี้ไปยังสตริงที่มีข้อมูลที่จัดเก็บในโครงสร้างที่ชี้ตามเวลาที่แปลงเป็นรูปแบบ: วันเดือนวันที่ชั่วโมง: นาที: วินาทีปี \ n \ 0 |
6 | struct tm *gmtime(const time_t *time); สิ่งนี้ส่งกลับตัวชี้ไปที่เวลาในรูปแบบของโครงสร้าง tm เวลาจะแสดงเป็นเวลาสากลเชิงพิกัด (UTC) ซึ่งโดยพื้นฐานแล้วคือเวลามาตรฐานกรีนิช (GMT) |
7 | time_t mktime(struct tm *time); สิ่งนี้จะส่งคืนค่าเทียบเท่าเวลาตามปฏิทินของเวลาที่พบในโครงสร้างที่ชี้ตามเวลา |
8 | double difftime ( time_t time2, time_t time1 ); ฟังก์ชันนี้จะคำนวณความแตกต่างเป็นวินาทีระหว่าง time1 และ time2 |
9 | size_t strftime(); ฟังก์ชันนี้สามารถใช้เพื่อจัดรูปแบบวันที่และเวลาในรูปแบบเฉพาะ |
วันที่และเวลาปัจจุบัน
สมมติว่าคุณต้องการดึงข้อมูลวันที่และเวลาของระบบปัจจุบันไม่ว่าจะเป็นเวลาท้องถิ่นหรือเวลาสากลเชิงพิกัด (UTC) ต่อไปนี้เป็นตัวอย่างเพื่อให้บรรลุเดียวกัน -
#include <iostream>
#include <ctime>
using namespace std;
int main() {
// current date/time based on current system
time_t now = time(0);
// convert now to string form
char* dt = ctime(&now);
cout << "The local date and time is: " << dt << endl;
// convert now to tm struct for UTC
tm *gmtm = gmtime(&now);
dt = asctime(gmtm);
cout << "The UTC date and time is:"<< dt << endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
The local date and time is: Sat Jan 8 20:07:41 2011
The UTC date and time is:Sun Jan 9 03:07:41 2011
จัดรูปแบบเวลาโดยใช้ struct tm
tmโครงสร้างมีความสำคัญมากในขณะที่ทำงานกับวันที่และเวลาใน C หรือ C ++ โครงสร้างนี้ถือวันที่และเวลาในรูปแบบของโครงสร้าง C ตามที่กล่าวข้างต้น ฟังก์ชันที่เกี่ยวข้องกับเวลาส่วนใหญ่ใช้โครงสร้าง tm ต่อไปนี้เป็นตัวอย่างที่ใช้ประโยชน์จากฟังก์ชันต่างๆที่เกี่ยวข้องกับวันที่และเวลาและโครงสร้าง tm -
ในขณะที่ใช้โครงสร้างในบทนี้ฉันตั้งสมมติฐานว่าคุณมีความเข้าใจพื้นฐานเกี่ยวกับโครงสร้าง C และวิธีการเข้าถึงสมาชิกโครงสร้างโดยใช้ตัวดำเนินการ arrow ->
#include <iostream>
#include <ctime>
using namespace std;
int main() {
// current date/time based on current system
time_t now = time(0);
cout << "Number of sec since January 1,1970 is:: " << now << endl;
tm *ltm = localtime(&now);
// print various components of tm structure.
cout << "Year:" << 1900 + ltm->tm_year<<endl;
cout << "Month: "<< 1 + ltm->tm_mon<< endl;
cout << "Day: "<< ltm->tm_mday << endl;
cout << "Time: "<< 5+ltm->tm_hour << ":";
cout << 30+ltm->tm_min << ":";
cout << ltm->tm_sec << endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Number of sec since January 1,1970 is:: 1588485717
Year:2020
Month: 5
Day: 3
Time: 11:31:57
ไลบรารีมาตรฐาน C ++ มีชุดความสามารถอินพุต / เอาท์พุตมากมายซึ่งเราจะเห็นในบทต่อ ๆ ไป บทนี้จะกล่าวถึงการดำเนินการ I / O ขั้นพื้นฐานและทั่วไปที่จำเป็นสำหรับการเขียนโปรแกรม C ++
C ++ I / O เกิดขึ้นในสตรีมซึ่งเป็นลำดับของไบต์ หากไบต์ไหลจากอุปกรณ์เช่นแป้นพิมพ์ดิสก์ไดรฟ์หรือการเชื่อมต่อเครือข่าย ฯลฯ ไปยังหน่วยความจำหลักจะเรียกสิ่งนี้ว่าinput operation และถ้าไบต์ไหลจากหน่วยความจำหลักไปยังอุปกรณ์เช่นหน้าจอแสดงผลเครื่องพิมพ์ดิสก์ไดรฟ์หรือการเชื่อมต่อเครือข่ายเป็นต้นสิ่งนี้เรียกว่า output operation.
ไฟล์ส่วนหัวของไลบรารี I / O
มีไฟล์ส่วนหัวต่อไปนี้ที่สำคัญสำหรับโปรแกรม C ++ -
ซีเนียร์ No | ไฟล์ส่วนหัวและฟังก์ชันและคำอธิบาย |
---|---|
1 | <iostream> ไฟล์นี้กำหนดไฟล์ cin, cout, cerr และ clog อ็อบเจ็กต์ซึ่งสอดคล้องกับสตรีมอินพุตมาตรฐานสตรีมเอาต์พุตมาตรฐานสตรีมข้อผิดพลาดมาตรฐานที่ไม่บัฟเฟอร์และสตรีมข้อผิดพลาดมาตรฐานบัฟเฟอร์ตามลำดับ |
2 | <iomanip> ไฟล์นี้ประกาศบริการที่มีประโยชน์สำหรับการดำเนินการ I / O ที่จัดรูปแบบด้วยสิ่งที่เรียกว่าตัวปรับแต่งกระแสข้อมูลพารามิเตอร์เช่น setw และ setprecision. |
3 | <fstream> ไฟล์นี้ประกาศบริการสำหรับการประมวลผลไฟล์ที่ผู้ใช้ควบคุม เราจะพูดถึงรายละเอียดในบทที่เกี่ยวข้องกับไฟล์และสตรีม |
กระแสเอาต์พุตมาตรฐาน (cout)
วัตถุที่กำหนดไว้ล่วงหน้า cout เป็นตัวอย่างของ ostreamชั้นเรียน. วัตถุ cout ถูกกล่าวว่า "เชื่อมต่อกับ" อุปกรณ์เอาต์พุตมาตรฐานซึ่งโดยปกติจะเป็นหน้าจอแสดงผล cout ใช้ร่วมกับตัวดำเนินการแทรกสตรีมซึ่งเขียนว่า << ซึ่งเป็นเครื่องหมายน้อยกว่าสองตัวดังที่แสดงในตัวอย่างต่อไปนี้
#include <iostream>
using namespace std;
int main() {
char str[] = "Hello C++";
cout << "Value of str is : " << str << endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Value of str is : Hello C++
คอมไพเลอร์ C ++ ยังกำหนดชนิดข้อมูลของตัวแปรที่จะส่งออกและเลือกตัวดำเนินการแทรกสตรีมที่เหมาะสมเพื่อแสดงค่า << โอเปอเรเตอร์ถูกโอเวอร์โหลดเพื่อเอาต์พุตไอเท็มข้อมูลประเภทบิวท์อินจำนวนเต็มลอยคู่สตริงและค่าตัวชี้
ตัวดำเนินการแทรก << อาจใช้มากกว่าหนึ่งครั้งในคำสั่งเดียวดังที่แสดงไว้ด้านบนและ endl ใช้เพื่อเพิ่มบรรทัดใหม่ที่ท้ายบรรทัด
สตรีมอินพุตมาตรฐาน (cin)
วัตถุที่กำหนดไว้ล่วงหน้า cin เป็นตัวอย่างของ istreamชั้นเรียน. กล่าวกันว่าวัตถุ cin ถูกต่อเข้ากับอุปกรณ์อินพุตมาตรฐานซึ่งโดยปกติจะเป็นแป้นพิมพ์ cin ใช้ร่วมกับตัวดำเนินการแยกสตรีมซึ่งเขียนเป็น >> ซึ่งมีค่ามากกว่าสองสัญญาณดังที่แสดงในตัวอย่างต่อไปนี้
#include <iostream>
using namespace std;
int main() {
char name[50];
cout << "Please enter your name: ";
cin >> name;
cout << "Your name is: " << name << endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานโค้ดจะแจ้งให้คุณป้อนชื่อ คุณป้อนค่าจากนั้นกด Enter เพื่อดูผลลัพธ์ต่อไปนี้ -
Please enter your name: cplusplus
Your name is: cplusplus
คอมไพลเลอร์ C ++ ยังกำหนดชนิดข้อมูลของค่าที่ป้อนและเลือกตัวดำเนินการแยกสตรีมที่เหมาะสมเพื่อแยกค่าและเก็บไว้ในตัวแปรที่กำหนด
ตัวดำเนินการแยกสตรีม >> อาจถูกใช้มากกว่าหนึ่งครั้งในคำสั่งเดียว หากต้องการขอข้อมูลมากกว่าหนึ่งรายการคุณสามารถใช้สิ่งต่อไปนี้ -
cin >> name >> age;
สิ่งนี้จะเทียบเท่ากับสองข้อความต่อไปนี้ -
cin >> name;
cin >> age;
สตรีมข้อผิดพลาดมาตรฐาน (cerr)
วัตถุที่กำหนดไว้ล่วงหน้า cerr เป็นตัวอย่างของ ostreamชั้นเรียน. มีการกล่าวถึงวัตถุ cerr กับอุปกรณ์ข้อผิดพลาดมาตรฐานซึ่งเป็นหน้าจอแสดงผลเช่นกัน แต่เป็นวัตถุcerr ไม่ถูกบัฟเฟอร์และการแทรกสตรีมแต่ละครั้งไปยัง cerr ทำให้เอาต์พุตปรากฏทันที
cerr ยังใช้ร่วมกับตัวดำเนินการแทรกสตรีมดังที่แสดงในตัวอย่างต่อไปนี้
#include <iostream>
using namespace std;
int main() {
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Error message : Unable to read....
สตรีมบันทึกมาตรฐาน (การอุดตัน)
วัตถุที่กำหนดไว้ล่วงหน้า clog เป็นตัวอย่างของ ostreamชั้นเรียน. มีการกล่าวถึงวัตถุอุดตันที่ติดอยู่กับอุปกรณ์ข้อผิดพลาดมาตรฐานซึ่งเป็นหน้าจอแสดงผลเช่นกัน แต่เป็นวัตถุclogถูกบัฟเฟอร์ ซึ่งหมายความว่าการแทรกแต่ละครั้งเพื่ออุดตันอาจทำให้เอาต์พุตถูกเก็บไว้ในบัฟเฟอร์จนกว่าบัฟเฟอร์จะเต็มหรือจนกว่าบัฟเฟอร์จะถูกล้าง
clog ยังใช้ร่วมกับตัวดำเนินการแทรกสตรีมดังที่แสดงในตัวอย่างต่อไปนี้
#include <iostream>
using namespace std;
int main() {
char str[] = "Unable to read....";
clog << "Error message : " << str << endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Error message : Unable to read....
คุณจะไม่สามารถเห็นความแตกต่างใด ๆ ใน cout, cerr และอุดตันด้วยตัวอย่างเล็ก ๆ เหล่านี้ แต่ในขณะที่เขียนและดำเนินการโปรแกรมใหญ่ ๆ ความแตกต่างจะชัดเจน ดังนั้นจึงเป็นแนวทางปฏิบัติที่ดีในการแสดงข้อความแสดงข้อผิดพลาดโดยใช้ cerr stream และในขณะที่แสดงข้อความบันทึกอื่น ๆ ควรใช้การอุดตัน
อาร์เรย์ C / C ++ ช่วยให้คุณสามารถกำหนดตัวแปรที่รวมรายการข้อมูลหลายรายการในประเภทเดียวกัน แต่ structure เป็นประเภทข้อมูลอื่นที่ผู้ใช้กำหนดซึ่งช่วยให้คุณสามารถรวมรายการข้อมูลประเภทต่างๆ
โครงสร้างใช้เพื่อแสดงบันทึกสมมติว่าคุณต้องการติดตามหนังสือของคุณในห้องสมุด คุณอาจต้องการติดตามคุณลักษณะต่อไปนี้เกี่ยวกับหนังสือแต่ละเล่ม -
- Title
- Author
- Subject
- รหัสหนังสือ
การกำหนดโครงสร้าง
ในการกำหนดโครงสร้างคุณต้องใช้คำสั่ง struct คำสั่ง struct กำหนดชนิดข้อมูลใหม่โดยมีสมาชิกมากกว่าหนึ่งคนสำหรับโปรแกรมของคุณ รูปแบบของคำสั่ง struct คือ -
struct [structure tag] {
member definition;
member definition;
...
member definition;
} [one or more structure variables];
structure tagเป็นทางเลือกและนิยามสมาชิกแต่ละตัวเป็นนิยามตัวแปรปกติเช่น int i; หรือลอยฉ; หรือนิยามตัวแปรอื่น ๆ ที่ถูกต้อง ในตอนท้ายของนิยามของโครงสร้างก่อนอัฒภาคสุดท้ายคุณสามารถระบุตัวแปรโครงสร้างอย่างน้อยหนึ่งตัวแปร แต่เป็นทางเลือก นี่คือวิธีที่คุณจะประกาศโครงสร้างหนังสือ -
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
การเข้าถึงสมาชิกโครงสร้าง
ในการเข้าถึงสมาชิกของโครงสร้างใด ๆ เราใช้ไฟล์ member access operator (.). ตัวดำเนินการเข้าถึงสมาชิกถูกเข้ารหัสเป็นช่วงเวลาระหว่างชื่อตัวแปรโครงสร้างและสมาชิกโครงสร้างที่เราต้องการเข้าถึง คุณจะใช้structคำหลักในการกำหนดตัวแปรประเภทโครงสร้าง ต่อไปนี้เป็นตัวอย่างเพื่ออธิบายการใช้โครงสร้าง -
#include <iostream>
#include <cstring>
using namespace std;
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main() {
struct Books Book1; // Declare Book1 of type Book
struct Books Book2; // Declare Book2 of type Book
// book 1 specification
strcpy( Book1.title, "Learn C++ Programming");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Programming");
Book1.book_id = 6495407;
// book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom");
Book2.book_id = 6495700;
// Print Book1 info
cout << "Book 1 title : " << Book1.title <<endl;
cout << "Book 1 author : " << Book1.author <<endl;
cout << "Book 1 subject : " << Book1.subject <<endl;
cout << "Book 1 id : " << Book1.book_id <<endl;
// Print Book2 info
cout << "Book 2 title : " << Book2.title <<endl;
cout << "Book 2 author : " << Book2.author <<endl;
cout << "Book 2 subject : " << Book2.subject <<endl;
cout << "Book 2 id : " << Book2.book_id <<endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Book 1 title : Learn C++ Programming
Book 1 author : Chand Miyan
Book 1 subject : C++ Programming
Book 1 id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Yakit Singha
Book 2 subject : Telecom
Book 2 id : 6495700
โครงสร้างเป็นอาร์กิวเมนต์ของฟังก์ชัน
คุณสามารถส่งผ่านโครงสร้างเป็นอาร์กิวเมนต์ของฟังก์ชันในลักษณะที่คล้ายกันมากเมื่อคุณส่งผ่านตัวแปรหรือตัวชี้อื่น ๆ คุณจะเข้าถึงตัวแปรโครงสร้างในลักษณะเดียวกับที่คุณเข้าถึงในตัวอย่างข้างต้น -
#include <iostream>
#include <cstring>
using namespace std;
void printBook( struct Books book );
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main() {
struct Books Book1; // Declare Book1 of type Book
struct Books Book2; // Declare Book2 of type Book
// book 1 specification
strcpy( Book1.title, "Learn C++ Programming");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Programming");
Book1.book_id = 6495407;
// book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom");
Book2.book_id = 6495700;
// Print Book1 info
printBook( Book1 );
// Print Book2 info
printBook( Book2 );
return 0;
}
void printBook( struct Books book ) {
cout << "Book title : " << book.title <<endl;
cout << "Book author : " << book.author <<endl;
cout << "Book subject : " << book.subject <<endl;
cout << "Book id : " << book.book_id <<endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700
ตัวชี้ไปที่โครงสร้าง
คุณสามารถกำหนดตัวชี้ไปยังโครงสร้างในลักษณะที่คล้ายกันมากเมื่อคุณกำหนดตัวชี้ไปยังตัวแปรอื่น ๆ ดังนี้ -
struct Books *struct_pointer;
ตอนนี้คุณสามารถจัดเก็บที่อยู่ของตัวแปรโครงสร้างในตัวแปรตัวชี้ที่กำหนดไว้ข้างต้น ในการค้นหาที่อยู่ของตัวแปรโครงสร้างให้วางเครื่องหมาย & ไว้หน้าชื่อโครงสร้างดังนี้ -
struct_pointer = &Book1;
ในการเข้าถึงสมาชิกของโครงสร้างโดยใช้ตัวชี้ไปยังโครงสร้างนั้นคุณต้องใช้ตัวดำเนินการ -> ดังต่อไปนี้ -
struct_pointer->title;
ให้เราเขียนตัวอย่างด้านบนอีกครั้งโดยใช้ตัวชี้โครงสร้างหวังว่านี่จะเป็นเรื่องง่ายสำหรับคุณที่จะเข้าใจแนวคิด -
#include <iostream>
#include <cstring>
using namespace std;
void printBook( struct Books *book );
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main() {
struct Books Book1; // Declare Book1 of type Book
struct Books Book2; // Declare Book2 of type Book
// Book 1 specification
strcpy( Book1.title, "Learn C++ Programming");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Programming");
Book1.book_id = 6495407;
// Book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom");
Book2.book_id = 6495700;
// Print Book1 info, passing address of structure
printBook( &Book1 );
// Print Book1 info, passing address of structure
printBook( &Book2 );
return 0;
}
// This function accept pointer to structure as parameter.
void printBook( struct Books *book ) {
cout << "Book title : " << book->title <<endl;
cout << "Book author : " << book->author <<endl;
cout << "Book subject : " << book->subject <<endl;
cout << "Book id : " << book->book_id <<endl;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700
คีย์เวิร์ด typedef
มีวิธีที่ง่ายกว่าในการกำหนดโครงสร้างหรือคุณสามารถสร้างประเภท "นามแฝง" ที่คุณสร้างขึ้น ตัวอย่างเช่น -
typedef struct {
char title[50];
char author[50];
char subject[100];
int book_id;
} Books;
ตอนนี้คุณสามารถใช้หนังสือโดยตรงเพื่อกำหนดตัวแปรประเภทหนังสือโดยไม่ต้องใช้คำหลักโครงสร้าง ต่อไปนี้เป็นตัวอย่าง -
Books Book1, Book2;
คุณสามารถใช้ได้ typedef คีย์เวิร์ดสำหรับ non-structs ดังต่อไปนี้ -
typedef long int *pint32;
pint32 x, y, z;
x, y และ z ล้วนเป็นตัวชี้ไปยัง ints แบบยาว
วัตถุประสงค์หลักของการเขียนโปรแกรม C ++ คือการเพิ่มการวางแนววัตถุให้กับภาษาการเขียนโปรแกรม C และคลาสเป็นคุณสมบัติหลักของ C ++ ที่รองรับการเขียนโปรแกรมเชิงวัตถุและมักเรียกว่าชนิดที่ผู้ใช้กำหนดเอง
คลาสถูกใช้เพื่อระบุรูปแบบของอ็อบเจ็กต์และรวมการแทนข้อมูลและวิธีการจัดการข้อมูลนั้นเป็นแพ็กเกจเดียว ข้อมูลและฟังก์ชันภายในคลาสเรียกว่าสมาชิกของคลาส
นิยามคลาส C ++
เมื่อคุณกำหนดคลาสคุณจะกำหนดพิมพ์เขียวสำหรับชนิดข้อมูล สิ่งนี้ไม่ได้กำหนดข้อมูลใด ๆ แต่เป็นการกำหนดความหมายของชื่อคลาสนั่นคือสิ่งที่วัตถุของคลาสจะประกอบด้วยและสิ่งที่สามารถดำเนินการกับวัตถุดังกล่าวได้
นิยามคลาสเริ่มต้นด้วยคีย์เวิร์ด classตามด้วยชื่อชั้น; และตัวคลาสล้อมรอบด้วยวงเล็บปีกกาคู่หนึ่ง คำจำกัดความของคลาสจะต้องตามด้วยอัฒภาคหรือรายการของการประกาศ ตัวอย่างเช่นเรากำหนดประเภทข้อมูล Box โดยใช้คำสำคัญclass ดังต่อไปนี้ -
class Box {
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
คำหลัก publicกำหนดแอ็ตทริบิวต์การเข้าถึงของสมาชิกของคลาสที่ตามหลังมัน สมาชิกสาธารณะสามารถเข้าถึงได้จากภายนอกชั้นเรียนที่ใดก็ได้ภายในขอบเขตของวัตถุคลาส คุณยังสามารถระบุสมาชิกของชั้นเรียนเป็นprivate หรือ protected ซึ่งเราจะพูดถึงในส่วนย่อย
กำหนดวัตถุ C ++
คลาสจัดเตรียมพิมพ์เขียวสำหรับอ็อบเจ็กต์ดังนั้นโดยพื้นฐานแล้วอ็อบเจ็กต์จะถูกสร้างขึ้นจากคลาส เราประกาศออบเจ็กต์ของคลาสด้วยการประกาศประเภทเดียวกันกับที่เราประกาศตัวแปรประเภทพื้นฐาน คำสั่งต่อไปนี้ประกาศสองวัตถุของคลาส Box -
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
ทั้งสองอ็อบเจ็กต์ Box1 และ Box2 จะมีสำเนาข้อมูลของตัวเอง
การเข้าถึงสมาชิกข้อมูล
สมาชิกข้อมูลสาธารณะของออบเจ็กต์ของคลาสสามารถเข้าถึงได้โดยใช้ตัวดำเนินการเข้าถึงสมาชิกโดยตรง (.) ให้เราลองใช้ตัวอย่างต่อไปนี้เพื่อทำให้สิ่งต่างๆชัดเจน -
#include <iostream>
using namespace std;
class Box {
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
int main() {
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 specification
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// volume of box 1
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Volume of Box2 : " << volume <<endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Volume of Box1 : 210
Volume of Box2 : 1560
สิ่งสำคัญคือต้องทราบว่าสมาชิกส่วนตัวและที่ได้รับการป้องกันไม่สามารถเข้าถึงได้โดยตรงโดยใช้ตัวดำเนินการเข้าถึงสมาชิกโดยตรง (.) เราจะเรียนรู้ว่าสมาชิกส่วนตัวและได้รับการป้องกันสามารถเข้าถึงได้อย่างไร
คลาสและออบเจ็กต์โดยละเอียด
จนถึงตอนนี้คุณมีแนวคิดพื้นฐานเกี่ยวกับคลาส C ++ และวัตถุ มีแนวคิดที่น่าสนใจเพิ่มเติมเกี่ยวกับคลาส C ++ และออบเจ็กต์ซึ่งเราจะพูดถึงในส่วนย่อยต่างๆที่แสดงด้านล่าง -
ซีเนียร์ No | แนวคิดและคำอธิบาย |
---|---|
1 | ฟังก์ชันสมาชิกในชั้นเรียน ฟังก์ชันสมาชิกของคลาสคือฟังก์ชันที่มีนิยามหรือต้นแบบภายในนิยามคลาสเหมือนกับตัวแปรอื่น ๆ |
2 | ตัวปรับการเข้าถึงคลาส สมาชิกชั้นเรียนสามารถกำหนดเป็นสาธารณะส่วนตัวหรือได้รับการคุ้มครอง โดยค่าเริ่มต้นสมาชิกจะถือว่าเป็นส่วนตัว |
3 | ตัวสร้างและตัวทำลาย ตัวสร้างคลาสคือฟังก์ชันพิเศษในคลาสที่ถูกเรียกใช้เมื่อสร้างอ็อบเจ็กต์ใหม่ของคลาส ตัวทำลายยังเป็นฟังก์ชันพิเศษซึ่งถูกเรียกใช้เมื่ออ็อบเจ็กต์ที่สร้างขึ้นถูกลบ |
4 | คัดลอกตัวสร้าง ตัวสร้างการคัดลอกคือตัวสร้างที่สร้างอ็อบเจ็กต์โดยการกำหนดค่าเริ่มต้นด้วยอ็อบเจ็กต์ในคลาสเดียวกันซึ่งถูกสร้างขึ้นก่อนหน้านี้ |
5 | ฟังก์ชั่นเพื่อน ก friend ฟังก์ชันได้รับอนุญาตให้เข้าถึงสมาชิกส่วนตัวและได้รับการป้องกันของคลาส |
6 | ฟังก์ชันแบบอินไลน์ ด้วยฟังก์ชันอินไลน์คอมไพลเลอร์จะพยายามขยายโค้ดในเนื้อความของฟังก์ชันแทนการเรียกใช้ฟังก์ชัน |
7 | Pointer นี้ ทุกวัตถุมีตัวชี้พิเศษ this ซึ่งชี้ไปที่วัตถุนั้นเอง |
8 | ชี้ไปที่คลาส C ++ ตัวชี้ไปยังชั้นเรียนจะทำในลักษณะเดียวกับที่ตัวชี้ไปยังโครงสร้าง ในความเป็นจริงคลาสเป็นเพียงโครงสร้างที่มีฟังก์ชันอยู่ในนั้น |
9 | สมาชิกคงที่ของชั้นเรียน ทั้งสมาชิกข้อมูลและสมาชิกฟังก์ชันของคลาสสามารถประกาศเป็นแบบคงที่ได้ |
แนวคิดที่สำคัญที่สุดอย่างหนึ่งในการเขียนโปรแกรมเชิงวัตถุคือการถ่ายทอดทางพันธุกรรม การสืบทอดช่วยให้เรากำหนดคลาสในรูปแบบของคลาสอื่นซึ่งทำให้ง่ายต่อการสร้างและดูแลแอปพลิเคชัน นอกจากนี้ยังให้โอกาสในการนำฟังก์ชันโค้ดกลับมาใช้ซ้ำและใช้งานได้รวดเร็ว
เมื่อสร้างคลาสแทนที่จะเขียนสมาชิกข้อมูลและฟังก์ชันสมาชิกใหม่ทั้งหมดโปรแกรมเมอร์สามารถกำหนดได้ว่าคลาสใหม่ควรสืบทอดสมาชิกของคลาสที่มีอยู่ คลาสที่มีอยู่นี้เรียกว่าbase คลาสและคลาสใหม่เรียกว่า derived ชั้นเรียน.
แนวคิดเรื่องการถ่ายทอดทางพันธุกรรมใช้ is aความสัมพันธ์. ตัวอย่างเช่นสัตว์เลี้ยงลูกด้วยนม IS-A สุนัข IS-A เลี้ยงลูกด้วยนมดังนั้นสุนัข IS-A เช่นกันและอื่น ๆ
ฐานและคลาสที่ได้รับ
คลาสสามารถได้มาจากมากกว่าหนึ่งคลาสซึ่งหมายความว่าสามารถสืบทอดข้อมูลและฟังก์ชันจากคลาสพื้นฐานได้หลายคลาส ในการกำหนดคลาสที่ได้รับเราใช้รายการที่มาของคลาสเพื่อระบุคลาสฐาน (es) รายการที่มาของคลาสจะตั้งชื่อคลาสพื้นฐานตั้งแต่หนึ่งคลาสขึ้นไปและมีรูปแบบ -
class derived-class: access-specifier base-class
โดยที่ตัวระบุการเข้าถึงเป็นหนึ่งใน public, protected, หรือ privateและ base-class คือชื่อของคลาสที่กำหนดไว้ก่อนหน้านี้ หากไม่ได้ใช้ตัวระบุการเข้าถึงแสดงว่าเป็นส่วนตัวโดยค่าเริ่มต้น
พิจารณาคลาสพื้นฐาน Shape และคลาสที่ได้รับมา Rectangle ดังต่อไปนี้ -
#include <iostream>
using namespace std;
// Base class
class Shape {
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Total area: 35
การควบคุมการเข้าถึงและการสืบทอด
คลาสที่ได้รับสามารถเข้าถึงสมาชิกที่ไม่ใช่ส่วนตัวทั้งหมดของคลาสพื้นฐานได้ ดังนั้นสมาชิกระดับฐานที่ไม่ควรเข้าถึงฟังก์ชันสมาชิกของคลาสที่ได้รับมาจึงควรประกาศเป็นส่วนตัวในคลาสพื้นฐาน
เราสามารถสรุปประเภทการเข้าถึงต่างๆตาม - ใครสามารถเข้าถึงได้ด้วยวิธีต่อไปนี้ -
เข้าไป | สาธารณะ | มีการป้องกัน | เอกชน |
---|---|---|---|
ชั้นเดียวกัน | ใช่ | ใช่ | ใช่ |
คลาสที่ได้รับ | ใช่ | ใช่ | ไม่ |
นอกชั้นเรียน | ใช่ | ไม่ | ไม่ |
คลาสที่ได้รับสืบทอดเมธอดคลาสพื้นฐานทั้งหมดโดยมีข้อยกเว้นต่อไปนี้ -
- ตัวสร้างตัวทำลายและตัวสร้างสำเนาของคลาสพื้นฐาน
- ตัวดำเนินการที่มากเกินไปของคลาสพื้นฐาน
- ฟังก์ชันเพื่อนของคลาสพื้นฐาน
ประเภทของมรดก
เมื่อได้รับคลาสจากคลาสฐานคลาสพื้นฐานอาจถูกสืบทอดผ่าน public, protected หรือ privateมรดก ประเภทของการสืบทอดถูกระบุโดยตัวระบุการเข้าถึงตามที่อธิบายไว้ข้างต้น
เราแทบจะไม่ได้ใช้ protected หรือ private มรดก แต่ publicนิยมใช้การถ่ายทอดทางพันธุกรรม ในขณะที่ใช้การสืบทอดประเภทต่างๆจะใช้กฎต่อไปนี้ -
Public Inheritance - เมื่อได้รับคลาสจากก public ชั้นฐาน public สมาชิกของคลาสพื้นฐานกลายเป็น public สมาชิกของคลาสที่ได้รับและ protected สมาชิกของคลาสพื้นฐานกลายเป็น protectedสมาชิกของคลาสที่ได้รับ คลาสฐานprivate สมาชิกจะไม่สามารถเข้าถึงได้โดยตรงจากคลาสที่ได้รับ แต่สามารถเข้าถึงได้ผ่านการโทรไปยังไฟล์ public และ protected สมาชิกของคลาสพื้นฐาน
Protected Inheritance - เมื่อได้มาจากก protected ชั้นฐาน public และ protected สมาชิกของคลาสพื้นฐานกลายเป็น protected สมาชิกของคลาสที่ได้รับ
Private Inheritance - เมื่อได้มาจากก private ชั้นฐาน public และ protected สมาชิกของคลาสพื้นฐานกลายเป็น private สมาชิกของคลาสที่ได้รับ
มรดกหลายรายการ
คลาส C ++ สามารถสืบทอดสมาชิกจากมากกว่าหนึ่งคลาสและนี่คือไวยากรณ์เพิ่มเติม -
class derived-class: access baseA, access baseB....
การเข้าถึงเป็นหนึ่งใน public, protected, หรือ privateและจะได้รับสำหรับทุกคลาสพื้นฐานและจะถูกคั่นด้วยลูกน้ำตามที่แสดงด้านบน ให้เราลองตัวอย่างต่อไปนี้ -
#include <iostream>
using namespace std;
// Base class Shape
class Shape {
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Base class PaintCost
class PaintCost {
public:
int getCost(int area) {
return area * 70;
}
};
// Derived class
class Rectangle: public Shape, public PaintCost {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
// Print the total cost of painting
cout << "Total paint cost: $" << Rect.getCost(area) << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Total area: 35
Total paint cost: $2450
C ++ ช่วยให้คุณสามารถระบุคำจำกัดความได้มากกว่าหนึ่งคำจำกัดความสำหรับไฟล์ function ชื่อหรือ operator ในขอบเขตเดียวกันซึ่งเรียกว่า function overloading และ operator overloading ตามลำดับ
การประกาศเกินพิกัดคือการประกาศที่ประกาศด้วยชื่อเดียวกันกับการประกาศที่ประกาศไว้ก่อนหน้านี้ในขอบเขตเดียวกันยกเว้นว่าการประกาศทั้งสองจะมีข้อโต้แย้งที่แตกต่างกันและความหมายที่แตกต่างกันอย่างเห็นได้ชัด (การนำไปใช้งาน)
เมื่อคุณโทรเกิน function หรือ operatorคอมไพลเลอร์จะกำหนดนิยามที่เหมาะสมที่สุดที่จะใช้โดยการเปรียบเทียบประเภทอาร์กิวเมนต์ที่คุณใช้ในการเรียกใช้ฟังก์ชันหรือตัวดำเนินการกับประเภทพารามิเตอร์ที่ระบุไว้ในนิยาม เรียกกระบวนการเลือกฟังก์ชันโอเวอร์โหลดที่เหมาะสมที่สุดหรือตัวดำเนินการoverload resolution.
ฟังก์ชันโอเวอร์โหลดใน C ++
คุณสามารถกำหนดได้หลายคำจำกัดความสำหรับชื่อฟังก์ชันเดียวกันในขอบเขตเดียวกัน คำจำกัดความของฟังก์ชันต้องแตกต่างกันตามประเภทและ / หรือจำนวนอาร์กิวเมนต์ในรายการอาร์กิวเมนต์ คุณไม่สามารถโอเวอร์โหลดการประกาศฟังก์ชันที่แตกต่างกันตามประเภทการส่งคืนเท่านั้น
ต่อไปนี้เป็นตัวอย่างที่มีฟังก์ชันเดียวกัน print() ถูกใช้เพื่อพิมพ์ข้อมูลประเภทต่างๆ -
#include <iostream>
using namespace std;
class printData {
public:
void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing float: " << f << endl;
}
void print(char* c) {
cout << "Printing character: " << c << endl;
}
};
int main(void) {
printData pd;
// Call print to print integer
pd.print(5);
// Call print to print float
pd.print(500.263);
// Call print to print character
pd.print("Hello C++");
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Printing int: 5
Printing float: 500.263
Printing character: Hello C++
ตัวดำเนินการมากเกินไปใน C ++
คุณสามารถกำหนดใหม่หรือโอเวอร์โหลดตัวดำเนินการในตัวส่วนใหญ่ที่มีอยู่ใน C ++ ได้ ดังนั้นโปรแกรมเมอร์สามารถใช้ตัวดำเนินการกับประเภทที่ผู้ใช้กำหนดได้เช่นกัน
ตัวดำเนินการที่โอเวอร์โหลดคือฟังก์ชันที่มีชื่อพิเศษ: คำหลัก "ตัวดำเนินการ" ตามด้วยสัญลักษณ์สำหรับตัวดำเนินการที่กำหนด เช่นเดียวกับฟังก์ชันอื่น ๆ ตัวดำเนินการที่โอเวอร์โหลดจะมีประเภทการส่งคืนและรายการพารามิเตอร์
Box operator+(const Box&);
ประกาศตัวดำเนินการเพิ่มเติมที่สามารถใช้ได้ addวัตถุกล่องสองชิ้นและส่งคืนวัตถุกล่องสุดท้าย ตัวดำเนินการที่โอเวอร์โหลดส่วนใหญ่อาจถูกกำหนดให้เป็นฟังก์ชันที่ไม่ใช่สมาชิกทั่วไปหรือเป็นฟังก์ชันสมาชิกชั้น ในกรณีที่เรากำหนดฟังก์ชันข้างต้นเป็นฟังก์ชันที่ไม่ใช่สมาชิกของคลาสเราจะต้องส่งสองอาร์กิวเมนต์สำหรับแต่ละตัวถูกดำเนินการดังนี้ -
Box operator+(const Box&, const Box&);
ต่อไปนี้เป็นตัวอย่างเพื่อแสดงแนวคิดของตัวดำเนินการเกี่ยวกับการโหลดโดยใช้ฟังก์ชันสมาชิก ที่นี่วัตถุจะถูกส่งผ่านเป็นอาร์กิวเมนต์ซึ่งคุณสมบัติจะถูกเข้าถึงโดยใช้วัตถุนี้วัตถุที่จะเรียกตัวดำเนินการนี้สามารถเข้าถึงได้โดยใช้this ตามคำอธิบายด้านล่าง -
#include <iostream>
using namespace std;
class Box {
public:
double getVolume(void) {
return length * breadth * height;
}
void setLength( double len ) {
length = len;
}
void setBreadth( double bre ) {
breadth = bre;
}
void setHeight( double hei ) {
height = hei;
}
// Overload + operator to add two Box objects.
Box operator+(const Box& b) {
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// Main function for the program
int main() {
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
Box Box3; // Declare Box3 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
// Add two object as follows:
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
โอเวอร์โหลด / ไม่โอเวอร์โหลด
ต่อไปนี้เป็นรายชื่อตัวดำเนินการที่สามารถโอเวอร์โหลดได้ -
+ | - | * | / | % | ^ |
& | | | ~ | ! | , | = |
< | > | <= | > = | ++ | - |
<< | >> | == | ! = | && | || |
+ = | - = | / = | % = | ^ = | & = |
| = | * = | << = | >> = | [] | () |
-> | -> * | ใหม่ | ใหม่ [] | ลบ | ลบ [] |
ต่อไปนี้เป็นรายชื่อตัวดำเนินการซึ่งไม่สามารถโอเวอร์โหลดได้ -
:: | . * | . | ?: |
ตัวอย่างการโอเวอร์โหลดของตัวดำเนินการ
ต่อไปนี้เป็นตัวอย่างการทำงานหนักเกินไปของตัวดำเนินการต่างๆเพื่อช่วยคุณในการทำความเข้าใจแนวคิด
ซีเนียร์ No | Operators & Example |
---|---|
1 | Unary Operators Overloading |
2 | Binary Operators Overloading |
3 | Relational Operators Overloading |
4 | Input/Output Operators Overloading |
5 | ++ and -- Operators Overloading |
6 | Assignment Operators Overloading |
7 | Function call () Operator Overloading |
8 | Subscripting [] Operator Overloading |
9 | Class Member Access Operator -> Overloading |
The word polymorphism means having many forms. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.
C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.
Consider the following example where a base class has been derived by other two classes −
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0){
width = a;
height = b;
}
int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape {
public:
Rectangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape {
public:
Triangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main() {
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Rectangle
shape = &rec;
// call rectangle area.
shape->area();
// store the address of Triangle
shape = &tri;
// call triangle area.
shape->area();
return 0;
}
When the above code is compiled and executed, it produces the following result −
Parent class area :
Parent class area :
The reason for the incorrect output is that the call of the function area() is being set once by the compiler as the version defined in the base class. This is called static resolution of the function call, or static linkage - the function call is fixed before the program is executed. This is also sometimes called early binding because the area() function is set during the compilation of the program.
But now, let's make a slight modification in our program and precede the declaration of area() in the Shape class with the keyword virtual so that it looks like this −
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0) {
width = a;
height = b;
}
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
After this slight modification, when the previous example code is compiled and executed, it produces the following result −
Rectangle class area
Triangle class area
This time, the compiler looks at the contents of the pointer instead of it's type. Hence, since addresses of objects of tri and rec classes are stored in *shape the respective area() function is called.
As you can see, each of the child classes has a separate implementation for the function area(). This is how polymorphism is generally used. You have different classes with a function of the same name, and even the same parameters, but with different implementations.
Virtual Function
A virtual function is a function in a base class that is declared using the keyword virtual. Defining in a base class a virtual function, with another version in a derived class, signals to the compiler that we don't want static linkage for this function.
What we do want is the selection of the function to be called at any given point in the program to be based on the kind of object for which it is called. This sort of operation is referred to as dynamic linkage, or late binding.
Pure Virtual Functions
It is possible that you want to include a virtual function in a base class so that it may be redefined in a derived class to suit the objects of that class, but that there is no meaningful definition you could give for the function in the base class.
We can change the virtual function area() in the base class to the following −
class Shape {
protected:
int width, height;
public:
Shape(int a = 0, int b = 0) {
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
The = 0 tells the compiler that the function has no body and above virtual function will be called pure virtual function.
Data abstraction refers to providing only essential information to the outside world and hiding their background details, i.e., to represent the needed information in program without presenting the details.
Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation.
Let's take one real life example of a TV, which you can turn on and off, change the channel, adjust the volume, and add external components such as speakers, VCRs, and DVD players, BUT you do not know its internal details, that is, you do not know how it receives signals over the air or through a cable, how it translates them, and finally displays them on the screen.
Thus, we can say a television clearly separates its internal implementation from its external interface and you can play with its interfaces like the power button, channel changer, and volume control without having any knowledge of its internals.
In C++, classes provides great level of data abstraction. They provide sufficient public methods to the outside world to play with the functionality of the object and to manipulate object data, i.e., state without actually knowing how class has been implemented internally.
For example, your program can make a call to the sort() function without knowing what algorithm the function actually uses to sort the given values. In fact, the underlying implementation of the sorting functionality could change between releases of the library, and as long as the interface stays the same, your function call will still work.
In C++, we use classes to define our own abstract data types (ADT). You can use the cout object of class ostream to stream data to standard output like this −
#include <iostream>
using namespace std;
int main() {
cout << "Hello C++" <<endl;
return 0;
}
Here, you don't need to understand how cout displays the text on the user's screen. You need to only know the public interface and the underlying implementation of ‘cout’ is free to change.
Access Labels Enforce Abstraction
In C++, we use access labels to define the abstract interface to the class. A class may contain zero or more access labels −
Members defined with a public label are accessible to all parts of the program. The data-abstraction view of a type is defined by its public members.
Members defined with a private label are not accessible to code that uses the class. The private sections hide the implementation from code that uses the type.
There are no restrictions on how often an access label may appear. Each access label specifies the access level of the succeeding member definitions. The specified access level remains in effect until the next access label is encountered or the closing right brace of the class body is seen.
Benefits of Data Abstraction
Data abstraction provides two important advantages −
Class internals are protected from inadvertent user-level errors, which might corrupt the state of the object.
The class implementation may evolve over time in response to changing requirements or bug reports without requiring change in user-level code.
By defining data members only in the private section of the class, the class author is free to make changes in the data. If the implementation changes, only the class code needs to be examined to see what affect the change may have. If data is public, then any function that directly access the data members of the old representation might be broken.
Data Abstraction Example
Any C++ program where you implement a class with public and private members is an example of data abstraction. Consider the following example −
#include <iostream>
using namespace std;
class Adder {
public:
// constructor
Adder(int i = 0) {
total = i;
}
// interface to outside world
void addNum(int number) {
total += number;
}
// interface to outside world
int getTotal() {
return total;
};
private:
// hidden data from outside world
int total;
};
int main() {
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Total 60
Above class adds numbers together, and returns the sum. The public members - addNum and getTotal are the interfaces to the outside world and a user needs to know them to use the class. The private member total is something that the user doesn't need to know about, but is needed for the class to operate properly.
Designing Strategy
Abstraction separates code into interface and implementation. So while designing your component, you must keep interface independent of the implementation so that if you change underlying implementation then interface would remain intact.
In this case whatever programs are using these interfaces, they would not be impacted and would just need a recompilation with the latest implementation.
All C++ programs are composed of the following two fundamental elements −
Program statements (code) − This is the part of a program that performs actions and they are called functions.
Program data − The data is the information of the program which gets affected by the program functions.
Encapsulation is an Object Oriented Programming concept that binds together the data and functions that manipulate the data, and that keeps both safe from outside interference and misuse. Data encapsulation led to the important OOP concept of data hiding.
Data encapsulation is a mechanism of bundling the data, and the functions that use them and data abstraction is a mechanism of exposing only the interfaces and hiding the implementation details from the user.
C++ supports the properties of encapsulation and data hiding through the creation of user-defined types, called classes. We already have studied that a class can contain private, protected and public members. By default, all items defined in a class are private. For example −
class Box {
public:
double getVolume(void) {
return length * breadth * height;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
ตัวแปรความยาวความกว้างและความสูงคือ private. ซึ่งหมายความว่าสมาชิกคนอื่น ๆ ในคลาส Box สามารถเข้าถึงได้เท่านั้นและไม่สามารถเข้าถึงได้โดยส่วนอื่น ๆ ของโปรแกรมของคุณ นี่เป็นวิธีการห่อหุ้มวิธีหนึ่งที่ทำได้
เพื่อสร้างส่วนต่างๆของชั้นเรียน public (กล่าวคือสามารถเข้าถึงส่วนอื่น ๆ ของโปรแกรมของคุณได้) คุณต้องประกาศหลังจากส่วน publicคำสำคัญ. ตัวแปรหรือฟังก์ชันทั้งหมดที่กำหนดหลังจากตัวระบุสาธารณะสามารถเข้าถึงได้โดยฟังก์ชันอื่น ๆ ทั้งหมดในโปรแกรมของคุณ
การทำให้ชั้นเรียนเป็นเพื่อนกับอีกคนหนึ่งจะทำให้รายละเอียดการนำไปใช้งานและลดการห่อหุ้ม วิธีที่ดีที่สุดคือการเก็บรายละเอียดของแต่ละคลาสให้ซ่อนจากคลาสอื่น ๆ ให้ได้มากที่สุด
ตัวอย่างการห่อหุ้มข้อมูล
โปรแกรม C ++ ใด ๆ ที่คุณใช้คลาสร่วมกับสมาชิกภาครัฐและเอกชนเป็นตัวอย่างของการห่อหุ้มข้อมูลและการแยกข้อมูล ลองพิจารณาตัวอย่างต่อไปนี้ -
#include <iostream>
using namespace std;
class Adder {
public:
// constructor
Adder(int i = 0) {
total = i;
}
// interface to outside world
void addNum(int number) {
total += number;
}
// interface to outside world
int getTotal() {
return total;
};
private:
// hidden data from outside world
int total;
};
int main() {
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Total 60
ชั้นเรียนด้านบนจะเพิ่มตัวเลขเข้าด้วยกันและส่งกลับผลรวม สมาชิกสาธารณะaddNum และ getTotal เป็นส่วนต่อประสานกับโลกภายนอกและผู้ใช้จำเป็นต้องรู้จักพวกเขาเพื่อใช้คลาส สมาชิกส่วนตัวtotal เป็นสิ่งที่ซ่อนตัวจากโลกภายนอก แต่จำเป็นสำหรับชั้นเรียนเพื่อให้ทำงานได้อย่างถูกต้อง
การออกแบบกลยุทธ์
พวกเราส่วนใหญ่ได้เรียนรู้ที่จะกำหนดให้สมาชิกชั้นเรียนเป็นส่วนตัวโดยปริยายเว้นแต่เราจำเป็นต้องเปิดเผยพวกเขาจริงๆ นั่นเป็นสิ่งที่ดีencapsulation.
สิ่งนี้ถูกนำไปใช้กับสมาชิกข้อมูลบ่อยที่สุด แต่จะใช้กับสมาชิกทั้งหมดอย่างเท่าเทียมกันรวมถึงฟังก์ชันเสมือน
อินเทอร์เฟซจะอธิบายถึงพฤติกรรมหรือความสามารถของคลาส C ++ โดยไม่เกี่ยวข้องกับการนำคลาสนั้นไปใช้งานโดยเฉพาะ
อินเทอร์เฟซ C ++ ถูกนำไปใช้โดยใช้ abstract classes และไม่ควรสับสนกับคลาสนามธรรมเหล่านี้กับสิ่งที่เป็นนามธรรมของข้อมูลซึ่งเป็นแนวคิดในการเก็บรายละเอียดการนำไปใช้งานแยกจากข้อมูลที่เกี่ยวข้อง
คลาสถูกทำให้เป็นนามธรรมโดยการประกาศฟังก์ชันอย่างน้อยหนึ่งอย่างเป็น pure virtualฟังก์ชัน ฟังก์ชันเสมือนจริงถูกระบุโดยการวาง "= 0" ในการประกาศดังนี้ -
class Box {
public:
// pure virtual function
virtual double getVolume() = 0;
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
วัตถุประสงค์ของไฟล์ abstract class(มักเรียกว่า ABC) คือการจัดเตรียมคลาสพื้นฐานที่เหมาะสมซึ่งคลาสอื่นสามารถสืบทอดได้ ไม่สามารถใช้คลาสนามธรรมเพื่อสร้างอินสแตนซ์อ็อบเจ็กต์และทำหน้าที่เป็นไฟล์interface. ความพยายามที่จะสร้างอินสแตนซ์อ็อบเจ็กต์ของคลาสนามธรรมทำให้เกิดข้อผิดพลาดในการคอมไพล์
ดังนั้นหากจำเป็นต้องสร้างอินสแตนซ์คลาสย่อยของ ABC จะต้องใช้ฟังก์ชันเสมือนแต่ละฟังก์ชันซึ่งหมายความว่ารองรับอินเทอร์เฟซที่ประกาศโดย ABC ความล้มเหลวในการแทนที่ฟังก์ชันเสมือนจริงในคลาสที่ได้รับจากนั้นการพยายามสร้างอินสแตนซ์อ็อบเจ็กต์ของคลาสนั้นเป็นข้อผิดพลาดในการคอมไพล์
คลาสที่สามารถใช้เพื่อสร้างอินสแตนซ์อ็อบเจ็กต์ได้ concrete classes.
ตัวอย่างคลาสบทคัดย่อ
พิจารณาตัวอย่างต่อไปนี้โดยที่คลาสพาเรนต์จัดเตรียมอินเตอร์เฟสให้กับคลาสพื้นฐานเพื่อใช้ฟังก์ชันที่เรียกว่า getArea() -
#include <iostream>
using namespace std;
// Base class
class Shape {
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived classes
class Rectangle: public Shape {
public:
int getArea() {
return (width * height);
}
};
class Triangle: public Shape {
public:
int getArea() {
return (width * height)/2;
}
};
int main(void) {
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total Rectangle area: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
// Print the area of the object.
cout << "Total Triangle area: " << Tri.getArea() << endl;
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Total Rectangle area: 35
Total Triangle area: 17
คุณสามารถดูได้ว่าคลาสนามธรรมกำหนดอินเทอร์เฟซอย่างไรในแง่ของ getArea () และอีกสองคลาสใช้ฟังก์ชันเดียวกัน แต่ใช้อัลกอริทึมที่แตกต่างกันเพื่อคำนวณพื้นที่เฉพาะสำหรับรูปร่าง
การออกแบบกลยุทธ์
ระบบเชิงวัตถุอาจใช้คลาสฐานนามธรรมเพื่อจัดเตรียมอินเทอร์เฟซทั่วไปและเป็นมาตรฐานที่เหมาะสมสำหรับแอ็พพลิเคชันภายนอกทั้งหมด จากนั้นโดยการสืบทอดจากคลาสพื้นฐานนามธรรมนั้นคลาสที่ได้รับจะถูกสร้างขึ้นซึ่งทำงานในลักษณะเดียวกัน
ความสามารถ (เช่นฟังก์ชันสาธารณะ) ที่นำเสนอโดยแอปพลิเคชันภายนอกนั้นจัดเตรียมไว้เป็นฟังก์ชันเสมือนจริงในคลาสฐานนามธรรม การปรับใช้ฟังก์ชันเสมือนจริงเหล่านี้มีให้ในคลาสที่ได้รับซึ่งสอดคล้องกับประเภทเฉพาะของแอ็พพลิเคชัน
สถาปัตยกรรมนี้ยังช่วยให้สามารถเพิ่มแอพพลิเคชั่นใหม่ลงในระบบได้อย่างง่ายดายแม้ว่าระบบจะได้รับการกำหนดแล้วก็ตาม
จนถึงตอนนี้เราใช้ไฟล์ iostream ไลบรารีมาตรฐานซึ่งให้ cin และ cout วิธีการอ่านจากอินพุตมาตรฐานและการเขียนไปยังเอาต์พุตมาตรฐานตามลำดับ
บทแนะนำนี้จะสอนวิธีอ่านและเขียนจากไฟล์ สิ่งนี้ต้องการไลบรารี C ++ มาตรฐานอื่นที่เรียกว่าfstreamซึ่งกำหนดประเภทข้อมูลใหม่สามประเภท -
ซีเนียร์ No | ประเภทข้อมูลและคำอธิบาย |
---|---|
1 | ofstream ชนิดข้อมูลนี้แสดงถึงสตรีมไฟล์เอาต์พุตและใช้เพื่อสร้างไฟล์และเขียนข้อมูลไปยังไฟล์ |
2 | ifstream ชนิดข้อมูลนี้แสดงถึงสตรีมไฟล์อินพุตและใช้เพื่ออ่านข้อมูลจากไฟล์ |
3 | fstream ชนิดข้อมูลนี้แสดงถึงสตรีมไฟล์โดยทั่วไปและมีความสามารถของทั้ง ofstream และ ifstream ซึ่งหมายความว่าสามารถสร้างไฟล์เขียนข้อมูลไปยังไฟล์และอ่านข้อมูลจากไฟล์ได้ |
ในการประมวลผลไฟล์ใน C ++ ไฟล์ส่วนหัว <iostream> และ <fstream> ต้องรวมอยู่ในไฟล์ต้นฉบับ C ++ ของคุณ
การเปิดไฟล์
ต้องเปิดไฟล์ก่อนจึงจะสามารถอ่านหรือเขียนไฟล์ได้ ทั้งofstream หรือ fstreamอาจใช้วัตถุเพื่อเปิดไฟล์สำหรับเขียน และวัตถุ ifstream ใช้เพื่อเปิดไฟล์เพื่อการอ่านเท่านั้น
ต่อไปนี้เป็นไวยากรณ์มาตรฐานสำหรับฟังก์ชัน open () ซึ่งเป็นสมาชิกของอ็อบเจ็กต์ fstream, ifstream และ ofstream
void open(const char *filename, ios::openmode mode);
ที่นี่อาร์กิวเมนต์แรกระบุชื่อและตำแหน่งของไฟล์ที่จะเปิดและอาร์กิวเมนต์ที่สองของไฟล์ open() ฟังก์ชันสมาชิกกำหนดโหมดที่ควรเปิดไฟล์
ซีเนียร์ No | โหมดแฟล็กและคำอธิบาย |
---|---|
1 | ios::app โหมดต่อท้าย เอาต์พุตทั้งหมดไปยังไฟล์นั้นที่จะต่อท้าย |
2 | ios::ate เปิดไฟล์สำหรับเอาต์พุตและย้ายตัวควบคุมการอ่าน / เขียนไปที่ส่วนท้ายของไฟล์ |
3 | ios::in เปิดไฟล์เพื่ออ่าน |
4 | ios::out เปิดไฟล์สำหรับเขียน |
5 | ios::trunc หากไฟล์มีอยู่แล้วเนื้อหาจะถูกตัดทอนก่อนเปิดไฟล์ |
คุณสามารถรวมค่าเหล่านี้ตั้งแต่สองค่าขึ้นไปโดย ORเข้าด้วยกัน ตัวอย่างเช่นหากคุณต้องการเปิดไฟล์ในโหมดเขียนและต้องการตัดทอนในกรณีที่มีอยู่แล้วต่อไปนี้จะเป็นไวยากรณ์ -
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );
ในทำนองเดียวกันคุณสามารถเปิดไฟล์เพื่ออ่านและเขียนได้ดังนี้ -
fstream afile;
afile.open("file.dat", ios::out | ios::in );
การปิดไฟล์
เมื่อโปรแกรม C ++ ยุติโปรแกรมจะล้างสตรีมทั้งหมดโดยอัตโนมัติปล่อยหน่วยความจำที่จัดสรรทั้งหมดและปิดไฟล์ที่เปิดทั้งหมด แต่เป็นแนวทางปฏิบัติที่ดีเสมอที่โปรแกรมเมอร์ควรปิดไฟล์ที่เปิดอยู่ทั้งหมดก่อนที่จะยุติโปรแกรม
ต่อไปนี้เป็นไวยากรณ์มาตรฐานสำหรับฟังก์ชัน close () ซึ่งเป็นสมาชิกของอ็อบเจ็กต์ fstream, ifstream และ ofstream
void close();
การเขียนไฟล์
ขณะทำการเขียนโปรแกรม C ++ คุณเขียนข้อมูลไปยังไฟล์จากโปรแกรมของคุณโดยใช้ตัวดำเนินการแทรกสตรีม (<<) เช่นเดียวกับที่คุณใช้ตัวดำเนินการนั้นเพื่อส่งออกข้อมูลไปยังหน้าจอ ข้อแตกต่างเพียงอย่างเดียวคือคุณใช้ไฟล์ofstream หรือ fstream วัตถุแทน cout วัตถุ.
อ่านจากไฟล์
คุณอ่านข้อมูลจากไฟล์ลงในโปรแกรมของคุณโดยใช้ตัวดำเนินการแยกสตรีม (>>) เช่นเดียวกับที่คุณใช้โอเปอเรเตอร์นั้นเพื่อป้อนข้อมูลจากแป้นพิมพ์ ข้อแตกต่างเพียงอย่างเดียวคือคุณใช้ไฟล์ifstream หรือ fstream วัตถุแทน cin วัตถุ.
อ่านและเขียนตัวอย่าง
ต่อไปนี้เป็นโปรแกรม C ++ ซึ่งเปิดไฟล์ในโหมดอ่านและเขียน หลังจากเขียนข้อมูลที่ผู้ใช้ป้อนไปยังไฟล์ชื่อ afile.dat โปรแกรมจะอ่านข้อมูลจากไฟล์และส่งออกไปยังหน้าจอ -
#include <fstream>
#include <iostream>
using namespace std;
int main () {
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้โค้ดจะสร้างอินพุตและเอาต์พุตตัวอย่างต่อไปนี้ -
$./a.out
Writing to the file
Enter your name: Zara
Enter your age: 9
Reading from the file
Zara
9
ตัวอย่างด้านบนใช้ประโยชน์จากฟังก์ชันเพิ่มเติมจากวัตถุ cin เช่นฟังก์ชัน getline () เพื่ออ่านบรรทัดจากภายนอกและฟังก์ชันละเว้น () เพื่อละเว้นอักขระพิเศษที่เหลือจากคำสั่งอ่านก่อนหน้า
ตัวชี้ตำแหน่งไฟล์
ทั้งสอง istream และ ostreamจัดเตรียมฟังก์ชันสมาชิกสำหรับการปรับตำแหน่งตัวชี้ตำแหน่งไฟล์ ฟังก์ชันสมาชิกเหล่านี้คือseekg ("หารับ") สำหรับ istream และ seekp ("ค้นหาใส่") สำหรับ ostream
อาร์กิวเมนต์สำหรับ seekg และ askp โดยปกติเป็นจำนวนเต็มยาว สามารถระบุอาร์กิวเมนต์ที่สองเพื่อระบุทิศทางการแสวงหา ทิศทางการแสวงหาสามารถios::beg (ค่าเริ่มต้น) สำหรับการวางตำแหน่งที่สัมพันธ์กับจุดเริ่มต้นของสตรีม ios::cur สำหรับการวางตำแหน่งที่สัมพันธ์กับตำแหน่งปัจจุบันในสตรีมหรือ ios::end สำหรับการวางตำแหน่งที่สัมพันธ์กับจุดสิ้นสุดของสตรีม
ตัวชี้ตำแหน่งไฟล์เป็นค่าจำนวนเต็มที่ระบุตำแหน่งในไฟล์เป็นจำนวนไบต์จากตำแหน่งเริ่มต้นของไฟล์ ตัวอย่างบางส่วนของการวางตำแหน่งตัวชี้ตำแหน่งไฟล์ "รับ" ได้แก่ -
// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n );
// position n bytes forward in fileObject
fileObject.seekg( n, ios::cur );
// position n bytes back from end of fileObject
fileObject.seekg( n, ios::end );
// position at end of fileObject
fileObject.seekg( 0, ios::end );
ข้อยกเว้นคือปัญหาที่เกิดขึ้นระหว่างการทำงานของโปรแกรม ข้อยกเว้น C ++ คือการตอบสนองต่อสถานการณ์พิเศษที่เกิดขึ้นในขณะที่โปรแกรมกำลังทำงานเช่นความพยายามที่จะหารด้วยศูนย์
ข้อยกเว้นเป็นวิธีการถ่ายโอนการควบคุมจากส่วนหนึ่งของโปรแกรมไปยังอีกส่วนหนึ่ง การจัดการข้อยกเว้น C ++ สร้างขึ้นจากคำหลักสามคำ:try, catch, และ throw.
throw- โปรแกรมแสดงข้อยกเว้นเมื่อปัญหาปรากฏขึ้น ทำได้โดยใช้ไฟล์throw คำสำคัญ.
catch- โปรแกรมตรวจจับข้อยกเว้นด้วยตัวจัดการข้อยกเว้นที่ตำแหน่งในโปรแกรมที่คุณต้องการจัดการปัญหา catch คีย์เวิร์ดบ่งบอกถึงการจับข้อยกเว้น
try - ก tryblock ระบุบล็อกของโค้ดที่จะเปิดใช้งานข้อยกเว้นเฉพาะ ตามด้วยบล็อกจับอย่างน้อยหนึ่งบล็อก
สมมติว่าบล็อกจะเพิ่มข้อยกเว้นเมธอดจะจับข้อยกเว้นโดยใช้การรวมกันของ try และ catchคำหลัก บล็อก try / catch ถูกวางไว้รอบ ๆ โค้ดที่อาจสร้างข้อยกเว้น รหัสภายในบล็อก try / catch เรียกว่ารหัสป้องกันและไวยากรณ์สำหรับการใช้ try / catch ดังต่อไปนี้ -
try {
// protected code
} catch( ExceptionName e1 ) {
// catch block
} catch( ExceptionName e2 ) {
// catch block
} catch( ExceptionName eN ) {
// catch block
}
คุณสามารถลงรายการได้หลายรายการ catch เพื่อตรวจจับข้อยกเว้นประเภทต่างๆในกรณีที่ไฟล์ try บล็อกมีข้อยกเว้นมากกว่าหนึ่งข้อในสถานการณ์ต่างๆ
การโยนข้อยกเว้น
สามารถโยนข้อยกเว้นที่ใดก็ได้ภายในบล็อกรหัสโดยใช้ throwคำให้การ. ตัวถูกดำเนินการของคำสั่ง throw จะกำหนดประเภทของข้อยกเว้นและสามารถเป็นนิพจน์ใดก็ได้และประเภทของผลลัพธ์ของนิพจน์จะกำหนดประเภทของข้อยกเว้นที่ถูกโยน
ต่อไปนี้เป็นตัวอย่างของการโยนข้อยกเว้นเมื่อเกิดการหารด้วยเงื่อนไขศูนย์ -
double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}
การจับข้อยกเว้น
catch บล็อกตาม tryบล็อกจับข้อยกเว้นใด ๆ คุณสามารถระบุประเภทของข้อยกเว้นที่คุณต้องการตรวจจับและสิ่งนี้ถูกกำหนดโดยการประกาศข้อยกเว้นที่ปรากฏในวงเล็บหลังจากที่จับคีย์เวิร์ด
try {
// protected code
} catch( ExceptionName e ) {
// code to handle ExceptionName exception
}
โค้ดด้านบนจะมีข้อยกเว้น ExceptionNameประเภท. หากคุณต้องการระบุว่า catch block ควรจัดการกับข้อยกเว้นประเภทใด ๆ ที่เกิดขึ้นใน try block คุณต้องใส่จุดไข่ปลา, ... , ระหว่างวงเล็บที่ล้อมรอบการประกาศข้อยกเว้นดังนี้ -
try {
// protected code
} catch(...) {
// code to handle any exception
}
ต่อไปนี้เป็นตัวอย่างซึ่งทำให้เกิดการหารด้วยข้อยกเว้นเป็นศูนย์และเราจับมันในบล็อกจับ
#include <iostream>
using namespace std;
double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}
int main () {
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
} catch (const char* msg) {
cerr << msg << endl;
}
return 0;
}
เนื่องจากเรากำลังเพิ่มข้อยกเว้นประเภท const char*ดังนั้นในขณะที่จับข้อยกเว้นนี้เราต้องใช้ const char * ใน catch block หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Division by zero condition!
ข้อยกเว้นมาตรฐาน C ++
C ++ แสดงรายการข้อยกเว้นมาตรฐานที่กำหนดไว้ใน <exception>ซึ่งเราสามารถใช้ในโปรแกรมของเรา สิ่งเหล่านี้จัดอยู่ในลำดับชั้นระดับแม่และลูกที่แสดงด้านล่าง -
นี่คือคำอธิบายเล็ก ๆ ของแต่ละข้อยกเว้นที่กล่าวถึงในลำดับชั้นข้างต้น -
ซีเนียร์ No | ข้อยกเว้นและคำอธิบาย |
---|---|
1 | std::exception ข้อยกเว้นและคลาสพาเรนต์ของข้อยกเว้น C ++ มาตรฐานทั้งหมด |
2 | std::bad_alloc นี้สามารถโยนโดย new. |
3 | std::bad_cast นี้สามารถโยนโดย dynamic_cast. |
4 | std::bad_exception นี่เป็นอุปกรณ์ที่มีประโยชน์ในการจัดการข้อยกเว้นที่ไม่คาดคิดในโปรแกรม C ++ |
5 | std::bad_typeid นี้สามารถโยนโดย typeid. |
6 | std::logic_error ข้อยกเว้นที่สามารถตรวจพบได้ในทางทฤษฎีโดยการอ่านรหัส |
7 | std::domain_error นี่เป็นข้อยกเว้นที่เกิดขึ้นเมื่อใช้โดเมนที่ไม่ถูกต้องทางคณิตศาสตร์ |
8 | std::invalid_argument สิ่งนี้เกิดขึ้นเนื่องจากข้อโต้แย้งที่ไม่ถูกต้อง |
9 | std::length_error สิ่งนี้จะเกิดขึ้นเมื่อสร้างสตริง std :: ที่ใหญ่เกินไป |
10 | std::out_of_range สิ่งนี้สามารถโยนได้ด้วยเมธอด 'at' ตัวอย่างเช่น std :: vector และ std :: bitset <> :: operator [] () |
11 | std::runtime_error ข้อยกเว้นที่ไม่สามารถตรวจพบในทางทฤษฎีโดยการอ่านรหัส |
12 | std::overflow_error สิ่งนี้จะเกิดขึ้นหากเกิดการล้นทางคณิตศาสตร์ |
13 | std::range_error เหตุการณ์นี้เกิดขึ้นเมื่อคุณพยายามจัดเก็บค่าที่อยู่นอกช่วง |
14 | std::underflow_error สิ่งนี้จะเกิดขึ้นหากเกิดการล้นเกินทางคณิตศาสตร์ |
กำหนดข้อยกเว้นใหม่
คุณสามารถกำหนดข้อยกเว้นของคุณเองได้โดยการสืบทอดและการลบล้าง exceptionฟังก์ชันคลาส ต่อไปนี้เป็นตัวอย่างซึ่งแสดงให้เห็นว่าคุณสามารถใช้คลาส std :: except เพื่อใช้ข้อยกเว้นของคุณเองในรูปแบบมาตรฐานได้อย่างไร -
#include <iostream>
#include <exception>
using namespace std;
struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
int main() {
try {
throw MyException();
} catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
} catch(std::exception& e) {
//Other errors
}
}
สิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
MyException caught
C++ Exception
ที่นี่ what()เป็นเมธอดสาธารณะที่จัดเตรียมโดยคลาสข้อยกเว้นและถูกแทนที่โดยคลาสข้อยกเว้นเด็กทั้งหมด สิ่งนี้ส่งคืนสาเหตุของข้อยกเว้น
ความเข้าใจที่ดีเกี่ยวกับการทำงานของหน่วยความจำแบบไดนามิกใน C ++ เป็นสิ่งสำคัญในการเป็นโปรแกรมเมอร์ C ++ ที่ดี หน่วยความจำในโปรแกรม C ++ ของคุณแบ่งออกเป็นสองส่วน -
The stack - ตัวแปรทั้งหมดที่ประกาศภายในฟังก์ชันจะใช้หน่วยความจำจากสแตก
The heap - นี่คือหน่วยความจำที่ไม่ได้ใช้ของโปรแกรมและสามารถใช้เพื่อจัดสรรหน่วยความจำแบบไดนามิกเมื่อโปรแกรมทำงาน
หลายครั้งคุณไม่ทราบล่วงหน้าว่าคุณจะต้องใช้หน่วยความจำเท่าใดในการจัดเก็บข้อมูลเฉพาะในตัวแปรที่กำหนดและสามารถกำหนดขนาดของหน่วยความจำที่ต้องการได้ในขณะทำงาน
คุณสามารถจัดสรรหน่วยความจำในขณะรันภายในฮีปสำหรับตัวแปรประเภทที่กำหนดโดยใช้ตัวดำเนินการพิเศษใน C ++ ซึ่งส่งคืนที่อยู่ของพื้นที่ที่จัดสรร ตัวดำเนินการนี้เรียกว่าnew ตัวดำเนินการ
หากคุณไม่ต้องการหน่วยความจำที่จัดสรรแบบไดนามิกอีกต่อไปคุณสามารถใช้ไฟล์ delete ตัวดำเนินการซึ่งยกเลิกการจัดสรรหน่วยความจำที่เคยถูกจัดสรรโดยตัวดำเนินการใหม่
ใหม่และลบตัวดำเนินการ
มีไวยากรณ์ทั่วไปที่จะใช้ดังต่อไปนี้ new ตัวดำเนินการเพื่อจัดสรรหน่วยความจำแบบไดนามิกสำหรับชนิดข้อมูลใด ๆ
new data-type;
ที่นี่ data-typeอาจเป็นประเภทข้อมูลในตัวรวมทั้งอาร์เรย์หรือประเภทข้อมูลที่ผู้ใช้กำหนด ได้แก่ คลาสหรือโครงสร้าง ให้เราเริ่มต้นด้วยชนิดข้อมูลในตัว ตัวอย่างเช่นเราสามารถกำหนดตัวชี้เพื่อพิมพ์ double แล้วขอให้จัดสรรหน่วยความจำในขณะดำเนินการ เราสามารถทำได้โดยใช้ไฟล์new ตัวดำเนินการที่มีข้อความต่อไปนี้ -
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
อาจจัดสรรหน่วยความจำไม่สำเร็จหากใช้ที่เก็บฟรีหมดแล้ว ดังนั้นจึงควรตรวจสอบว่าโอเปอเรเตอร์ใหม่ส่งคืนตัวชี้ NULL หรือไม่และดำเนินการตามความเหมาะสมดังต่อไปนี้ -
double* pvalue = NULL;
if( !(pvalue = new double )) {
cout << "Error: out of memory." <<endl;
exit(1);
}
malloc()ฟังก์ชันจาก C ยังคงมีอยู่ใน C ++ แต่ขอแนะนำให้หลีกเลี่ยงการใช้ฟังก์ชัน malloc () ข้อได้เปรียบหลักของ new over malloc () คือใหม่ไม่เพียงแค่จัดสรรหน่วยความจำเท่านั้น แต่ยังสร้างวัตถุซึ่งเป็นจุดประสงค์หลักของ C ++
เมื่อใดก็ตามที่คุณรู้สึกว่าตัวแปรที่ได้รับการจัดสรรแบบไดนามิกไม่จำเป็นอีกต่อไปคุณสามารถเพิ่มหน่วยความจำที่มีอยู่ในร้านค้าฟรีโดยใช้ตัวดำเนินการ 'ลบ' ดังนี้ -
delete pvalue; // Release memory pointed to by pvalue
ให้เราใส่แนวคิดข้างต้นและสร้างตัวอย่างต่อไปนี้เพื่อแสดงว่า 'ใหม่' และ 'ลบ' ทำงานอย่างไร -
#include <iostream>
using namespace std;
int main () {
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
*pvalue = 29494.99; // Store value at allocated address
cout << "Value of pvalue : " << *pvalue << endl;
delete pvalue; // free up the memory.
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Value of pvalue : 29495
การจัดสรรหน่วยความจำแบบไดนามิกสำหรับอาร์เรย์
พิจารณาว่าคุณต้องการจัดสรรหน่วยความจำสำหรับอาร์เรย์ของอักขระเช่นสตริง 20 อักขระ การใช้ไวยากรณ์เดียวกันกับที่เราใช้ข้างต้นเราสามารถจัดสรรหน่วยความจำแบบไดนามิกดังที่แสดงด้านล่าง
char* pvalue = NULL; // Pointer initialized with null
pvalue = new char[20]; // Request memory for the variable
ในการลบอาร์เรย์ที่เราเพิ่งสร้างคำสั่งจะมีลักษณะดังนี้ -
delete [] pvalue; // Delete array pointed to by pvalue
ตามไวยากรณ์ทั่วไปที่คล้ายกันของตัวดำเนินการใหม่คุณสามารถจัดสรรอาร์เรย์หลายมิติได้ดังนี้ -
double** pvalue = NULL; // Pointer initialized with null
pvalue = new double [3][4]; // Allocate memory for a 3x4 array
อย่างไรก็ตามไวยากรณ์ที่จะปล่อยหน่วยความจำสำหรับอาร์เรย์หลายมิติจะยังคงเหมือนเดิม -
delete [] pvalue; // Delete array pointed to by pvalue
การจัดสรรหน่วยความจำแบบไดนามิกสำหรับออบเจ็กต์
ออบเจ็กต์ไม่แตกต่างจากชนิดข้อมูลธรรมดา ตัวอย่างเช่นพิจารณารหัสต่อไปนี้ที่เราจะใช้อาร์เรย์ของวัตถุเพื่อชี้แจงแนวคิด -
#include <iostream>
using namespace std;
class Box {
public:
Box() {
cout << "Constructor called!" <<endl;
}
~Box() {
cout << "Destructor called!" <<endl;
}
};
int main() {
Box* myBoxArray = new Box[4];
delete [] myBoxArray; // Delete array
return 0;
}
ถ้าคุณจะจัดสรรอาร์เรย์ของอ็อบเจ็กต์ Box สี่ตัวตัวสร้างแบบง่ายจะถูกเรียกสี่ครั้งและในทำนองเดียวกันในขณะที่ลบอ็อบเจ็กต์เหล่านี้ destructor จะถูกเรียกจำนวนครั้งเท่ากัน
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!
ลองพิจารณาสถานการณ์เมื่อเรามี Zara สองคนที่มีชื่อเดียวกันในคลาสเดียวกัน เมื่อใดก็ตามที่เราต้องการแยกความแตกต่างอย่างแน่นอนเราจะต้องใช้ข้อมูลเพิ่มเติมพร้อมกับชื่อของพวกเขาเช่นพื้นที่หากพวกเขาอาศัยอยู่ในพื้นที่อื่นหรือชื่อแม่หรือพ่อของพวกเขาเป็นต้น
สถานการณ์เดียวกันอาจเกิดขึ้นในแอปพลิเคชัน C ++ ของคุณ ตัวอย่างเช่นคุณอาจเขียนโค้ดบางตัวที่มีฟังก์ชันชื่อ xyz () และมีไลบรารีอื่นที่พร้อมใช้งานซึ่งมีฟังก์ชัน xyz () เหมือนกัน ตอนนี้คอมไพเลอร์ไม่มีทางรู้ได้ว่าฟังก์ชัน xyz () เวอร์ชันใดที่คุณอ้างถึงภายในโค้ดของคุณ
ก namespaceได้รับการออกแบบมาเพื่อเอาชนะความยากลำบากนี้และใช้เป็นข้อมูลเพิ่มเติมเพื่อแยกความแตกต่างของฟังก์ชันคลาสตัวแปรและอื่น ๆ ที่คล้ายคลึงกันด้วยชื่อเดียวกันที่มีอยู่ในไลบรารีต่างๆ การใช้เนมสเปซคุณสามารถกำหนดบริบทที่จะกำหนดชื่อได้ โดยพื้นฐานแล้วเนมสเปซกำหนดขอบเขต
การกำหนดเนมสเปซ
นิยามเนมสเปซเริ่มต้นด้วยคีย์เวิร์ด namespace ตามด้วยชื่อเนมสเปซดังนี้ -
namespace namespace_name {
// code declarations
}
ในการเรียกเวอร์ชันที่เปิดใช้งานเนมสเปซของฟังก์ชันหรือตัวแปรใด ๆ ให้นำหน้า (: :) ชื่อเนมสเปซดังนี้ -
name::code; // code could be variable or function.
ให้เราดูว่าเนมสเปซขอบเขตเอนทิตีรวมถึงตัวแปรและฟังก์ชันอย่างไร -
#include <iostream>
using namespace std;
// first name space
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
// second name space
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
int main () {
// Calls function from first name space.
first_space::func();
// Calls function from second name space.
second_space::func();
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Inside first_space
Inside second_space
คำสั่งโดยใช้
คุณยังสามารถหลีกเลี่ยงการเติมเนมสเปซล่วงหน้าด้วยนามสกุล using namespaceคำสั่ง คำสั่งนี้บอกคอมไพลเลอร์ว่าโค้ดที่ตามมาใช้ชื่อในเนมสเปซที่ระบุ ดังนั้นเนมสเปซจึงมีนัยสำหรับรหัสต่อไปนี้ -
#include <iostream>
using namespace std;
// first name space
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
// second name space
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
using namespace first_space;
int main () {
// This calls function from first name space.
func();
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Inside first_space
คำสั่ง 'ใช้' ยังสามารถใช้เพื่ออ้างถึงรายการเฉพาะภายในเนมสเปซ ตัวอย่างเช่นหากส่วนเดียวของเนมสเปซมาตรฐานที่คุณต้องการใช้คือ cout คุณสามารถอ้างถึงได้ดังนี้ -
using std::cout;
รหัสต่อมาสามารถอ้างถึง cout โดยไม่ต้องเติมเนมสเปซล่วงหน้า แต่รายการอื่น ๆ ในไฟล์ std เนมสเปซยังคงต้องมีความชัดเจนดังต่อไปนี้ -
#include <iostream>
using std::cout;
int main () {
cout << "std::endl is used with std!" << std::endl;
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
std::endl is used with std!
ชื่อที่แนะนำในไฟล์ usingคำสั่งปฏิบัติตามกฎขอบเขตปกติ ชื่อสามารถมองเห็นได้จากจุดของusingคำสั่งไปยังจุดสิ้นสุดของขอบเขตที่พบคำสั่ง เอนทิตีที่มีชื่อเดียวกันซึ่งกำหนดไว้ในขอบเขตภายนอกจะถูกซ่อนไว้
เนมสเปซที่ไม่ชัดเจน
สามารถกำหนดเนมสเปซได้หลายส่วนดังนั้นเนมสเปซจึงประกอบด้วยผลรวมของส่วนที่กำหนดแยกกัน ส่วนที่แยกจากกันของเนมสเปซสามารถกระจายไปยังไฟล์หลาย ๆ ไฟล์
ดังนั้นหากส่วนหนึ่งของเนมสเปซต้องการชื่อที่กำหนดไว้ในไฟล์อื่นก็ยังต้องประกาศชื่อนั้น การเขียนนิยามเนมสเปซต่อไปนี้เป็นการกำหนดเนมสเปซใหม่หรือเพิ่มองค์ประกอบใหม่ให้กับที่มีอยู่ -
namespace namespace_name {
// code declarations
}
เนมสเปซที่ซ้อนกัน
Namespaces สามารถซ้อนกันซึ่งคุณสามารถกำหนดหนึ่งเนมสเปซภายในช่องชื่ออื่นได้ดังนี้ -
namespace namespace_name1 {
// code declarations
namespace namespace_name2 {
// code declarations
}
}
คุณสามารถเข้าถึงสมาชิกของเนมสเปซที่ซ้อนกันได้โดยใช้ตัวดำเนินการความละเอียดดังนี้ -
// to access members of namespace_name2
using namespace namespace_name1::namespace_name2;
// to access members of namespace:name1
using namespace namespace_name1;
ในข้อความข้างต้นหากคุณใช้ namespace_name1 มันจะทำให้องค์ประกอบของ namespace_name2 พร้อมใช้งานในขอบเขตดังนี้ -
#include <iostream>
using namespace std;
// first name space
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
// second name space
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
}
using namespace first_space::second_space;
int main () {
// This calls function from second name space.
func();
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Inside second_space
เทมเพลตเป็นรากฐานของการเขียนโปรแกรมทั่วไปซึ่งเกี่ยวข้องกับการเขียนโค้ดในลักษณะที่ไม่ขึ้นกับประเภทใดประเภทหนึ่ง
เทมเพลตคือพิมพ์เขียวหรือสูตรสำหรับสร้างคลาสทั่วไปหรือฟังก์ชัน คอนเทนเนอร์ไลบรารีเช่นตัววนซ้ำและอัลกอริทึมเป็นตัวอย่างของการเขียนโปรแกรมทั่วไปและได้รับการพัฒนาโดยใช้แนวคิดเทมเพลต
แต่ละคอนเทนเนอร์มีคำจำกัดความเดียวเช่น vectorแต่เราสามารถกำหนดเวกเตอร์ได้หลายประเภทเช่น vector <int> หรือ vector <string>.
คุณสามารถใช้เทมเพลตเพื่อกำหนดฟังก์ชันและคลาสได้ให้เราดูวิธีการทำงาน -
เทมเพลตฟังก์ชัน
รูปแบบทั่วไปของนิยามฟังก์ชันเทมเพลตแสดงที่นี่ -
template <class type> ret-type func-name(parameter list) {
// body of function
}
ในที่นี้ type คือชื่อตัวยึดสำหรับชนิดข้อมูลที่ฟังก์ชันใช้ ชื่อนี้สามารถใช้ภายในนิยามฟังก์ชัน
ต่อไปนี้เป็นตัวอย่างของเทมเพลตฟังก์ชันที่ส่งคืนค่าสูงสุดสองค่า -
#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& Max (T const& a, T const& b) {
return a < b ? b:a;
}
int main () {
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World
เทมเพลตคลาส
เช่นเดียวกับที่เราสามารถกำหนดเทมเพลตฟังก์ชันได้แล้วเรายังสามารถกำหนดเทมเพลตคลาสได้อีกด้วย รูปแบบทั่วไปของการประกาศคลาสทั่วไปแสดงไว้ที่นี่ -
template <class type> class class-name {
.
.
.
}
ที่นี่ typeคือชื่อชนิดตัวยึดตำแหน่งซึ่งจะถูกระบุเมื่อคลาสถูกสร้างอินสแตนซ์ คุณสามารถกำหนดประเภทข้อมูลทั่วไปได้มากกว่าหนึ่งประเภทโดยใช้รายการที่คั่นด้วยจุลภาค
ต่อไปนี้เป็นตัวอย่างในการกำหนด class Stack <> และใช้วิธีการทั่วไปเพื่อพุชและป๊อปองค์ประกอบจากสแต็ก -
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return true if empty.
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem) {
// append copy of passed element
elems.push_back(elem);
}
template <class T>
void Stack<T>::pop () {
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// remove last element
elems.pop_back();
}
template <class T>
T Stack<T>::top () const {
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// return copy of last element
return elems.back();
}
int main() {
try {
Stack<int> intStack; // stack of ints
Stack<string> stringStack; // stack of strings
// manipulate int stack
intStack.push(7);
cout << intStack.top() <<endl;
// manipulate string stack
stringStack.push("hello");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
} catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
7
hello
Exception: Stack<>::pop(): empty stack
พรีโปรเซสเซอร์เป็นคำสั่งซึ่งให้คำแนะนำแก่คอมไพลเลอร์ในการประมวลผลข้อมูลล่วงหน้าก่อนที่การคอมไพล์จริงจะเริ่ม
คำสั่งก่อนตัวประมวลผลทั้งหมดขึ้นต้นด้วย # และอักขระช่องว่างเท่านั้นที่อาจปรากฏก่อนคำสั่งตัวประมวลผลล่วงหน้าบนบรรทัด คำสั่งตัวประมวลผลล่วงหน้าไม่ใช่คำสั่ง C ++ ดังนั้นจึงไม่ลงท้ายด้วยอัฒภาค (;)
คุณได้เห็นไฟล์ #includeคำสั่งในตัวอย่างทั้งหมด มาโครนี้ใช้เพื่อรวมไฟล์ส่วนหัวลงในไฟล์ต้นฉบับ
มีคำสั่งพรีโปรเซสเซอร์ที่รองรับ C ++ เช่น #include, #define, #if, #else, #line และอื่น ๆ ให้เราดูคำสั่งที่สำคัญ -
#define พรีโปรเซสเซอร์
#define คำสั่งก่อนตัวประมวลผลสร้างค่าคงที่สัญลักษณ์ ค่าคงที่สัญลักษณ์เรียกว่า amacro และรูปแบบทั่วไปของคำสั่งคือ -
#define macro-name replacement-text
เมื่อบรรทัดนี้ปรากฏในไฟล์แมโครที่เกิดขึ้นในภายหลังทั้งหมดในไฟล์นั้นจะถูกแทนที่ด้วยข้อความแทนที่ก่อนที่โปรแกรมจะคอมไพล์ ตัวอย่างเช่น -
#include <iostream>
using namespace std;
#define PI 3.14159
int main () {
cout << "Value of PI :" << PI << endl;
return 0;
}
ตอนนี้ให้เราทำการประมวลผลล่วงหน้าของโค้ดนี้เพื่อดูผลลัพธ์ที่สมมติว่าเรามีไฟล์ซอร์สโค้ด ดังนั้นให้เรารวบรวมด้วยตัวเลือก -E และเปลี่ยนเส้นทางผลลัพธ์เป็น test.p ตอนนี้ถ้าคุณตรวจสอบ test.p มันจะมีข้อมูลมากมายและที่ด้านล่างคุณจะพบค่าที่ถูกแทนที่ดังนี้ -
$gcc -E test.cpp > test.p
...
int main () {
cout << "Value of PI :" << 3.14159 << endl;
return 0;
}
มาโครที่เหมือนฟังก์ชัน
คุณสามารถใช้ #define เพื่อกำหนดมาโครซึ่งจะใช้อาร์กิวเมนต์ดังนี้ -
#include <iostream>
using namespace std;
#define MIN(a,b) (((a)<(b)) ? a : b)
int main () {
int i, j;
i = 100;
j = 30;
cout <<"The minimum is " << MIN(i, j) << endl;
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
The minimum is 30
การรวบรวมตามเงื่อนไข
มีหลายคำสั่งซึ่งสามารถใช้เพื่อรวบรวมส่วนที่เลือกของซอร์สโค้ดของโปรแกรมของคุณ กระบวนการนี้เรียกว่าการคอมไพล์ตามเงื่อนไข
โครงสร้างพรีโพรเซสเซอร์แบบมีเงื่อนไขนั้นเหมือนกับโครงสร้างการเลือก 'if' พิจารณารหัสก่อนโปรเซสเซอร์ต่อไปนี้ -
#ifndef NULL
#define NULL 0
#endif
คุณสามารถรวบรวมโปรแกรมเพื่อวัตถุประสงค์ในการดีบัก คุณยังสามารถเปิดหรือปิดการดีบักโดยใช้มาโครเดียวได้ดังนี้ -
#ifdef DEBUG
cerr <<"Variable x = " << x << endl;
#endif
ซึ่งทำให้เกิดไฟล์ cerrคำสั่งที่จะคอมไพล์ในโปรแกรมหากมีการกำหนด DEBUG ค่าคงที่เชิงสัญลักษณ์ก่อนคำสั่ง #ifdef DEBUG คุณสามารถใช้ #if 0 statment เพื่อแสดงความคิดเห็นส่วนหนึ่งของโปรแกรมได้ดังนี้ -
#if 0
code prevented from compiling
#endif
ให้เราลองตัวอย่างต่อไปนี้ -
#include <iostream>
using namespace std;
#define DEBUG
#define MIN(a,b) (((a)<(b)) ? a : b)
int main () {
int i, j;
i = 100;
j = 30;
#ifdef DEBUG
cerr <<"Trace: Inside main function" << endl;
#endif
#if 0
/* This is commented part */
cout << MKSTR(HELLO C++) << endl;
#endif
cout <<"The minimum is " << MIN(i, j) << endl;
#ifdef DEBUG
cerr <<"Trace: Coming out of main function" << endl;
#endif
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
The minimum is 30
Trace: Inside main function
Trace: Coming out of main function
ตัวดำเนินการ # และ ##
ตัวดำเนินการก่อนกระบวนการ # และ ## พร้อมใช้งานใน C ++ และ ANSI / ISO C ตัวดำเนินการ # ทำให้โทเค็นข้อความทดแทนถูกแปลงเป็นสตริงที่ล้อมรอบด้วยเครื่องหมายคำพูด
พิจารณานิยามมาโครต่อไปนี้ -
#include <iostream>
using namespace std;
#define MKSTR( x ) #x
int main () {
cout << MKSTR(HELLO C++) << endl;
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
HELLO C++
ให้เราดูว่ามันทำงานอย่างไร เป็นเรื่องง่ายที่จะเข้าใจว่าตัวประมวลผลล่วงหน้า C ++ เปลี่ยนสาย -
cout << MKSTR(HELLO C++) << endl;
บรรทัดด้านบนจะเปลี่ยนเป็นบรรทัดต่อไปนี้ -
cout << "HELLO C++" << endl;
ตัวดำเนินการ ## ใช้เพื่อเชื่อมสองโทเค็นเข้าด้วยกัน นี่คือตัวอย่าง -
#define CONCAT( x, y ) x ## y
เมื่อ CONCAT ปรากฏในโปรแกรมอาร์กิวเมนต์ของมันจะเชื่อมต่อกันและใช้เพื่อแทนที่มาโคร ตัวอย่างเช่น CONCAT (HELLO, C ++) ถูกแทนที่ด้วย "HELLO C ++" ในโปรแกรมดังนี้
#include <iostream>
using namespace std;
#define concat(a, b) a ## b
int main() {
int xy = 100;
cout << concat(x, y);
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
100
ให้เราดูว่ามันทำงานอย่างไร เป็นเรื่องง่ายที่จะเข้าใจว่าตัวประมวลผลล่วงหน้า C ++ แปลง -
cout << concat(x, y);
บรรทัดด้านบนจะเปลี่ยนเป็นบรรทัดต่อไปนี้ -
cout << xy;
มาโคร C ++ ที่กำหนดไว้ล่วงหน้า
C ++ มีมาโครที่กำหนดไว้ล่วงหน้าจำนวนหนึ่งที่กล่าวถึงด้านล่าง -
ซีเนียร์ No | มาโครและคำอธิบาย |
---|---|
1 | __LINE__ ซึ่งประกอบด้วยหมายเลขบรรทัดปัจจุบันของโปรแกรมเมื่อกำลังคอมไพล์ |
2 | __FILE__ ซึ่งมีชื่อไฟล์ปัจจุบันของโปรแกรมเมื่อกำลังคอมไพล์ |
3 | __DATE__ ซึ่งประกอบด้วยสตริงของรูปแบบเดือน / วัน / ปีที่เป็นวันที่ของการแปลไฟล์ต้นฉบับเป็นรหัสวัตถุ |
4 | __TIME__ ซึ่งประกอบด้วยสตริงของ form hour: minute: second ที่เป็นเวลาที่โปรแกรมคอมไพล์ |
ให้เราดูตัวอย่างสำหรับมาโครข้างต้นทั้งหมด -
#include <iostream>
using namespace std;
int main () {
cout << "Value of __LINE__ : " << __LINE__ << endl;
cout << "Value of __FILE__ : " << __FILE__ << endl;
cout << "Value of __DATE__ : " << __DATE__ << endl;
cout << "Value of __TIME__ : " << __TIME__ << endl;
return 0;
}
หากเรารวบรวมและเรียกใช้โค้ดด้านบนสิ่งนี้จะให้ผลลัพธ์ดังต่อไปนี้ -
Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48
สัญญาณคือการขัดจังหวะที่ส่งไปยังกระบวนการโดยระบบปฏิบัติการซึ่งสามารถยุติโปรแกรมก่อนเวลาอันควร คุณสามารถสร้างอินเทอร์รัปต์ได้โดยกด Ctrl + C บนระบบ UNIX, LINUX, Mac OS X หรือ Windows
มีสัญญาณที่โปรแกรมไม่สามารถจับได้ แต่มีรายการสัญญาณต่อไปนี้ซึ่งคุณสามารถจับได้ในโปรแกรมของคุณและสามารถดำเนินการตามสัญญาณได้อย่างเหมาะสม สัญญาณเหล่านี้กำหนดไว้ในไฟล์ส่วนหัว C ++ <csignal>
ซีเนียร์ No | สัญญาณและคำอธิบาย |
---|---|
1 | SIGABRT การยุติโปรแกรมผิดปกติเช่นการโทรไปที่ abort. |
2 | SIGFPE การดำเนินการทางคณิตศาสตร์ที่ผิดพลาดเช่นการหารด้วยศูนย์หรือการดำเนินการที่ทำให้เกิดการล้น |
3 | SIGILL การตรวจจับคำสั่งที่ผิดกฎหมาย |
4 | SIGINT การรับสัญญาณเตือนแบบโต้ตอบ |
5 | SIGSEGV การเข้าถึงที่เก็บข้อมูลไม่ถูกต้อง |
6 | SIGTERM ส่งคำขอยกเลิกไปยังโปรแกรม |
สัญญาณ () ฟังก์ชั่น
ไลบรารีการจัดการสัญญาณ C ++ มีฟังก์ชัน signalเพื่อดักจับเหตุการณ์ที่ไม่คาดคิด ต่อไปนี้เป็นไวยากรณ์ของฟังก์ชัน signal () -
void (*signal (int sig, void (*func)(int)))(int);
ทำให้มันง่ายฟังก์ชันนี้ได้รับสองอาร์กิวเมนต์: อาร์กิวเมนต์แรกเป็นจำนวนเต็มซึ่งแสดงถึงหมายเลขสัญญาณและอาร์กิวเมนต์ที่สองเป็นตัวชี้ไปยังฟังก์ชันการจัดการสัญญาณ
ให้เราเขียนโปรแกรม C ++ ง่ายๆซึ่งเราจะจับสัญญาณ SIGINT โดยใช้ฟังก์ชัน signal () ไม่ว่าคุณต้องการจับสัญญาณใดในโปรแกรมของคุณคุณต้องลงทะเบียนสัญญาณนั้นโดยใช้signalและเชื่อมโยงกับเครื่องจัดการสัญญาณ ตรวจสอบตัวอย่างต่อไปนี้ -
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler( int signum ) {
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
exit(signum);
}
int main () {
// register signal SIGINT and signal handler
signal(SIGINT, signalHandler);
while(1) {
cout << "Going to sleep...." << endl;
sleep(1);
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
Going to sleep....
Going to sleep....
Going to sleep....
ตอนนี้กด Ctrl + c เพื่อขัดจังหวะโปรแกรมและคุณจะเห็นว่าโปรแกรมของคุณจะจับสัญญาณและจะออกมาโดยการพิมพ์สิ่งต่อไปนี้ -
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
ฟังก์ชัน Raise ()
คุณสามารถสร้างสัญญาณตามฟังก์ชัน raise()ซึ่งใช้หมายเลขสัญญาณจำนวนเต็มเป็นอาร์กิวเมนต์และมีไวยากรณ์ต่อไปนี้
int raise (signal sig);
ที่นี่ sigคือหมายเลขสัญญาณเพื่อส่งสัญญาณใด ๆ : SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP ต่อไปนี้เป็นตัวอย่างที่เราเพิ่มสัญญาณภายในโดยใช้ฟังก์ชัน Raise () ดังต่อไปนี้ -
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler( int signum ) {
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
exit(signum);
}
int main () {
int i = 0;
// register signal SIGINT and signal handler
signal(SIGINT, signalHandler);
while(++i) {
cout << "Going to sleep...." << endl;
if( i == 3 ) {
raise( SIGINT);
}
sleep(1);
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้โค้ดจะให้ผลลัพธ์ดังต่อไปนี้และจะออกมาโดยอัตโนมัติ -
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
มัลติเธรดเป็นรูปแบบเฉพาะของการทำงานหลายอย่างพร้อมกันและมัลติทาสกิ้งเป็นคุณลักษณะที่ช่วยให้คอมพิวเตอร์ของคุณสามารถรันโปรแกรมสองโปรแกรมขึ้นไปพร้อมกันได้ โดยทั่วไปการทำงานหลายอย่างพร้อมกันมีสองประเภท ได้แก่ แบบใช้กระบวนการและแบบใช้เธรด
การทำงานหลายอย่างพร้อมกันตามกระบวนการจะจัดการกับการทำงานของโปรแกรมพร้อมกัน การทำงานแบบมัลติทาสก์แบบใช้เธรดเกี่ยวข้องกับการทำงานพร้อมกันของชิ้นส่วนของโปรแกรมเดียวกัน
โปรแกรมมัลติเธรดประกอบด้วยสองส่วนหรือมากกว่าที่สามารถทำงานพร้อมกันได้ แต่ละส่วนของโปรแกรมดังกล่าวเรียกว่าเธรดและแต่ละเธรดกำหนดเส้นทางการดำเนินการแยกกัน
C ++ ไม่มีการสนับสนุนในตัวสำหรับแอปพลิเคชันแบบมัลติเธรด แต่ขึ้นอยู่กับระบบปฏิบัติการทั้งหมดในการจัดหาคุณลักษณะนี้
บทช่วยสอนนี้จะถือว่าคุณกำลังทำงานบน Linux OS และเรากำลังจะเขียนโปรแกรม C ++ แบบมัลติเธรดโดยใช้ POSIX POSIX Threads หรือ Pthreads ให้ API ซึ่งมีอยู่ในระบบ POSIX ที่เหมือน Unix เช่น FreeBSD, NetBSD, GNU / Linux, MacOS X และ Solaris
การสร้างเธรด
รูทีนต่อไปนี้ใช้เพื่อสร้างเธรด POSIX -
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)
ที่นี่ pthread_createสร้างเธรดใหม่และทำให้สามารถเรียกใช้งานได้ กิจวัตรนี้สามารถเรียกกี่ครั้งก็ได้จากทุกที่ภายในรหัสของคุณ นี่คือคำอธิบายของพารามิเตอร์ -
ซีเนียร์ No | พารามิเตอร์และคำอธิบาย |
---|---|
1 | thread ตัวระบุเฉพาะที่ทึบแสงสำหรับเธรดใหม่ที่ส่งคืนโดยรูทีนย่อย |
2 | attr อ็อบเจ็กต์แอ็ตทริบิวต์ทึบแสงที่อาจใช้เพื่อตั้งค่าแอ็ตทริบิวต์เธรด คุณสามารถระบุอ็อบเจ็กต์แอ็ตทริบิวต์เธรดหรือค่า NULL สำหรับค่าดีฟอลต์ |
3 | start_routine รูทีน C ++ ที่เธรดจะดำเนินการเมื่อสร้างขึ้น |
4 | arg อาร์กิวเมนต์เดียวที่อาจถูกส่งไปยัง start_routine จะต้องส่งผ่านโดยการอ้างอิงเป็นตัวชี้ประเภทโมฆะ อาจใช้ NULL หากไม่มีการโต้แย้ง |
จำนวนเธรดสูงสุดที่กระบวนการอาจสร้างขึ้นนั้นขึ้นอยู่กับการนำไปใช้งาน เมื่อสร้างแล้วเธรดจะเป็นแบบเดียวกันและอาจสร้างเธรดอื่น ๆ ไม่มีลำดับชั้นโดยนัยหรือการพึ่งพาระหว่างเธรด
การยุติเธรด
มีกิจวัตรต่อไปนี้ที่เราใช้เพื่อยุติเธรด POSIX -
#include <pthread.h>
pthread_exit (status)
ที่นี่ pthread_exitใช้เพื่อออกจากเธรดอย่างชัดเจน โดยทั่วไปรูทีน pthread_exit () จะถูกเรียกหลังจากเธรดทำงานเสร็จสิ้นและไม่จำเป็นต้องมีอยู่อีกต่อไป
หาก main () เสร็จสิ้นก่อนเธรดที่สร้างขึ้นและออกด้วย pthread_exit () เธรดอื่นจะดำเนินการต่อ มิฉะนั้นจะถูกยกเลิกโดยอัตโนมัติเมื่อ main () เสร็จสิ้น
Example
โค้ดตัวอย่างง่ายๆนี้สร้าง 5 เธรดด้วยรูทีน pthread_create () แต่ละเธรดจะพิมพ์ข้อความ "Hello World!" แล้วยุติด้วยการเรียกไปที่ pthread_exit ()
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
cout << "Hello World! Thread ID, " << tid << endl;
pthread_exit(NULL);
}
int main () {
pthread_t threads[NUM_THREADS];
int rc;
int i;
for( i = 0; i < NUM_THREADS; i++ ) {
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
pthread_exit(NULL);
}
คอมไพล์โปรแกรมต่อไปนี้โดยใช้ไลบรารี -lpthread ดังนี้ -
$gcc test.cpp -lpthread
ตอนนี้รันโปรแกรมของคุณซึ่งให้ผลลัพธ์ต่อไปนี้ -
main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4
การส่งผ่านอาร์กิวเมนต์ไปยังเธรด
ตัวอย่างนี้แสดงวิธีการส่งผ่านหลายอาร์กิวเมนต์ผ่านโครงสร้าง คุณสามารถส่งผ่านประเภทข้อมูลใดก็ได้ในการเรียกกลับเธรดเนื่องจากชี้ว่าเป็นโมฆะตามที่อธิบายไว้ในตัวอย่างต่อไปนี้ -
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
struct thread_data {
int thread_id;
char *message;
};
void *PrintHello(void *threadarg) {
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;
cout << "Thread ID : " << my_data->thread_id ;
cout << " Message : " << my_data->message << endl;
pthread_exit(NULL);
}
int main () {
pthread_t threads[NUM_THREADS];
struct thread_data td[NUM_THREADS];
int rc;
int i;
for( i = 0; i < NUM_THREADS; i++ ) {
cout <<"main() : creating thread, " << i << endl;
td[i].thread_id = i;
td[i].message = "This is message";
rc = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]);
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
pthread_exit(NULL);
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message
การเข้าร่วมและการแยกเธรด
มีสองกิจวัตรต่อไปนี้ที่เราสามารถใช้เพื่อเข้าร่วมหรือแยกเธรด -
pthread_join (threadid, status)
pthread_detach (threadid)
รูทีนย่อย pthread_join () บล็อกเธรดการเรียกจนกว่าเธรด 'threadid' ที่ระบุจะสิ้นสุดลง เมื่อเธรดถูกสร้างขึ้นหนึ่งในแอ็ตทริบิวต์จะกำหนดว่าจะเข้าร่วมได้หรือแยกออก เฉพาะเธรดที่สร้างขึ้นโดยสามารถเข้าร่วมได้ หากเธรดถูกสร้างขึ้นแบบแยกออกจากกันจะไม่สามารถเข้าร่วมได้
ตัวอย่างนี้สาธิตวิธีการรอให้เธรดเสร็จสมบูรณ์โดยใช้รูทีนการรวม Pthread
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
using namespace std;
#define NUM_THREADS 5
void *wait(void *t) {
int i;
long tid;
tid = (long)t;
sleep(1);
cout << "Sleeping in thread " << endl;
cout << "Thread with id : " << tid << " ...exiting " << endl;
pthread_exit(NULL);
}
int main () {
int rc;
int i;
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
void *status;
// Initialize and set thread joinable
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for( i = 0; i < NUM_THREADS; i++ ) {
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], &attr, wait, (void *)i );
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
// free attribute and wait for the other threads
pthread_attr_destroy(&attr);
for( i = 0; i < NUM_THREADS; i++ ) {
rc = pthread_join(threads[i], &status);
if (rc) {
cout << "Error:unable to join," << rc << endl;
exit(-1);
}
cout << "Main: completed thread id :" << i ;
cout << " exiting with status :" << status << endl;
}
cout << "Main: program exiting." << endl;
pthread_exit(NULL);
}
เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -
main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0 exiting with status :0
Main: completed thread id :1 exiting with status :0
Main: completed thread id :2 exiting with status :0
Main: completed thread id :3 exiting with status :0
Main: completed thread id :4 exiting with status :0
Main: program exiting.
CGI คืออะไร?
Common Gateway Interface หรือ CGI เป็นชุดของมาตรฐานที่กำหนดวิธีแลกเปลี่ยนข้อมูลระหว่างเว็บเซิร์ฟเวอร์และสคริปต์ที่กำหนดเอง
ปัจจุบันข้อกำหนด CGI ได้รับการดูแลโดย NCSA และ NCSA กำหนด CGI ดังนี้ -
Common Gateway Interface หรือ CGI เป็นมาตรฐานสำหรับโปรแกรมเกตเวย์ภายนอกเพื่อเชื่อมต่อกับเซิร์ฟเวอร์ข้อมูลเช่นเซิร์ฟเวอร์ HTTP
เวอร์ชันปัจจุบันคือ CGI / 1.1 และ CGI / 1.2 อยู่ระหว่างการดำเนินการ
การท่องเว็บ
เพื่อทำความเข้าใจแนวคิดของ CGI มาดูกันว่าจะเกิดอะไรขึ้นเมื่อเราคลิกไฮเปอร์ลิงก์เพื่อเรียกดูหน้าเว็บหรือ URL
เบราว์เซอร์ของคุณติดต่อกับเว็บเซิร์ฟเวอร์ HTTP และต้องการ URL เช่น ชื่อไฟล์.
เว็บเซิร์ฟเวอร์จะแยกวิเคราะห์ URL และจะค้นหาชื่อไฟล์ หากพบไฟล์ที่ร้องขอเว็บเซิร์ฟเวอร์จะส่งไฟล์นั้นกลับไปที่เบราว์เซอร์มิฉะนั้นจะส่งข้อความแสดงข้อผิดพลาดที่ระบุว่าคุณร้องขอไฟล์ผิด
เว็บเบราว์เซอร์รับการตอบสนองจากเว็บเซิร์ฟเวอร์และแสดงไฟล์ที่ได้รับหรือข้อความแสดงข้อผิดพลาดตามการตอบกลับที่ได้รับ
อย่างไรก็ตามเป็นไปได้ที่จะตั้งค่าเซิร์ฟเวอร์ HTTP ในลักษณะที่เมื่อใดก็ตามที่มีการร้องขอไฟล์ในไดเร็กทอรีหนึ่งไฟล์นั้นจะไม่ถูกส่งกลับ แทนที่จะดำเนินการเป็นโปรแกรมและผลลัพธ์ที่ได้จากโปรแกรมจะถูกส่งกลับไปยังเบราว์เซอร์ของคุณเพื่อแสดง
Common Gateway Interface (CGI) เป็นโปรโตคอลมาตรฐานสำหรับการเปิดใช้งานแอปพลิเคชัน (เรียกว่าโปรแกรม CGI หรือสคริปต์ CGI) เพื่อโต้ตอบกับเว็บเซิร์ฟเวอร์และกับไคลเอ็นต์ โปรแกรม CGI เหล่านี้สามารถเขียนด้วย Python, PERL, Shell, C หรือ C ++ เป็นต้น
แผนภาพสถาปัตยกรรม CGI
โปรแกรมง่ายๆต่อไปนี้แสดงสถาปัตยกรรมอย่างง่ายของ CGI -
การกำหนดค่าเว็บเซิร์ฟเวอร์
ก่อนที่คุณจะดำเนินการเขียนโปรแกรม CGI ตรวจสอบให้แน่ใจว่าเว็บเซิร์ฟเวอร์ของคุณรองรับ CGI และได้รับการกำหนดค่าให้จัดการกับโปรแกรม CGI โปรแกรม CGI ทั้งหมดที่จะเรียกใช้โดยเซิร์ฟเวอร์ HTTP จะถูกเก็บไว้ในไดเร็กทอรีที่กำหนดค่าไว้ล่วงหน้า ไดเร็กทอรีนี้เรียกว่าไดเร็กทอรี CGI และตามแบบแผนจะถูกตั้งชื่อเป็น / var / www / cgi-bin ตามแบบแผนไฟล์ CGI จะมีนามสกุลเป็น.cgiแม้ว่าจะเป็นไฟล์ปฏิบัติการ C ++
โดยค่าเริ่มต้น Apache Web Server ถูกกำหนดค่าให้รันโปรแกรม CGI ใน / var / www / cgi-bin หากคุณต้องการระบุไดเร็กทอรีอื่นเพื่อรันสคริปต์ CGI ของคุณคุณสามารถแก้ไขส่วนต่อไปนี้ในไฟล์ httpd.conf -
<Directory "/var/www/cgi-bin">
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/cgi-bin">
Options All
</Directory>
ที่นี่ฉันคิดว่าคุณมี Web Server และทำงานได้สำเร็จและคุณสามารถเรียกใช้โปรแกรม CGI อื่น ๆ เช่น Perl หรือ Shell เป็นต้น
โปรแกรม CGI ครั้งแรก
พิจารณาเนื้อหาโปรแกรม C ++ ต่อไปนี้ -
#include <iostream>
using namespace std;
int main () {
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Hello World - First CGI Program</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<h2>Hello World! This is my first CGI program</h2>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
รวบรวมโค้ดด้านบนและตั้งชื่อไฟล์ปฏิบัติการเป็น cplusplus.cgi ไฟล์นี้ถูกเก็บไว้ในไดเร็กทอรี / var / www / cgi-bin และมีเนื้อหาดังต่อไปนี้ ก่อนที่จะรันโปรแกรม CGI ของคุณตรวจสอบให้แน่ใจว่าคุณได้เปลี่ยนโหมดของไฟล์โดยใช้ไฟล์chmod 755 cplusplus.cgi คำสั่ง UNIX เพื่อทำให้ไฟล์เรียกทำงานได้
โปรแกรม CGI แรกของฉัน
โปรแกรม C ++ ข้างต้นเป็นโปรแกรมง่ายๆที่เขียนผลลัพธ์บนหน้าจอไฟล์ STDOUT เช่น มีคุณสมบัติที่สำคัญและพิเศษอย่างหนึ่งซึ่งก็คือการพิมพ์บรรทัดแรกContent-type:text/html\r\n\r\n. บรรทัดนี้ถูกส่งกลับไปยังเบราว์เซอร์และระบุประเภทเนื้อหาที่จะแสดงบนหน้าจอเบราว์เซอร์ ตอนนี้คุณต้องเข้าใจแนวคิดพื้นฐานของ CGI แล้วและคุณสามารถเขียนโปรแกรม CGI ที่ซับซ้อนได้โดยใช้ Python โปรแกรม C ++ CGI สามารถโต้ตอบกับระบบภายนอกอื่น ๆ เช่น RDBMS เพื่อแลกเปลี่ยนข้อมูล
ส่วนหัว HTTP
เส้น Content-type:text/html\r\n\r\nเป็นส่วนหนึ่งของส่วนหัว HTTP ซึ่งส่งไปยังเบราว์เซอร์เพื่อทำความเข้าใจเนื้อหา ส่วนหัว HTTP ทั้งหมดจะอยู่ในรูปแบบต่อไปนี้ -
HTTP Field Name: Field Content
For Example
Content-type: text/html\r\n\r\n
มีส่วนหัว HTTP ที่สำคัญอื่น ๆ อีกเล็กน้อยซึ่งคุณจะใช้บ่อยในการเขียนโปรแกรม CGI ของคุณ
ซีเนียร์ No | ส่วนหัวและคำอธิบาย |
---|---|
1 | Content-type: สตริง MIME ที่กำหนดรูปแบบของไฟล์ที่ส่งคืน ตัวอย่างคือ Content-type: text / html |
2 | Expires: Date วันที่ข้อมูลไม่ถูกต้อง เบราว์เซอร์ควรใช้สิ่งนี้เพื่อตัดสินใจว่าจะต้องรีเฟรชหน้าเมื่อใด สตริงวันที่ที่ถูกต้องควรอยู่ในรูปแบบ 01 มกราคม 1998 12:00:00 GMT |
3 | Location: URL URL ที่ควรส่งคืนแทน URL ที่ร้องขอ คุณสามารถใช้ไฟล์นี้เพื่อเปลี่ยนเส้นทางคำขอไปยังไฟล์ใดก็ได้ |
4 | Last-modified: Date วันที่แก้ไขทรัพยากรครั้งล่าสุด |
5 | Content-length: N ความยาวเป็นไบต์ของข้อมูลที่ส่งกลับ เบราว์เซอร์ใช้ค่านี้เพื่อรายงานเวลาดาวน์โหลดโดยประมาณสำหรับไฟล์ |
6 | Set-Cookie: String ชุดคุกกี้ผ่านสตริง |
ตัวแปรสภาพแวดล้อม CGI
โปรแกรม CGI ทั้งหมดจะสามารถเข้าถึงตัวแปรสภาพแวดล้อมต่อไปนี้ ตัวแปรเหล่านี้มีบทบาทสำคัญในขณะที่เขียนโปรแกรม CGI
ซีเนียร์ No | ชื่อตัวแปรและคำอธิบาย |
---|---|
1 | CONTENT_TYPE ชนิดข้อมูลของเนื้อหาที่ใช้เมื่อไคลเอ็นต์ส่งเนื้อหาที่แนบไปยังเซิร์ฟเวอร์ เช่นอัพโหลดไฟล์เป็นต้น |
2 | CONTENT_LENGTH ความยาวของข้อมูลแบบสอบถามที่มีให้สำหรับคำขอ POST เท่านั้น |
3 | HTTP_COOKIE ส่งคืนชุดคุกกี้ในรูปแบบของคู่คีย์และค่า |
4 | HTTP_USER_AGENT ฟิลด์ User-Agent request-header มีข้อมูลเกี่ยวกับตัวแทนผู้ใช้ที่มาจากคำร้องขอ เป็นชื่อของเว็บเบราว์เซอร์ |
5 | PATH_INFO เส้นทางสำหรับสคริปต์ CGI |
6 | QUERY_STRING ข้อมูลที่เข้ารหัส URL ที่ส่งมาพร้อมกับการร้องขอเมธอด GET |
7 | REMOTE_ADDR ที่อยู่ IP ของโฮสต์ระยะไกลที่ทำการร้องขอ สิ่งนี้มีประโยชน์สำหรับการบันทึกหรือเพื่อวัตถุประสงค์ในการตรวจสอบสิทธิ์ |
8 | REMOTE_HOST ชื่อแบบเต็มของโฮสต์ที่ทำการร้องขอ หากไม่มีข้อมูลนี้คุณสามารถใช้ REMOTE_ADDR เพื่อรับที่อยู่ IR ได้ |
9 | REQUEST_METHOD วิธีการที่ใช้ในการร้องขอ วิธีการทั่วไปคือ GET และ POST |
10 | SCRIPT_FILENAME เส้นทางแบบเต็มไปยังสคริปต์ CGI |
11 | SCRIPT_NAME ชื่อของสคริปต์ CGI |
12 | SERVER_NAME ชื่อโฮสต์หรือที่อยู่ IP ของเซิร์ฟเวอร์ |
13 | SERVER_SOFTWARE ชื่อและเวอร์ชันของซอฟต์แวร์ที่เซิร์ฟเวอร์กำลังเรียกใช้ |
นี่คือโปรแกรม CGI ขนาดเล็กเพื่อแสดงรายการตัวแปร CGI ทั้งหมด
#include <iostream>
#include <stdlib.h>
using namespace std;
const string ENV[ 24 ] = {
"COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
"HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",
"HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",
"HTTP_HOST", "HTTP_USER_AGENT", "PATH",
"QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
"REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
"SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",
"SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",
"SERVER_SIGNATURE","SERVER_SOFTWARE" };
int main () {
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>CGI Environment Variables</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table border = \"0\" cellspacing = \"2\">";
for ( int i = 0; i < 24; i++ ) {
cout << "<tr><td>" << ENV[ i ] << "</td><td>";
// attempt to retrieve value of environment variable
char *value = getenv( ENV[ i ].c_str() );
if ( value != 0 ) {
cout << value;
} else {
cout << "Environment variable does not exist.";
}
cout << "</td></tr>\n";
}
cout << "</table><\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
C ++ CGI ไลบรารี
สำหรับตัวอย่างจริงคุณจะต้องดำเนินการหลายอย่างโดยโปรแกรม CGI ของคุณ มีไลบรารี CGI ที่เขียนขึ้นสำหรับโปรแกรม C ++ ซึ่งคุณสามารถดาวน์โหลดได้จากftp://ftp.gnu.org/gnu/cgicc/และทำตามขั้นตอนเพื่อติดตั้งไลบรารี -
$tar xzf cgicc-X.X.X.tar.gz
$cd cgicc-X.X.X/ $./configure --prefix=/usr
$make $make install
คุณสามารถตรวจสอบเอกสารที่เกี่ยวข้องสามารถดูได้ที่'C ++ CGI Lib เอกสาร
รับและโพสต์วิธีการ
คุณต้องเจอสถานการณ์ต่างๆมากมายเมื่อคุณต้องส่งข้อมูลบางอย่างจากเบราว์เซอร์ของคุณไปยังเว็บเซิร์ฟเวอร์และท้ายที่สุดไปยังโปรแกรม CGI ของคุณ เบราว์เซอร์ส่วนใหญ่ใช้สองวิธีในการส่งข้อมูลนี้ไปยังเว็บเซิร์ฟเวอร์ วิธีการเหล่านี้คือ GET Method และ POST Method
การส่งผ่านข้อมูลโดยใช้วิธี GET
เมธอด GET จะส่งข้อมูลผู้ใช้ที่เข้ารหัสต่อท้ายคำขอเพจ หน้าและข้อมูลที่เข้ารหัสจะถูกคั่นด้วยเครื่องหมาย? ตัวละครดังนี้ -
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
เมธอด GET เป็นวิธีการเริ่มต้นในการส่งผ่านข้อมูลจากเบราว์เซอร์ไปยังเว็บเซิร์ฟเวอร์และจะสร้างสตริงแบบยาวที่ปรากฏในกล่อง Location: ของเบราว์เซอร์ของคุณ อย่าใช้เมธอด GET หากคุณมีรหัสผ่านหรือข้อมูลที่ละเอียดอ่อนอื่น ๆ เพื่อส่งผ่านไปยังเซิร์ฟเวอร์ เมธอด GET มีข้อ จำกัด ด้านขนาดและคุณสามารถส่งอักขระได้ไม่เกิน 1024 ตัวในสตริงคำขอ
เมื่อใช้เมธอด GET ข้อมูลจะถูกส่งผ่านโดยใช้ส่วนหัว QUERY_STRING http และจะสามารถเข้าถึงได้ในโปรแกรม CGI ของคุณผ่านตัวแปรสภาพแวดล้อม QUERY_STRING
คุณสามารถส่งผ่านข้อมูลได้เพียงแค่เชื่อมคู่คีย์และค่าเข้ากับ URL ใด ๆ หรือคุณสามารถใช้แท็ก HTML <FORM> เพื่อส่งผ่านข้อมูลโดยใช้เมธอด GET
ตัวอย่าง URL แบบง่าย: รับวิธีการ
นี่คือ URL ง่ายๆซึ่งจะส่งผ่านค่าสองค่าไปยังโปรแกรม hello_get.py โดยใช้เมธอด GET
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALIด้านล่างนี้คือโปรแกรมในการสร้าง cpp_get.cgiโปรแกรม CGI เพื่อจัดการอินพุตที่กำหนดโดยเว็บเบราว์เซอร์ เราจะใช้ไลบรารี C ++ CGI ซึ่งทำให้เข้าถึงข้อมูลที่ส่งผ่านได้ง่ายมาก -
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Using GET and POST Methods</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("first_name");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "First name: " << **fi << endl;
} else {
cout << "No text entered for first name" << endl;
}
cout << "<br/>\n";
fi = formData.getElement("last_name");
if( !fi->isEmpty() &&fi != (*formData).end()) {
cout << "Last name: " << **fi << endl;
} else {
cout << "No text entered for last name" << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
ตอนนี้รวบรวมโปรแกรมข้างต้นดังนี้ -
$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc
สร้าง cpp_get.cgi และใส่ไว้ในไดเรกทอรี CGI ของคุณและพยายามเข้าถึงโดยใช้ลิงค์ต่อไปนี้ -
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALIสิ่งนี้จะสร้างผลลัพธ์ต่อไปนี้ -
First name: ZARA
Last name: ALI
ตัวอย่างแบบฟอร์มอย่างง่าย: GET Method
นี่คือตัวอย่างง่ายๆที่ส่งผ่านค่าสองค่าโดยใช้รูปแบบ HTML และปุ่มส่ง เราจะใช้สคริปต์ CGI เดียวกัน cpp_get.cgi เพื่อจัดการอินพุตนี้
<form action = "/cgi-bin/cpp_get.cgi" method = "get">
First Name: <input type = "text" name = "first_name"> <br />
Last Name: <input type = "text" name = "last_name" />
<input type = "submit" value = "Submit" />
</form>
นี่คือผลลัพธ์จริงของแบบฟอร์มด้านบน คุณป้อนชื่อและนามสกุลจากนั้นคลิกปุ่มส่งเพื่อดูผลลัพธ์
การส่งข้อมูลโดยใช้วิธี POST
วิธีการส่งข้อมูลไปยังโปรแกรม CGI ที่น่าเชื่อถือกว่าโดยทั่วไปคือวิธีการโพสต์ ข้อมูลนี้จะบรรจุข้อมูลในลักษณะเดียวกับเมธอด GET แต่แทนที่จะส่งเป็นสตริงข้อความหลังจาก a? ใน URL จะส่งเป็นข้อความแยกต่างหาก ข้อความนี้มาในสคริปต์ CGI ในรูปแบบของอินพุตมาตรฐาน
โปรแกรม cpp_get.cgi เดียวกันจะจัดการเมธอด POST เช่นกัน ให้เรายกตัวอย่างเช่นเดียวกับด้านบนซึ่งส่งผ่านค่าสองค่าโดยใช้ HTML FORM และปุ่มส่ง แต่คราวนี้ใช้วิธี POST ดังนี้ -
<form action = "/cgi-bin/cpp_get.cgi" method = "post">
First Name: <input type = "text" name = "first_name"><br />
Last Name: <input type = "text" name = "last_name" />
<input type = "submit" value = "Submit" />
</form>
นี่คือผลลัพธ์จริงของแบบฟอร์มด้านบน คุณป้อนชื่อและนามสกุลจากนั้นคลิกปุ่มส่งเพื่อดูผลลัพธ์
การส่งข้อมูลช่องทำเครื่องหมายไปยังโปรแกรม CGI
ช่องทำเครื่องหมายถูกใช้เมื่อจำเป็นต้องเลือกมากกว่าหนึ่งตัวเลือก
นี่คือตัวอย่างโค้ด HTML สำหรับฟอร์มที่มีช่องทำเครื่องหมายสองช่อง -
<form action = "/cgi-bin/cpp_checkbox.cgi" method = "POST" target = "_blank">
<input type = "checkbox" name = "maths" value = "on" /> Maths
<input type = "checkbox" name = "physics" value = "on" /> Physics
<input type = "submit" value = "Select Subject" />
</form>
ผลลัพธ์ของรหัสนี้เป็นรูปแบบต่อไปนี้ -
ด้านล่างนี้คือโปรแกรม C ++ ซึ่งจะสร้างสคริปต์ cpp_checkbox.cgi เพื่อจัดการอินพุตที่เว็บเบราว์เซอร์กำหนดผ่านปุ่มช่องทำเครื่องหมาย
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc formData;
bool maths_flag, physics_flag;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Checkbox Data to CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
maths_flag = formData.queryCheckbox("maths");
if( maths_flag ) {
cout << "Maths Flag: ON " << endl;
} else {
cout << "Maths Flag: OFF " << endl;
}
cout << "<br/>\n";
physics_flag = formData.queryCheckbox("physics");
if( physics_flag ) {
cout << "Physics Flag: ON " << endl;
} else {
cout << "Physics Flag: OFF " << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
การส่งผ่านข้อมูลปุ่มตัวเลือกไปยังโปรแกรม CGI
ปุ่มวิทยุจะใช้เมื่อต้องเลือกเพียงตัวเลือกเดียว
นี่คือตัวอย่างโค้ด HTML สำหรับแบบฟอร์มที่มีปุ่มตัวเลือกสองปุ่ม -
<form action = "/cgi-bin/cpp_radiobutton.cgi" method = "post" target = "_blank">
<input type = "radio" name = "subject" value = "maths" checked = "checked"/> Maths
<input type = "radio" name = "subject" value = "physics" /> Physics
<input type = "submit" value = "Select Subject" />
</form>
ผลลัพธ์ของรหัสนี้เป็นรูปแบบต่อไปนี้ -
ด้านล่างนี้คือโปรแกรม C ++ ซึ่งจะสร้างสคริปต์ cpp_radiobutton.cgi เพื่อจัดการอินพุตที่เว็บเบราว์เซอร์กำหนดผ่านปุ่มตัวเลือก
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Radio Button Data to CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("subject");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "Radio box selected: " << **fi << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
การส่งผ่านข้อมูลพื้นที่ข้อความไปยังโปรแกรม CGI
องค์ประกอบ TEXTAREA ถูกใช้เมื่อต้องส่งข้อความหลายบรรทัดไปยังโปรแกรม CGI
นี่คือตัวอย่างโค้ด HTML สำหรับแบบฟอร์มที่มีกล่อง TEXTAREA -
<form action = "/cgi-bin/cpp_textarea.cgi" method = "post" target = "_blank">
<textarea name = "textcontent" cols = "40" rows = "4">
Type your text here...
</textarea>
<input type = "submit" value = "Submit" />
</form>
ผลลัพธ์ของรหัสนี้เป็นรูปแบบต่อไปนี้ -
ด้านล่างนี้คือโปรแกรม C ++ ซึ่งจะสร้างสคริปต์ cpp_textarea.cgi เพื่อจัดการอินพุตที่เว็บเบราว์เซอร์กำหนดผ่านพื้นที่ข้อความ
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Text Area Data to CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("textcontent");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "Text Content: " << **fi << endl;
} else {
cout << "No text entered" << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
การส่งผ่านข้อมูลแบบหล่นลงไปยังโปรแกรม CGI
Drop down Box ใช้เมื่อเรามีตัวเลือกมากมาย แต่จะเลือกเพียงหนึ่งหรือสองตัวเท่านั้น
นี่คือตัวอย่างโค้ด HTML สำหรับแบบฟอร์มที่มีช่องแบบเลื่อนลง -
<form action = "/cgi-bin/cpp_dropdown.cgi" method = "post" target = "_blank">
<select name = "dropdown">
<option value = "Maths" selected>Maths</option>
<option value = "Physics">Physics</option>
</select>
<input type = "submit" value = "Submit"/>
</form>
ผลลัพธ์ของรหัสนี้เป็นรูปแบบต่อไปนี้ -
ด้านล่างนี้คือโปรแกรม C ++ ซึ่งจะสร้างสคริปต์ cpp_dropdown.cgi เพื่อจัดการอินพุตที่เว็บเบราว์เซอร์มอบให้ผ่านช่องแบบเลื่อนลง
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Drop Down Box Data to CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
form_iterator fi = formData.getElement("dropdown");
if( !fi->isEmpty() && fi != (*formData).end()) {
cout << "Value Selected: " << **fi << endl;
}
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
การใช้คุกกี้ใน CGI
โปรโตคอล HTTP เป็นโปรโตคอลไร้สัญชาติ แต่สำหรับเว็บไซต์เชิงพาณิชย์จำเป็นต้องรักษาข้อมูลเซสชันระหว่างหน้าต่างๆ ตัวอย่างเช่นการลงทะเบียนผู้ใช้หนึ่งสิ้นสุดลงหลังจากเสร็จสิ้นหลายหน้า แต่จะรักษาข้อมูลเซสชันของผู้ใช้ในหน้าเว็บทั้งหมดได้อย่างไร
ในหลาย ๆ สถานการณ์การใช้คุกกี้เป็นวิธีที่มีประสิทธิภาพที่สุดในการจดจำและติดตามการตั้งค่าการซื้อค่าคอมมิชชั่นและข้อมูลอื่น ๆ ที่จำเป็นสำหรับประสบการณ์ของผู้เยี่ยมชมหรือสถิติไซต์ที่ดีขึ้น
มันทำงานอย่างไร
เซิร์ฟเวอร์ของคุณส่งข้อมูลบางส่วนไปยังเบราว์เซอร์ของผู้เยี่ยมชมในรูปแบบของคุกกี้ เบราว์เซอร์อาจยอมรับคุกกี้ หากเป็นเช่นนั้นระบบจะจัดเก็บเป็นบันทึกข้อความธรรมดาในฮาร์ดไดรฟ์ของผู้เยี่ยมชม ตอนนี้เมื่อผู้เยี่ยมชมเข้ามาที่หน้าอื่นในไซต์ของคุณคุกกี้จะพร้อมสำหรับการเรียกคืน เมื่อดึงข้อมูลเซิร์ฟเวอร์ของคุณจะรู้ / จำสิ่งที่เก็บไว้
คุกกี้คือบันทึกข้อมูลข้อความธรรมดาของฟิลด์ความยาวตัวแปร 5 ช่อง -
Expires- แสดงวันที่คุกกี้จะหมดอายุ หากว่างเปล่าคุกกี้จะหมดอายุเมื่อผู้เยี่ยมชมออกจากเบราว์เซอร์
Domain - แสดงชื่อโดเมนของไซต์ของคุณ
Path- แสดงเส้นทางไปยังไดเรกทอรีหรือหน้าเว็บที่ตั้งค่าคุกกี้ ซึ่งอาจว่างเปล่าหากคุณต้องการดึงคุกกี้จากไดเร็กทอรีหรือเพจใด ๆ
Secure- หากช่องนี้มีคำว่า "ปลอดภัย" คุกกี้จะถูกเรียกคืนด้วยเซิร์ฟเวอร์ที่ปลอดภัยเท่านั้น หากฟิลด์นี้ว่างแสดงว่าไม่มีข้อ จำกัด ดังกล่าว
Name = Value - คุกกี้ถูกตั้งค่าและเรียกดูในรูปแบบของคู่คีย์และค่า
การตั้งค่าคุกกี้
การส่งคุกกี้ไปยังเบราว์เซอร์นั้นง่ายมาก คุกกี้เหล่านี้จะถูกส่งไปพร้อมกับ HTTP Header ก่อนที่จะมีการยื่นประเภทเนื้อหา สมมติว่าคุณต้องการตั้งค่า UserID และรหัสผ่านเป็นคุกกี้ ดังนั้นการตั้งค่าคุกกี้จะทำได้ดังนี้
#include <iostream>
using namespace std;
int main () {
cout << "Set-Cookie:UserID = XYZ;\r\n";
cout << "Set-Cookie:Password = XYZ123;\r\n";
cout << "Set-Cookie:Domain = www.tutorialspoint.com;\r\n";
cout << "Set-Cookie:Path = /perl;\n";
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Cookies in CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "Setting cookies" << endl;
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
จากตัวอย่างนี้คุณต้องเข้าใจวิธีตั้งค่าคุกกี้ เราใช้Set-Cookie HTTP header เพื่อตั้งค่าคุกกี้
ที่นี่เป็นทางเลือกในการตั้งค่าแอตทริบิวต์คุกกี้เช่น Expires, Domain และ Path เป็นที่น่าสังเกตว่าคุกกี้ถูกตั้งค่าก่อนที่จะส่งสายเวทย์มนตร์"Content-type:text/html\r\n\r\n.
รวบรวมโปรแกรมด้านบนเพื่อสร้าง setcookies.cgi และพยายามตั้งค่าคุกกี้โดยใช้ลิงค์ต่อไปนี้ มันจะตั้งค่าคุกกี้สี่ตัวที่คอมพิวเตอร์ของคุณ -
/cgi-bin/setcookies.cgi
การดึงคุกกี้
เรียกดูคุกกี้ที่ตั้งไว้ทั้งหมดได้อย่างง่ายดาย คุกกี้จะถูกเก็บไว้ใน HTTP_COOKIE ตัวแปรสภาพแวดล้อม CGI และจะมีรูปแบบต่อไปนี้
key1 = value1; key2 = value2; key3 = value3....
นี่คือตัวอย่างวิธีการดึงข้อมูลคุกกี้
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc cgi;
const_cookie_iterator cci;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Cookies in CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table border = \"0\" cellspacing = \"2\">";
// get environment variables
const CgiEnvironment& env = cgi.getEnvironment();
for( cci = env.getCookieList().begin();
cci != env.getCookieList().end();
++cci ) {
cout << "<tr><td>" << cci->getName() << "</td><td>";
cout << cci->getValue();
cout << "</td></tr>\n";
}
cout << "</table><\n";
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
ตอนนี้รวบรวมโปรแกรมด้านบนเพื่อสร้าง getcookies.cgi และพยายามรับรายการคุกกี้ทั้งหมดที่มีอยู่ในคอมพิวเตอร์ของคุณ -
/cgi-bin/getcookies.cgi
สิ่งนี้จะสร้างรายการคุกกี้ทั้งสี่ชุดในส่วนก่อนหน้าและคุกกี้อื่น ๆ ทั้งหมดที่ตั้งไว้ในคอมพิวเตอร์ของคุณ -
UserID XYZ
Password XYZ123
Domain www.tutorialspoint.com
Path /perl
ตัวอย่างการอัปโหลดไฟล์
ในการอัปโหลดไฟล์รูปแบบ HTML ต้องมีแอตทริบิวต์ enctype ตั้งค่าเป็น multipart/form-data. แท็กอินพุตที่มีประเภทไฟล์จะสร้างปุ่ม "เรียกดู"
<html>
<body>
<form enctype = "multipart/form-data" action = "/cgi-bin/cpp_uploadfile.cgi"
method = "post">
<p>File: <input type = "file" name = "userfile" /></p>
<p><input type = "submit" value = "Upload" /></p>
</form>
</body>
</html>
ผลลัพธ์ของรหัสนี้เป็นรูปแบบต่อไปนี้ -
Note- ตัวอย่างด้านบนถูกปิดใช้งานโดยเจตนาเพื่อหยุดไม่ให้ผู้อื่นอัปโหลดไฟล์บนเซิร์ฟเวอร์ของเรา แต่คุณสามารถลองใช้โค้ดด้านบนกับเซิร์ฟเวอร์ของคุณได้
นี่คือสคริปต์ cpp_uploadfile.cpp เพื่อจัดการการอัปโหลดไฟล์ -
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc cgi;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>File Upload in CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
// get list of files to be uploaded
const_file_iterator file = cgi.getFile("userfile");
if(file != cgi.getFiles().end()) {
// send data type at cout.
cout << HTTPContentHeader(file->getDataType());
// write content at cout.
file->writeToStream(cout);
}
cout << "<File uploaded successfully>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
ตัวอย่างข้างต้นใช้สำหรับการเขียนเนื้อหาที่ cout สตรีม แต่คุณสามารถเปิดสตรีมไฟล์ของคุณและบันทึกเนื้อหาของไฟล์ที่อัปโหลดในไฟล์ในตำแหน่งที่ต้องการ
หวังว่าคุณจะสนุกกับบทช่วยสอนนี้ ถ้าใช่โปรดส่งความคิดเห็นของคุณถึงเรา