การสร้างอาร์เรย์ไดนามิกสองมิติในค อาร์เรย์ไดนามิกสองมิติ

โดยทั่วไป จำนวนหน่วยความจำที่จำเป็นสำหรับตัวแปรเฉพาะจะถูกระบุก่อนกระบวนการคอมไพล์โดยการประกาศตัวแปรนั้น หากจำเป็นต้องสร้างตัวแปรโดยไม่ทราบขนาดล่วงหน้า ระบบจะใช้หน่วยความจำแบบไดนามิก การจอง และ การปลดปล่อย ปัญหาหน่วยความจำในโปรแกรม C++ สามารถเกิดขึ้นได้ตลอดเวลา มีการดำเนินการ การกระจาย หน่วยความจำได้สองวิธี:

  • โดยใช้ฟังก์ชัน มอลลอค, โทรล็อค, จัดสรรใหม่และ ฟรี;
  • ผ่านตัวดำเนินการ ใหม่และ ลบ.

การทำงาน มอลลอค เงินสำรองบล็อกเซลล์หน่วยความจำที่ต่อเนื่องกันสำหรับการจัดเก็บ วัตถุที่ระบุและส่งคืนตัวชี้ไปที่เซลล์แรกของบล็อกนี้ การเรียกใช้ฟังก์ชันดูเหมือนว่า:

เป็นโมฆะ *malloc(ขนาด);

ที่นี่ ขนาด- ค่าจำนวนเต็มที่ไม่ได้ลงนามซึ่งกำหนดขนาดของพื้นที่หน่วยความจำที่จัดสรรเป็นไบต์ หากการสำรองหน่วยความจำสำเร็จ ฟังก์ชันจะกลับมา ตัวแปรประเภท เป็นโมฆะ *ซึ่งสามารถลดเหลือเท่าใดก็ได้ ประเภทที่ต้องการตัวชี้

การทำงาน - โทรล็อคมีไว้สำหรับการจัดสรรหน่วยความจำด้วย รายการด้านล่างหมายความว่าจะถูกเน้น หมายเลของค์ประกอบโดย ขนาดไบต์

เป็นโมฆะ *calloc(nime, ขนาด);

ฟังก์ชั่นนี้จะส่งคืนตัวชี้ไปยังพื้นที่ที่เลือกหรือ โมฆะเมื่อไม่สามารถจัดสรรหน่วยความจำได้ คุณสมบัติพิเศษของฟังก์ชันคือการรีเซ็ตองค์ประกอบที่เลือกทั้งหมดให้เป็นศูนย์

การทำงาน จัดสรรใหม่ปรับขนาดหน่วยความจำที่จัดสรรไว้ก่อนหน้านี้ พวกเขาพูดกับเธอแบบนี้:

ถ่าน * realloc (โมฆะ * p, ขนาด);

ที่นี่ พี- ชี้ไปยังพื้นที่หน่วยความจำที่ต้องเปลี่ยนขนาด ขนาด. หากที่อยู่ของพื้นที่หน่วยความจำเปลี่ยนแปลงอันเป็นผลมาจากฟังก์ชัน ที่อยู่ใหม่จะกลับมาเป็นผล ถ้า มูลค่าที่แท้จริงพารามิเตอร์แรก โมฆะจากนั้นฟังก์ชัน จัดสรรใหม่ทำงานเหมือนกับฟังก์ชัน มอลลอคนั่นคือจัดสรรพื้นที่หน่วยความจำขนาด ขนาดไบต์

หากต้องการเพิ่มหน่วยความจำที่จัดสรรให้ใช้ฟังก์ชัน ฟรี. พวกเขาพูดกับเธอแบบนี้:

เป็นโมฆะฟรี (โมฆะ * ขนาด p);

ที่นี่ พี- ชี้ไปยังตำแหน่งหน่วยความจำที่จัดสรรไว้ก่อนหน้านี้โดยฟังก์ชัน มอลลอค, โทรล็อคหรือ จัดสรรใหม่.

ผู้ประกอบการ ใหม่และ ลบฟังก์ชั่นที่คล้ายกัน มอลลอคและ ฟรี. ใหม่จัดสรรหน่วยความจำ และอาร์กิวเมนต์เดียวของมันคือนิพจน์ที่ระบุจำนวนไบต์ที่จะสงวนไว้ ตัวดำเนินการส่งคืนตัวชี้ไปยังจุดเริ่มต้นของบล็อกหน่วยความจำที่จัดสรร ผู้ดำเนินการ ลบเพิ่มหน่วยความจำ อาร์กิวเมนต์คือที่อยู่ของเซลล์แรกของบล็อกที่ต้องการปล่อย

อาร์เรย์แบบไดนามิก- อาร์เรย์ ความยาวตัวแปรหน่วยความจำที่ได้รับการจัดสรรระหว่างการทำงานของโปรแกรม การจัดสรรหน่วยความจำดำเนินการโดยฟังก์ชัน คาลลอค,มัลลอคหรือผู้ปฏิบัติงาน ใหม่. ที่อยู่ขององค์ประกอบแรกของตำแหน่งหน่วยความจำที่จัดสรรจะถูกเก็บไว้ในตัวแปรที่ประกาศเป็นตัวชี้ ตัวอย่างเช่น ข้อความต่อไปนี้หมายความว่ามีการอธิบายตัวชี้ มาสและกำหนดที่อยู่ของจุดเริ่มต้นของพื้นที่ต่อเนื่องกัน หน่วยความจำแบบไดนามิกเน้นโดยใช้โอเปอเรเตอร์ ใหม่:

int *mas=ใหม่ int;

จำนวนหน่วยความจำที่จัดสรรเพียงพอที่จะเก็บค่า int ได้ 10 ค่า

จริงๆ แล้วในตัวแปรนั้น มาสที่อยู่ถูกเก็บไว้ องค์ประกอบเป็นศูนย์อาร์เรย์แบบไดนามิก ดังนั้นที่อยู่ขององค์ประกอบแรกถัดไปในพื้นที่หน่วยความจำที่จัดสรรคือ มาส+1, ก มาส+i คือที่อยู่ขององค์ประกอบ i-th องค์ประกอบ i-th ของอาร์เรย์ไดนามิกสามารถเข้าถึงได้ตามปกติด้วย mas[i] หรือด้วยวิธีอื่น *(มาส +ไอ) . สิ่งสำคัญคือต้องแน่ใจว่าคุณไม่เกินขอบเขตของพื้นที่หน่วยความจำที่จัดสรร

เมื่อไร อาร์เรย์แบบไดนามิก(เมื่อใดก็ได้ระหว่างการทำงานของโปรแกรม) ไม่จำเป็นอีกต่อไป จากนั้นจึงสามารถปลดปล่อยหน่วยความจำได้โดยใช้ฟังก์ชัน ฟรีหรือผู้ปฏิบัติงาน ลบ.

ฉันเสนอให้พิจารณางานหลายอย่างที่เสริมบทเรียนนี้:

ปัญหาที่ 1

ค้นหาผลรวมขององค์ประกอบจริงของอาร์เรย์ไดนามิก

//ตัวอย่างการใช้งาน ฟังก์ชันมัลลอคและฟรี #include "stdafx.h" #include ใช้เนมสเปซมาตรฐาน; int main() ( setlocale(LC_ALL,"Rus"); int i, n; float *a; //ตัวชี้ให้ลอย float s; cout<<"\n"; cin>>น; // ป้อนขนาดอาร์เรย์ // จัดสรรหน่วยความจำสำหรับอาร์เรย์ขององค์ประกอบจริง n a = (float *) malloc (n * sizeof (float)); ศาล<<"Введите массив A \n"; //ввод элементов массива for (i=0; i>*(ก+ฉัน); ) //สะสมผลรวมขององค์ประกอบอาร์เรย์สำหรับ (s=0, i=0; i

//ตัวอย่างการใช้ฟังก์ชัน malloc และฟังก์ชันอิสระ

#รวม "stdafx.h"

#รวม

ใช้เนมสเปซมาตรฐาน ;

int หลัก()

ฉัน, n;

ลอย * เป็น; //ตัวชี้ให้ลอย

ลอย ;

ศาล<< "\n" ; cin >> ไม่มี ; //ป้อนขนาดอาร์เรย์

//จัดสรรหน่วยความจำสำหรับอาร์เรย์ที่มีองค์ประกอบจริง n ตัว

a = (float * ) malloc (n * ขนาดของ (float ) ) ;

ศาล<< "ป้อนอาร์เรย์ A\n";

//ใส่องค์ประกอบอาร์เรย์

สำหรับ (i = 0 ; i< n ; i ++ )

cin >> * (a + i) ;

//การสะสมผลรวมขององค์ประกอบอาร์เรย์

สำหรับ (s = 0 , i = 0 ; i< n ; i ++ )

s += * (ก + ฉัน) ;

//ส่งออกค่าจำนวน

ศาล<< "S=" << s << "\n" ;

//เพิ่มหน่วยความจำ

ฟรี(ก);

ระบบ("หยุดชั่วคราว");

กลับ 0 ;

ปัญหาที่ 2

แก้ไขอาร์เรย์แบบไดนามิกของจำนวนเต็มเพื่อให้องค์ประกอบที่เป็นบวกกลายเป็นลบและในทางกลับกัน ในการแก้ปัญหา เราจะคูณแต่ละองค์ประกอบด้วย -1

//ตัวอย่างการใช้ตัวดำเนินการใหม่และลบ #include "stdafx.h" #include ใช้เนมสเปซมาตรฐาน; int main() ( setlocale(LC_ALL,"Rus"); int i, n; //ป้อนจำนวนองค์ประกอบอาร์เรย์ cout<<"n="; cin>>น; //การจัดสรรหน่วยความจำ int *a=new int[n]; ศาล<<"Введите элементы массива:\n"; //ввод массива for (i=0; i>ก[ฉัน]; //ส่งออกอาร์เรย์ที่ระบุสำหรับ (i=0; i

// ตัวอย่างการใช้ตัวดำเนินการใหม่และลบ

#รวม "stdafx.h"

#รวม

ใช้เนมสเปซมาตรฐาน ;

int หลัก()

setlocale(LC_ALL, "มาตุภูมิ");

ฉัน, n;

//ป้อนจำนวนองค์ประกอบอาร์เรย์

ศาล<< "n=" ; cin >> ไม่มี ;

//การจัดสรรหน่วยความจำ

int * a = int ใหม่ [ n ] ;

ศาล<< "ป้อนองค์ประกอบอาร์เรย์:\n";

//อาร์เรย์อินพุต

ในขณะที่รวบรวมข้อมูลเพื่อเขียนบทความนี้ ฉันจำความคุ้นเคยครั้งแรกกับพอยน์เตอร์ได้ - ฉันรู้สึกเศร้ามาก... ดังนั้นหลังจากอ่านหลายหัวข้อในหัวข้อนี้จากหนังสือเกี่ยวกับการเขียนโปรแกรมใน C ++ หลายเล่มแล้วจึงตัดสินใจใช้เส้นทางที่แตกต่างและนำเสนอ หัวข้อของตัวชี้ C++ ตามลำดับที่ฉันคิดว่าจำเป็น ฉันจะให้คำจำกัดความสั้นๆ ทันที และเราจะดูคำแนะนำในการใช้งานจริงโดยใช้ตัวอย่าง บทความถัดไป () จะสรุปความแตกต่าง การใช้พอยน์เตอร์กับสตริงแบบ C (อาร์เรย์อักขระ) และสิ่งสำคัญที่ต้องจำ

ตัวชี้ในภาษา C++ คือตัวแปรที่เก็บที่อยู่ของข้อมูล (ค่า) ไว้ในหน่วยความจำ ไม่ใช่ตัวข้อมูลเอง

หลังจากดูตัวอย่างต่อไปนี้ คุณจะเข้าใจสิ่งสำคัญ - เหตุใดเราจึงต้องมีพอยน์เตอร์ในการเขียนโปรแกรม วิธีประกาศและใช้งาน

สมมติว่าในโปรแกรมเราต้องสร้างอาร์เรย์จำนวนเต็ม ซึ่งเป็นขนาดที่แน่นอนซึ่งเราไม่ทราบก่อนที่โปรแกรมจะเริ่มทำงาน นั่นคือเราไม่ทราบว่าผู้ใช้จะต้องป้อนตัวเลขจำนวนเท่าใดในอาร์เรย์นี้ แน่นอนว่าเราสามารถเล่นได้อย่างปลอดภัยและประกาศอาร์เรย์ขององค์ประกอบหลายพันรายการ (เช่น 5,000) สิ่งนี้ (ในความเห็นส่วนตัวของเรา) น่าจะเพียงพอสำหรับผู้ใช้ในการทำงาน ใช่ – แน่นอน – นี่อาจจะเพียงพอแล้ว แต่อย่าลืมว่าอาร์เรย์นี้จะใช้พื้นที่มากใน RAM (5,000 * 4 (ประเภท int) = 20,000 ไบต์) เราได้รักษาความปลอดภัยให้กับตัวเองแล้ว และผู้ใช้จะเติมองค์ประกอบอาร์เรย์ของเราเพียง 10 รายการเท่านั้น ปรากฎว่ามีการใช้งานจริง 40 ไบต์ และ 19,960 ไบต์เป็นการสิ้นเปลืองหน่วยความจำ

การใช้ RAM อย่างไม่สมเหตุสมผล

#รวม ใช้เนมสเปซมาตรฐาน; int main() ( setlocale(LC_ALL, "rus"); const int SizeOfArray = 5000; int arrWithDigits = (); ศาล<< "Массив занял в памяти " << sizeof(arrWithDigits) << " байт" << endl; int amount = 0; cout << "Сколько чисел вы введёте в массив? "; cin >>จำนวน; ศาล<< "Реально необходимо " << amount * sizeof(int) << " байт" << endl; for (int i = 0; i < amount; i++) { cout << i + 1 << "-е число: "; cin >> arrWithDigits[i]; ) อุทธรณ์<< endl; for (int i = 0; i < amount; i++) { cout << arrWithDigits[i] << " "; } cout << endl; return 0; }

#รวม

ใช้เนมสเปซมาตรฐาน ;

int หลัก()

const int SizeOfArray = 5,000 ;

int arrWithDigits [ SizeOfArray ] = ( ) ;

ศาล<< "อาร์เรย์ครอบครองในหน่วยความจำ"<< sizeof (arrWithDigits ) << " байт" << endl ;

จำนวน int = 0 ;

ศาล<< “คุณจะป้อนตัวเลขจำนวนเท่าใดในอาร์เรย์?”;

cin >> จำนวน ;

ศาล<< "จำเป็นจริงๆ"<< amount * sizeof (int ) << " байт" << endl ;

สำหรับ (int i = 0 ; i< amount ; i ++ )

ศาล<< i + 1 << "-е число: " ;

cin >> arrWithDigits [ ฉัน ] ;

ศาล<< endl ;

สำหรับ (int i = 0 ; i< amount ; i ++ )

ศาล<< arrWithDigits [ i ] << " " ;

ศาล<< endl ;

กลับ 0 ;

ไปยังฟังก์ชันไลบรารีมาตรฐาน ขนาดของ()ผ่านอาร์เรย์ที่ประกาศไว้ arrWithDigitsบรรทัดที่ 10 มันจะกลับไปยังตำแหน่งของการเรียกขนาดเป็นไบต์ที่อาร์เรย์นี้ครอบครองในหน่วยความจำ สำหรับคำถามที่ว่า “คุณจะใส่ตัวเลขจำนวนเท่าใดลงในอาร์เรย์?” คำตอบคือ 10 ในบรรทัดที่ 15 เป็นนิพจน์ จำนวน * ขนาดของ (int)จะเท่ากับ 10 * 4 เนื่องจากฟังก์ชัน ขนาดของ(int)จะส่งกลับ 4 (ขนาดเป็นไบต์ของประเภท int) จากนั้นให้ป้อนตัวเลขจากแป้นพิมพ์แล้วโปรแกรมจะแสดงบนหน้าจอ ปรากฎว่าองค์ประกอบ 4990 ที่เหลือจะเก็บค่าศูนย์ไว้ จึงไม่มีประโยชน์ที่จะแสดงให้พวกเขาเห็น

ข้อมูลหลักบนหน้าจอ: อาร์เรย์ใช้ 20,000 ไบต์ แต่ในความเป็นจริงต้องใช้ 40 ไบต์ จะออกจากสถานการณ์นี้ได้อย่างไร? บางคนอาจต้องการเขียนโปรแกรมใหม่เพื่อให้ผู้ใช้ป้อนขนาดของอาร์เรย์จากแป้นพิมพ์ และหลังจากป้อนค่าแล้ว ให้ประกาศอาร์เรย์ด้วยจำนวนองค์ประกอบที่ต้องการ แต่สิ่งนี้ไม่สามารถทำได้หากไม่มีพอยน์เตอร์ อย่างที่คุณจำได้ ขนาดของอาร์เรย์จะต้องเป็นค่าคงที่ นั่นคือ ต้องเริ่มต้นค่าคงที่จำนวนเต็มก่อนที่จะประกาศอาร์เรย์ และเราไม่สามารถพร้อมท์ให้ป้อนข้อมูลจากคีย์บอร์ดได้ ทดลองและตรวจสอบ


ในกรณีนี้เจ้าหน้าที่จะจุดไฟให้เราเป็นสีแดง >> เนื่องจากค่าคงที่ไม่สามารถเปลี่ยนแปลงได้

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


ที่นี่เราได้รับคำเตือนว่าขนาดของอาร์เรย์ไม่สามารถเป็นค่าของตัวแปรปกติได้ ต้องการค่าคงที่!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ในโค้ดต่อไปนี้ เราจะใช้พอยน์เตอร์และโอเปอเรเตอร์ที่ใหม่สำหรับคุณ ใหม่(จัดสรรหน่วยความจำ) และ ลบ(เพิ่มหน่วยความจำ)

การใช้ RAM อย่างชาญฉลาดโดยใช้พอยน์เตอร์

#รวม #รวม ใช้เนมสเปซมาตรฐาน; int main() ( setlocale(LC_ALL, "rus"); int sizeOfArray = 0; // ขนาดอาร์เรย์ (ป้อนโดยผู้ใช้) ศาล<< "Чтобы создать массив чисел, введите его размер: "; cin >> ขนาดของอาร์เรย์; // ความสนใจ! int* arrWithDigits - การประกาศตัวชี้ // ไปยังหน่วยความจำที่จะถูกจัดสรร new int* arrWithDigits = new int ; สำหรับ (int i = 0; i< sizeOfArray; i++) { arrWithDigits[i] = i + 1; cout << arrWithDigits[i] << " "; } cout << endl; delete arrWithDigits; // освобождение памяти return 0; }

#รวม

#รวม

ใช้เนมสเปซมาตรฐาน ;

int หลัก()

setlocale(LC_ALL, "มาตุภูมิ");

int sizeOfArray = 0 ; // ขนาดอาร์เรย์ (ป้อนโดยผู้ใช้)

ศาล<< "หากต้องการสร้างอาร์เรย์ของตัวเลข ให้ป้อนขนาด: ";

cin >> sizeOfArray ;

// ความสนใจ! int* arrWithDigits - การประกาศตัวชี้

// ไปยังชิ้นส่วนของหน่วยความจำที่ใหม่จะจัดสรร

int * arrWithDigits = int ใหม่ [ sizeOfArray ] ;

สำหรับ (int i = 0 ; i< sizeOfArray ; i ++ )

arrWithDigits[i] = i+1;

ศาล<< arrWithDigits [ i ] << " " ;

ศาล<< endl ;

ลบ arrWithDigits ; // เพิ่มหน่วยความจำ

กลับ 0 ;

ผู้ใช้ป้อนค่าจากแป้นพิมพ์ - บรรทัด 12 ตัวชี้ถูกกำหนดไว้ด้านล่าง: int * arrWithDigitsรายการนี้หมายความว่า arrWithDigitsเป็นตัวชี้ มันถูกสร้างขึ้นเพื่อจัดเก็บที่อยู่ของเซลล์ที่จะระบุจำนวนเต็ม ในกรณีของเรา arrWithDigitsจะชี้ไปที่เซลล์อาร์เรย์ที่มีดัชนี 0 เครื่องหมาย * - เช่นเดียวกับที่ใช้ในการคูณ ขึ้นอยู่กับบริบท คอมไพลเลอร์จะ "เข้าใจ" ว่านี่คือการประกาศพอยน์เตอร์ ไม่ใช่การคูณ ถัดมาเป็นป้าย = และผู้ปฏิบัติงาน ใหม่ซึ่งจัดสรรชิ้นส่วนของหน่วยความจำ เราจำได้ว่าหน่วยความจำของเราควรได้รับการจัดสรรให้กับอาร์เรย์ ไม่ใช่สำหรับตัวเลขตัวเดียว บันทึก ใหม่ int [sizeOfArray]สามารถถอดรหัสได้ดังนี้: ใหม่(จัดสรรหน่วยความจำ) ภายใน(สำหรับเก็บจำนวนเต็ม) (ในปริมาณ ขนาดของอาร์เรย์ ).

ดังนั้นในบรรทัดที่ 16 จึงได้กำหนดไว้ อาร์เรย์แบบไดนามิก. ซึ่งหมายความว่าหน่วยความจำจะถูกจัดสรร (หรือไม่ได้จัดสรร) ในขณะที่โปรแกรมกำลังทำงานอยู่ และไม่ใช่ในระหว่างการคอมไพล์ ดังที่เกิดขึ้นกับอาร์เรย์ปกติ นั่นคือการจัดสรรหน่วยความจำขึ้นอยู่กับการพัฒนาโปรแกรมและการตัดสินใจที่เกิดขึ้นโดยตรงในการทำงาน ในกรณีของเรา ขึ้นอยู่กับว่าผู้ใช้ป้อนอะไรเข้าไปในตัวแปร ขนาดของอาร์เรย์

บรรทัดที่ 25 ใช้ตัวดำเนินการ ลบ. มันจะปล่อยโอเปอเรเตอร์ที่ได้รับการจัดสรร ใหม่หน่วยความจำ. เพราะ ใหม่จัดสรรหน่วยความจำสำหรับจัดเก็บอาเรย์จากนั้นเมื่อปล่อยมันคุณจะต้องทำให้คอมไพเลอร์ชัดเจนว่าจำเป็นต้องปล่อยหน่วยความจำของอาเรย์ให้ว่างและไม่ใช่แค่เซลล์ศูนย์ซึ่งชี้ไปที่ arrWithDigits. ดังนั้นระหว่าง ลบและชื่อตัวชี้จะอยู่ในวงเล็บเหลี่ยม ลบ arrWithDigits ;จำไว้ว่าทุกครั้งที่มีการจัดสรรหน่วยความจำโดยใช้ ใหม่คุณต้องเพิ่มหน่วยความจำนี้โดยใช้ ลบ. แน่นอนว่าเมื่อโปรแกรมหยุดทำงาน หน่วยความจำที่โปรแกรมครอบครองอยู่ก็จะถูกปลดปล่อยโดยอัตโนมัติ แต่จงใช้ตัวดำเนินการให้เป็นนิสัย ใหม่และ ลบจับคู่กับ ท้ายที่สุดแล้ว โปรแกรมสามารถมีอาร์เรย์ได้ 5-6 ตัว เป็นต้น และหากคุณเพิ่มหน่วยความจำทุกครั้งที่ไม่จำเป็นอีกต่อไปในโปรแกรมที่ทำงานอยู่ในอนาคต หน่วยความจำจะถูกใช้อย่างชาญฉลาดมากขึ้น

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

ลองพิจารณาการใช้พอยน์เตอร์เป็นพารามิเตอร์ของฟังก์ชัน ในการเริ่มต้น ให้พิมพ์และคอมไพล์โค้ดต่อไปนี้ ในนั้นฟังก์ชันจะได้รับตัวแปรสองตัวและเสนอให้ทำการเปลี่ยนแปลงค่าของมัน

พยายามเปลี่ยนตัวแปรที่ส่งผ่านไปยังฟังก์ชัน

#รวม #รวม ใช้เนมสเปซมาตรฐาน; โมฆะ changeData(int varForCh1, int varForCh2); int main() ( setlocale(LC_ALL, "rus"); int ตัวแปรForChange_1 = 0; int ตัวแปรForChange_2 = 0; cout<< "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; cout << endl; changeData(variableForChange_1, variableForChange_2); cout << endl; cout << "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; return 0; } void changeData(int varForCh1, int varForCh2) { cout << "Введите новое значение первой переменной: "; cin >>varForCh1; ศาล<< "Введите новое значение второй переменной: "; cin >> varForCh2; )

#รวม

#รวม

ใช้เนมสเปซมาตรฐาน ;

โมฆะการเปลี่ยนแปลงข้อมูล (int varForCh1 , int varForCh2 ) ;

int หลัก()

setlocale(LC_ALL, "มาตุภูมิ");

ตัวแปร intForChange_1 = 0 ;

ตัวแปร intForChange_2 = 0 ;

ศาล<< "variableForChange_1 = " << variableForChange_1 << endl ;

ศาล<< "variableForChange_2 = " << variableForChange_2 << endl ;

ศาล<< endl ;

changeData(ตัวแปรForChange_1, ตัวแปรForChange_2);

ศาล<< endl ;

ศาล<< "variableForChange_1 = " << variableForChange_1 << endl ;

ศาล<< "variableForChange_2 = " << variableForChange_2 << endl ;

กลับ 0 ;

โมฆะ changeData (int varForCh1, int varForCh2)

ศาล<< "ป้อนค่าใหม่สำหรับตัวแปรแรก: ";

cin >> varForCh1 ;

ศาล<< "ป้อนค่าใหม่สำหรับตัวแปรตัวที่สอง: ";

cin >> varForCh2 ;

รันโปรแกรมและป้อนค่าตัวแปรใหม่ ผลลัพธ์จะเห็นว่าเมื่อฟังก์ชันเสร็จสิ้น ตัวแปรต่างๆ จะไม่เปลี่ยนแปลงและมีค่าเท่ากับ 0

อย่างที่คุณจำได้ ฟังก์ชันนี้ไม่ได้ทำงานโดยตรงกับตัวแปร แต่จะสร้างสำเนาที่ตรงกันทุกประการ สำเนาเหล่านี้จะถูกทำลายหลังจากออกจากฟังก์ชัน นั่นคือฟังก์ชันได้รับตัวแปรบางตัวเป็นพารามิเตอร์ สร้างสำเนา ทำงานกับมัน และทำลายมัน ตัวแปรนั้นจะยังคงไม่เปลี่ยนแปลง

การใช้พอยน์เตอร์ทำให้เราสามารถส่งที่อยู่ตัวแปรไปยังฟังก์ชันได้ จากนั้นฟังก์ชันจะสามารถทำงานกับข้อมูลตัวแปรตามที่อยู่ได้โดยตรง มาทำการเปลี่ยนแปลงโปรแกรมก่อนหน้ากัน

การเปลี่ยนค่าตัวแปรโดยใช้พอยน์เตอร์

#รวม #รวม ใช้เนมสเปซมาตรฐาน; โมฆะ changeData(int* varForCh1, int* varForCh2); int main() ( setlocale(LC_ALL, "rus"); int ตัวแปรForChange_1 = 0; int ตัวแปรForChange_2 = 0; cout<< "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; cout << endl; changeData(&variableForChange_1, &variableForChange_2); cout << endl; cout << "variableForChange_1 = " << variableForChange_1 << endl; cout << "variableForChange_2 = " << variableForChange_2 << endl; return 0; } void changeData(int* varForCh1, int* varForCh2) { cout << "Введите новое значение первой переменной: "; cin >> *varForCh1; ศาล<< "Введите новое значение второй переменной: "; cin >> *varForCh2; )

วัตถุประสงค์ของการบรรยาย: ศึกษาการประกาศ การจัดสรร และการปล่อยหน่วยความจำสำหรับอาร์เรย์ไดนามิกมิติเดียว การเข้าถึงองค์ประกอบ เรียนรู้วิธีการแก้ปัญหาโดยใช้อาร์เรย์ไดนามิกมิติเดียวในภาษา C++

เมื่อใช้โครงสร้างข้อมูลจำนวนมาก มักจะเกิดขึ้นว่าต้องมีขนาดตัวแปรขึ้นอยู่กับขนาดของโครงสร้างข้อมูล เวลานำโปรแกรม ในกรณีเหล่านี้มีความจำเป็นต้องใช้ การจัดสรรหน่วยความจำแบบไดนามิก. หนึ่งในโครงสร้างข้อมูลที่พบบ่อยที่สุดคืออาร์เรย์ ซึ่งขนาดไม่ได้ถูกกำหนดหรือแก้ไขตั้งแต่แรก

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

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

การประกาศอาร์เรย์ไดนามิกมิติเดียว

ภายใต้การประกาศมิติเดียว อาร์เรย์แบบไดนามิกเข้าใจการประกาศของตัวชี้ไปยังตัวแปรประเภทที่กำหนดเพื่อให้ตัวแปรนี้สามารถใช้เป็น อาร์เรย์แบบไดนามิก.

ไวยากรณ์:

พิมพ์ *ชื่ออาร์เรย์;

ประเภท – ประเภทขององค์ประกอบที่กำลังประกาศ อาร์เรย์แบบไดนามิก. องค์ประกอบ อาร์เรย์แบบไดนามิกไม่สามารถมีฟังก์ชันและองค์ประกอบได้ ประเภทเป็นโมฆะ.

ตัวอย่างเช่น:

int *a; สองเท่า *d;

ในตัวอย่างเหล่านี้ a และ d เป็นตัวชี้ไปยังจุดเริ่มต้นของตำแหน่งหน่วยความจำที่จัดสรร พอยน์เตอร์รับค่าที่อยู่ของพื้นที่หน่วยความจำที่จัดสรรสำหรับค่าประเภท int และประเภท double ตามลำดับ

ดังนั้นเมื่อจัดสรรหน่วยความจำแบบไดนามิกสำหรับอาร์เรย์แบบไดนามิกคุณควรอธิบายตัวชี้ที่เกี่ยวข้องซึ่งจะกำหนดค่าที่อยู่ของจุดเริ่มต้นของพื้นที่หน่วยความจำที่จัดสรรไว้

การจัดสรรหน่วยความจำสำหรับอาเรย์ไดนามิกหนึ่งมิติ

เพื่อเป็นการจัดสรรหน่วยความจำให้กับมิติเดียว อาร์เรย์แบบไดนามิกใน C++ มี 2 วิธี

1) โดยการดำเนินการ new ซึ่งจัดสรรส่วนของหน่วยความจำไดนามิกที่มีขนาดที่เหมาะสมสำหรับการจัดเก็บอาเรย์และไม่อนุญาตให้เตรียมใช้งานองค์ประกอบอาเรย์ได้

ไวยากรณ์:

ArrayName = ชนิดใหม่ [ConstantTypeExpression];

ArrayName – ตัวระบุอาร์เรย์ นั่นคือชื่อของตัวชี้สำหรับบล็อกหน่วยความจำที่จัดสรร

ประเภทนิพจน์คงที่– กำหนดจำนวนองค์ประกอบ ( มิติข้อมูล) ของอาเรย์. นิพจน์ของประเภทคงที่จะถูกประเมิน ณ เวลารวบรวม

ตัวอย่างเช่น:

int *mas; mas = int ใหม่ ; /*จัดสรรหน่วยความจำแบบไดนามิกขนาด 100*sizeof(int) ไบต์*/ double *m = new double [n]; /*จัดสรรหน่วยความจำแบบไดนามิกขนาด n*sizeof(double) ไบต์*/ long (*lm); lm = ยาวใหม่ ; /*จัดสรรหน่วยความจำแบบไดนามิกขนาด 2*4*ขนาด (ยาว) ไบต์*/

เมื่อจัดสรรหน่วยความจำแบบไดนามิก จะต้องระบุขนาดของอาร์เรย์ให้ครบถ้วน

2) โดยใช้ฟังก์ชันไลบรารี malloc (calloc) ซึ่งใช้ในการจัดสรรหน่วยความจำแบบไดนามิก

ไวยากรณ์:

ArrayName = (ชนิด *) malloc(N*ขนาดของ(ชนิด));

ArrayName = (ชนิด *) calloc(N, ขนาดของ(ชนิด));

ArrayName – ตัวระบุอาร์เรย์ นั่นคือชื่อของตัวชี้สำหรับบล็อกหน่วยความจำที่จัดสรร

Type – ประเภทของตัวชี้ไปยังอาร์เรย์

N – จำนวนองค์ประกอบอาร์เรย์

ตัวอย่างเช่น:

ลอย *a; a=(ลอย *)malloc(10*ขนาดของ(ลอย)); // หรือ a=(float *)calloc(10,sizeof(float)); /*จัดสรรหน่วยความจำแบบไดนามิกขนาด 10*ขนาด (ลอย) ไบต์*/

เนื่องจากฟังก์ชัน malloc(calloc) กลับมา ตัวชี้ที่ไม่ได้พิมพ์เป็นโมฆะ * ดังนั้นจึงจำเป็นต้องแปลงผลลัพธ์

// การประกาศอาร์เรย์ไดนามิกสองมิติจำนวน 10 องค์ประกอบ:

float **ptrarray = ลอยใหม่* ; // สองบรรทัดในอาร์เรย์

สำหรับ (จำนวน int = 0; นับ< 2; count++)

ptrarray = โฟลตใหม่ ; // และห้าคอลัมน์

// โดยที่ ptrarray เป็นอาร์เรย์ของพอยน์เตอร์ไปยังพื้นที่หน่วยความจำที่จัดสรรสำหรับอาร์เรย์ของจำนวนจริงประเภท float

ขั้นแรก มีการประกาศตัวชี้ลำดับที่สอง float **ptrarray ซึ่งอ้างอิงถึงอาร์เรย์ของตัวชี้ float* โดยที่ขนาดของอาร์เรย์คือสอง . หลังจากนั้นใน for loop แต่ละบรรทัดของอาร์เรย์จะถูกประกาศ บรรทัดที่ 2หน่วยความจำได้รับการจัดสรรให้กับห้าองค์ประกอบ ผลลัพธ์ที่ได้คือ ptrarray อาร์เรย์แบบไดนามิก 2 มิติ ลองพิจารณาตัวอย่างการเพิ่มหน่วยความจำที่จัดสรรไว้สำหรับอาร์เรย์ไดนามิก 2 มิติ

// การเพิ่มหน่วยความจำที่จัดสรรสำหรับอาร์เรย์ไดนามิกสองมิติ:

สำหรับ (จำนวน int = 0; นับ< 2; count++)

ลบ ptrarray;

// โดยที่ 2 คือจำนวนบรรทัดในอาร์เรย์

#รวม
#รวม
#รวม
เป็นโมฆะหลัก ()
{

int *a; // ชี้ไปที่อาร์เรย์

ระบบ("chcp 1251");

scanf("%d", &n);

scanf("%d", &m);

// การจัดสรรหน่วยความจำ

a = (int*) malloc(n*m*sizeof(int));

// การป้อนองค์ประกอบอาร์เรย์

สำหรับ(i=0; ผม

สำหรับ(j=0; เจ

printf("a[%d][%d] = ", i, j);

scanf("%d", (a+i*m+j));

// องค์ประกอบอาร์เรย์เอาท์พุต

สำหรับ(i=0; ผม

สำหรับ(j=0; เจ

printf("%5d ", *(a+i*m+j)); // 5 คนรู้จักสำหรับองค์ประกอบอาร์เรย์

รับชาร์(); รับชาร์();
}

ผลการดำเนินการ

กรอกจำนวนบรรทัด: 3

ป้อนจำนวนคอลัมน์: 4

อีกวิธีหนึ่งในการจัดสรรหน่วยความจำแบบไดนามิกสำหรับอาร์เรย์สองมิติก็เป็นไปได้เช่นกัน - โดยใช้อาร์เรย์ของพอยน์เตอร์ ในการทำเช่นนี้คุณต้องมี:
- จัดสรรบล็อก RAM สำหรับอาร์เรย์ของพอยน์เตอร์
- จัดสรรบล็อก RAM สำหรับอาร์เรย์หนึ่งมิติซึ่งเป็นแถวของเมทริกซ์ที่ต้องการ
- เขียนที่อยู่ของบรรทัดลงในอาร์เรย์ของพอยน์เตอร์

ฟังก์ชัน malloc() ส่งคืนตัวชี้ไปยังไบต์แรกของพื้นที่หน่วยความจำขนาดขนาดที่ได้รับการจัดสรรจากพื้นที่หน่วยความจำที่จัดสรรแบบไดนามิก ถ้ามีหน่วยความจำไม่เพียงพอในพื้นที่หน่วยความจำแบบไดนามิก ตัวชี้ null จะถูกส่งกลับ

#รวม
#รวม
#รวม
เป็นโมฆะหลัก ()
{

อินท์**ก; // ตัวชี้ไปยังตัวชี้ไปยังสตริง

ระบบ("chcp 1251");

printf("กรอกจำนวนบรรทัด: ");

scanf("%d", &n);

printf("ระบุจำนวนคอลัมน์: ");

scanf("%d", &m);

// การจัดสรรหน่วยความจำสำหรับพอยน์เตอร์ให้กับสตริง

a = (int**)malloc(n*ขนาดของ(int*));

// การป้อนองค์ประกอบอาร์เรย์

สำหรับ(i=0; ผม

// การจัดสรรหน่วยความจำเพื่อจัดเก็บสตริง

a[i] = (int*)malloc(m*sizeof(int));

สำหรับ(j=0; เจ

printf("a[%d][%d] = ", i, j);

scanf("%d", &a[i][j]);

// องค์ประกอบอาร์เรย์เอาท์พุต

สำหรับ(i=0; ผม

สำหรับ(j=0; เจ

printf("%5d ", a[i][j]); // 5 คนรู้จักสำหรับองค์ประกอบอาร์เรย์

ฟรี(ก[i]); // เพิ่มหน่วยความจำให้กับสตริง

รับชาร์(); รับชาร์();
}

ผลลัพธ์ของการรันโปรแกรมจะคล้ายกับกรณีก่อนหน้า

การใช้การจัดสรรหน่วยความจำแบบไดนามิกสำหรับตัวชี้แถว คุณสามารถจัดสรรอาร์เรย์ว่างได้ ฟรี เป็นอาร์เรย์สองมิติ (เมทริกซ์) ซึ่งขนาดของแถวอาจแตกต่างกันได้ ข้อดีของการใช้อาร์เรย์อิสระคือ คุณไม่จำเป็นต้องจัดสรรหน่วยความจำคอมพิวเตอร์มากเกินไปเพื่อรองรับสตริงที่มีความยาวสูงสุดที่เป็นไปได้ ที่จริงแล้ว อาร์เรย์อิสระคืออาร์เรย์หนึ่งมิติของตัวชี้ไปยังอาร์เรย์ข้อมูลหนึ่งมิติ

พอยน์เตอร์

ตัวชี้คือตัวแปรที่มีค่าเป็นที่อยู่ซึ่งมีข้อมูลอยู่ ที่อยู่คือจำนวนเซลล์หน่วยความจำที่อยู่ในหรือจากที่ข้อมูลตั้งอยู่

ตามประเภทข้อมูลใน SI พอยน์เตอร์จะแบ่งออกเป็น:

ตัวชี้ที่พิมพ์คือตัวชี้ที่มีที่อยู่ของข้อมูลบางประเภท (ระบบหรือผู้ใช้)

ตัวชี้ที่ไม่ได้พิมพ์คือตัวชี้ที่มีที่อยู่ข้อมูลประเภทที่ไม่ระบุ (เพียงที่อยู่)

ประกาศตัวชี้;

การตั้งค่าตัวชี้;

การเข้าถึงค่าที่อยู่ที่ตัวชี้ การประกาศ (คำอธิบาย) ของตัวชี้ในภาษา SI มีรูปแบบดังต่อไปนี้:

พิมพ์ *ชื่อ [=value];

เมื่อประกาศ ตัวชี้ใน SI จะสามารถเริ่มต้นได้โดยการระบุค่าที่สอดคล้องกันผ่านเครื่องหมายกำหนด ค่านี้ต้องเป็นที่อยู่ซึ่งเขียนในรูปแบบใดรูปแบบหนึ่งต่อไปนี้:

เป็นโมฆะ (id เป็นโมฆะ);

ตัวชี้อื่น;

ที่อยู่ที่เปลี่ยนแปลงได้ (ผ่านการดำเนินการรับที่อยู่)

นิพจน์ที่แสดงถึงเลขคณิตของพอยน์เตอร์

ที่อยู่ที่เป็นผลมาจากการจัดสรรหน่วยความจำแบบไดนามิก

#รวม

int var; // ตัวแปรจำนวนเต็มปกติ

int *ptrVar; // ตัวชี้จำนวนเต็ม (ptrVar ต้องเป็นประเภท int เนื่องจากจะอ้างอิงถึงตัวแปรประเภท int)

ptrVar = // กำหนดที่อยู่ของเซลล์หน่วยความจำให้พอยน์เตอร์ โดยที่ค่าของตัวแปร var อยู่

scanf("%d", &var); // ตัวแปร var มีค่าที่ป้อนจากคีย์บอร์ด

printf("%d\n", *ptrVar); // ค่าเอาต์พุตผ่านพอยน์เตอร์

ผลการดำเนินการ: 6 6

การบรรยายครั้งที่ 3

ฟังก์ชั่น.

ฟังก์ชันคือโมดูลโปรแกรมที่มีชื่อที่ระบุทางวากยสัมพันธ์ซึ่งดำเนินการเฉพาะหรือกลุ่มของการดำเนินการ แต่ละฟังก์ชันมีส่วนต่อประสานและการนำไปใช้งานของตัวเอง อินเทอร์เฟซฟังก์ชัน – ส่วนหัวของฟังก์ชัน ซึ่งระบุชื่อของฟังก์ชัน รายการพารามิเตอร์ และประเภทของค่าที่ส่งคืน

คำอธิบายของฟังก์ชันในภาษา SI จะดำเนินการที่ใดก็ได้ในโปรแกรมนอกเหนือจากคำอธิบายของฟังก์ชันอื่นๆ และประกอบด้วยสามองค์ประกอบ:

1. ต้นแบบฟังก์ชัน

2. ส่วนหัวของฟังก์ชัน;

3.ฟังก์ชั่นร่างกาย.

ต้นแบบฟังก์ชันเป็นส่วนเสริมของคำอธิบายฟังก์ชันซึ่งมีจุดประสงค์เพื่อประกาศฟังก์ชันที่มีอินเทอร์เฟซที่สอดคล้องกับต้นแบบที่กำหนด การประกาศต้นแบบมีรูปแบบดังต่อไปนี้:

พิมพ์ชื่อ (รายการประเภทพารามิเตอร์ที่เป็นทางการ);

พารามิเตอร์ฟังก์ชันคือค่าที่ส่งผ่านไปยังฟังก์ชันเมื่อมีการเรียกใช้

ส่วนหัวของฟังก์ชัน – คำอธิบายส่วนอินเทอร์เฟซของฟังก์ชัน ซึ่งประกอบด้วย: ประเภทค่าที่ส่งคืน ชื่อของฟังก์ชัน และรายการพารามิเตอร์ที่เป็นทางการของฟังก์ชัน ไวยากรณ์สำหรับการประกาศส่วนหัวของฟังก์ชันคือ:

พิมพ์ชื่อ (รายการพารามิเตอร์ที่เป็นทางการ)

ตัวอย่างของส่วนหัวของฟังก์ชัน:

Int func(int i, ดับเบิ้ล x, ดับเบิ้ล y)

ฟังก์ชั่นโมฆะ (int ind, char *string)

ฟังก์ชั่นคู่ (เป็นโมฆะ)

เนื้อความของฟังก์ชันคือส่วนการใช้งานที่มีโค้ดโปรแกรมที่จะดำเนินการเมื่อมีการเรียกใช้ฟังก์ชัน เนื้อหาของฟังก์ชันจะมาต่อจากส่วนหัวของฟังก์ชันเสมอ (ไม่สามารถแยกออกจากกันได้) และจะอยู่ในเครื่องหมายปีกกา

การใช้ฟังก์ชันใน SI เพื่อคำนวณแฟกทอเรียลของตัวเลข

แฟกทอเรียลคู่ (ไม่ได้ลงนาม);

แฟกทอเรียลคู่ (หมายเลขที่ไม่ได้ลงนาม)

ข้อเท็จจริงสองเท่า = 1.0;

สำหรับ(ไม่ได้ลงนาม i=1;i<=num;i++)

ข้อเท็จจริง *= (สองเท่า)i;

กลับข้อเท็จจริง;

โครงสร้าง.

โครงสร้างเป็นชนิดข้อมูลที่ซับซ้อนซึ่งแสดงถึงชุดขององค์ประกอบประเภทต่างๆ ที่เรียงลำดับในหน่วยความจำ แต่ละองค์ประกอบในโครงสร้างมีชื่อเป็นของตัวเองและเรียกว่าฟิลด์

การประกาศใน SI ของโครงสร้างดูเหมือนว่า:

โครงสร้าง [ชื่อประเภท]

ฟิลด์_1;

ฟิลด์_2;

สนาม_N;

) [รายการตัวแปร];

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

ไฟล์.

ไฟล์คือพื้นที่ที่มีชื่อข้อมูลบนสื่อบันทึกข้อมูลบางชนิด ประเภทไฟล์ (สัมพันธ์กับภาษา SI):
ข้อความ;
ไบนารี่.
การดำเนินการพื้นฐานกับไฟล์:
1.การเปิดไฟล์
2.การอ่านและการเขียนข้อมูล
3.การปิดไฟล์

การดำเนินการเพิ่มเติม:
1. การนำทางไฟล์
2. การจัดการข้อผิดพลาดเมื่อทำงานกับไฟล์
3.การลบและเปลี่ยนชื่อไฟล์
4.คำอธิบายตัวแปร

โหมดการเปิด ไฟล์ที่มี SI

การเปลี่ยนเส้นทางสตรีม
FILE * freopen (const char * ชื่อไฟล์, const char * โหมด, FILE * สตรีม);

ฟังก์ชันส่งคืน:
ตัวชี้ไปยังไฟล์ - ทุกอย่างเรียบร้อยดี
NULL – ข้อผิดพลาดแทนที่

การปิดไฟล์
int fclose (ไฟล์ * สตรีม);

ฟังก์ชันส่งคืน:
0 – ปิดไฟล์สำเร็จ
1 – เกิดข้อผิดพลาดในการปิดไฟล์

สิ้นสุดการตรวจสอบไฟล์
int feof(ไฟล์ *สตรีม);
สตรีม - ตัวชี้ไปยังไฟล์ที่เปิด

ฟังก์ชันส่งคืน:
0 – หากยังไม่ถึงจุดสิ้นสุดของไฟล์
!0 – ถึงจุดสิ้นสุดของไฟล์แล้ว

กำลังเปิดไฟล์ข้อความ
พารามิเตอร์ตัวที่สองระบุอักขระ t เพิ่มเติม (เป็นทางเลือก):
rt, น้ำหนัก, ที่, rt+, น้ำหนัก+, ที่+

อ่านจากไฟล์ข้อความ

การอ่านที่จัดรูปแบบ
int fscanf(ไฟล์ *สตรีม, รูปแบบ const char *, ...);

ฟังก์ชันส่งคืน:
>0 – จำนวนตัวแปรที่อ่านสำเร็จ
0 - ไม่มีการอ่านตัวแปรใดสำเร็จ
EOF - ถึงข้อผิดพลาดหรือถึงจุดสิ้นสุดของไฟล์
กำลังอ่านบรรทัด

ฟังก์ชันส่งคืน:
บัฟเฟอร์ - ทุกอย่างเรียบร้อยดี
กำลังอ่านบรรทัด
ถ่าน * fgets (ถ่าน * บัฟเฟอร์, int maxlen, FILE * สตรีม);

ฟังก์ชันส่งคืน:
บัฟเฟอร์ - ทุกอย่างเรียบร้อยดี
NULL – ข้อผิดพลาดหรือถึงจุดสิ้นสุดของไฟล์
การอ่านสัญลักษณ์
int fgetc(ไฟล์ *สตรีม);
ฟังก์ชันส่งคืน:
รหัสสัญลักษณ์ - หากทุกอย่างเรียบร้อยดี
EOF – หากเกิดข้อผิดพลาดหรือถึงจุดสิ้นสุดของไฟล์
นำตัวละครกลับเข้าสู่กระแส
int ungetc(int c, FILE *สตรีม);
ฟังก์ชันส่งคืน:
รหัสสัญลักษณ์ – หากทุกอย่างสำเร็จ
EOF – มีข้อผิดพลาดเกิดขึ้น

เขียนเป็นข้อความ ไฟล์เอสไอ

เอาต์พุตที่จัดรูปแบบแล้ว
int fprintf(FILE *กระแส, const char *รูปแบบ, ...);
ฟังก์ชันส่งคืน:
จำนวนตัวอักษรที่เขียน - หากทุกอย่างเป็นปกติ
ค่าลบ – หากมีข้อผิดพลาด
การเขียนสตริง
int fputs(const char *string, FILE *stream);
ฟังก์ชันส่งคืน:
จำนวนตัวอักษรที่เขียน - ทุกอย่างเรียบร้อยดี
EOF – มีข้อผิดพลาดเกิดขึ้น
เขียนสัญลักษณ์
int fputc (int c, FILE * สตรีม);
ฟังก์ชันส่งคืน:
รหัสของสัญลักษณ์ที่บันทึกไว้ - ทุกอย่างเรียบร้อยดี
EOF – มีข้อผิดพลาดเกิดขึ้น
การเปิดไฟล์ไบนารี
พารามิเตอร์ตัวที่สองระบุสัญลักษณ์ b เพิ่มเติม (จำเป็น): rb, wb, ab, rb+, wb+, ab+
อ่านจากไฟล์ไบนารี
size_t fread (โมฆะ * บัฟเฟอร์, ขนาด size_t, size_t num, FILE * สตรีม);
ฟังก์ชันส่งคืนจำนวนบล็อกที่อ่าน หากน้อยกว่า num แสดงว่าเกิดข้อผิดพลาดหรือไปถึง
จุดสิ้นสุดของไฟล์

เขียนเป็นไฟล์ไบนารี
size_t fwrite (const เป็นโมฆะ * บัฟเฟอร์, ขนาด size_t, size_t num, FILE * สตรีม);
ฟังก์ชันส่งคืนจำนวนบล็อกที่เขียน หากน้อยกว่า num แสดงว่าเกิดข้อผิดพลาด

การนำทางไฟล์

การอ่านออฟเซ็ตปัจจุบันในไฟล์:
int ftell ยาว (ไฟล์ * สตรีม);
การเปลี่ยนออฟเซ็ตปัจจุบันในไฟล์:
int fseek (ไฟล์ * สตรีม, int offset แบบยาว, int origin);

SEEK_SET (0) – จากจุดเริ่มต้นของไฟล์
SEEK_CUR (1) – จากตำแหน่งปัจจุบัน
SEEK_END (2) – จากท้ายไฟล์
ฟังก์ชันส่งคืน:
0 – ทุกอย่างเรียบร้อยดี
!0 – เกิดข้อผิดพลาด
ย้ายไปที่จุดเริ่มต้นของไฟล์:
ย้อนกลับเป็นโมฆะ (FILE * สตรีม);
การอ่านตำแหน่งปัจจุบันในไฟล์:
int fgetpos(ไฟล์ *สตรีม, fpos_t *pos);
การตั้งค่าตำแหน่งปัจจุบันในไฟล์:
int fsetpos(ไฟล์ *สตรีม, const fpos_t *pos);
ฟังก์ชันส่งคืน:
0 - ทุกอย่างสำเร็จ
!0 – เกิดข้อผิดพลาด
โครงสร้าง fpos_t:
typedef โครงสร้าง fpos_t (
หายไปนาน;
mbstate_t wstate;
) fpos_t;

รับสัญญาณข้อผิดพลาด:
int ferror (ไฟล์ * สตรีม);
ฟังก์ชันจะส่งกลับค่าที่ไม่ใช่ศูนย์หากเกิดข้อผิดพลาด
ฟังก์ชั่นรีเซ็ตข้อผิดพลาด:
เป็นโมฆะ clearerr (FILE * สตรีม);
ฟังก์ชั่นข้อความแสดงข้อผิดพลาด:
เป็นโมฆะ perror (const char *string);

การบัฟเฟอร์

ฟังก์ชั่นล้างบัฟเฟอร์:
int fflush (ไฟล์ * สตรีม);
ฟังก์ชันส่งคืน:
0 – ทุกอย่างเรียบร้อยดี
EOF – มีข้อผิดพลาดเกิดขึ้น
ฟังก์ชั่นการจัดการบัฟเฟอร์:
เป็นโมฆะ setbuf (ไฟล์ * สตรีม, ถ่าน * บัฟเฟอร์);

สร้างบัฟเฟอร์ขนาด BUFSIZ ใช้ก่อนอินพุตหรือเอาต์พุตไปยังสตรีม

ไฟล์ชั่วคราว

ฟังก์ชั่นการสร้างไฟล์ชั่วคราว:
FILE * tmpfile (เป็นโมฆะ);
สร้างไฟล์ชั่วคราวในโหมด wb+ หลังจากปิดไฟล์แล้ว ไฟล์หลังจะถูกลบโดยอัตโนมัติ
ฟังก์ชั่นการสร้างชื่อไฟล์ชั่วคราว:
ถ่าน * tmpnam (ถ่าน * บัฟเฟอร์);

การลบและเปลี่ยนชื่อ

ฟังก์ชั่นการลบไฟล์:
int ลบ (const char * ชื่อไฟล์);
ฟังก์ชั่นการเปลี่ยนชื่อไฟล์:
int เปลี่ยนชื่อ (const char *fname, const char *nname);
ฟังก์ชันส่งคืน:
0 – หากสำเร็จ
!0 – มิฉะนั้น

การบรรยายครั้งที่ 4

ซ้อนกัน.

สแต็กเป็นสิ่งที่ตรงกันข้ามกับคิวเนื่องจากทำงานแบบเข้าหลังออกก่อน (LIFO) หากต้องการเห็นภาพปึก ให้นึกถึงแผ่นปึก จานแรกที่วางอยู่บนโต๊ะจะถูกใช้เป็นอันดับสุดท้าย และจานสุดท้ายที่วางอยู่ด้านบนจะถูกใช้ก่อน สแต็กมักใช้ในซอฟต์แวร์ระบบ รวมถึงคอมไพเลอร์และล่าม

เมื่อทำงานกับสแต็ก การดำเนินการหลักคือการแทรกและดึงองค์ประกอบ การดำเนินการเหล่านี้มักเรียกว่า "พุช" และ "ป๊อป" ดังนั้น ในการใช้งานสแต็ก คุณจะต้องเขียนสองฟังก์ชัน: push() ซึ่ง "ส่ง" ค่าไปยังสแต็ก และ pop() ซึ่ง "ป๊อป" ค่าจากสแต็ก คุณต้องจัดสรรพื้นที่หน่วยความจำที่จะใช้เป็นสแต็กด้วย เพื่อจุดประสงค์นี้ คุณสามารถจัดสรรอาร์เรย์หรือจัดสรรหน่วยความจำแบบไดนามิกโดยใช้ฟังก์ชันภาษา C ที่จัดเตรียมไว้สำหรับการจัดสรรหน่วยความจำแบบไดนามิก เช่นเดียวกับคิว ฟังก์ชันดึงข้อมูลจะนำองค์ประกอบออกจากรายการและลบออกหากยังไม่ได้จัดเก็บไว้ที่อื่น ด้านล่างนี้คือรูปแบบทั่วไปของฟังก์ชัน push() และ pop() ที่ทำงานบนอาร์เรย์จำนวนเต็ม สแต็กข้อมูลประเภทอื่นๆ สามารถจัดระเบียบได้โดยการเปลี่ยนประเภทข้อมูลพื้นฐานของอาร์เรย์

int ถึง = 0; /* ด้านบนของสแต็ก */

/* ผลักองค์ประกอบลงบนสแต็ก */

โมฆะผลักดัน (int i)

ถ้า(tos >= MAX) (

printf("สแต็คเต็ม\n");

/* รับองค์ประกอบด้านบนของสแต็ก */

ถ้า(tos< 0) {

printf("สแต็คว่างเปล่า\n");

กองกลับ;

ตัวแปร tos ("ด้านบนของสแต็ก") มีดัชนีด้านบนของสแต็ก เมื่อใช้ฟังก์ชันเหล่านี้ จำเป็นต้องคำนึงถึงกรณีที่สแต็กเต็มหรือว่างเปล่า ในกรณีของเรา สัญญาณของสแต็กว่างคือ tos เท่ากับศูนย์ และสัญญาณของสแต็กล้นคือ to เพิ่มขึ้นมากจนค่าของมันจะชี้ไปที่ใดที่หนึ่งเลยเซลล์สุดท้ายของอาร์เรย์

ตัวอย่างการทำงานกับสแต็ก

สแตกจะอยู่ในหน่วยความจำที่จัดสรรแบบไดนามิก และไม่ใช่ในอาร์เรย์ที่มีขนาดคงที่ แม้ว่าตัวอย่างง่ายๆ นี้จะไม่จำเป็นต้องใช้การจัดสรรหน่วยความจำแบบไดนามิก เราจะมาดูวิธีใช้หน่วยความจำแบบไดนามิกเพื่อจัดเก็บข้อมูลสแต็ก

/* เครื่องคิดเลขง่ายๆ ที่มีสี่ขั้นตอน */

#รวม

#รวม

อินท์ *p; /* ตัวชี้ไปยังพื้นที่หน่วยความจำว่าง */

int *ถึง; /* ตัวชี้ไปที่ด้านบนของสแต็ก */

int *บอส; /* ตัวชี้ไปที่ด้านล่างของสแต็ก */

โมฆะผลักดัน (int i);

p = (int *) malloc(สูงสุด*ขนาดของ(int)); /* รับหน่วยความจำสำหรับสแต็ก */

printf("เกิดข้อผิดพลาดขณะจัดสรรหน่วยความจำ\n");

บอส = p + MAX-1;

printf("เครื่องคิดเลขสี่ขั้นตอน\n");

printf("กด "q" เพื่อออก\n");

printf("%d\n", a+b);

printf("%d\n", b-a);

printf("%d\n", b*a);

printf("หารด้วย 0.\n");

printf("%d\n", b/a);

case ".": /* แสดงเนื้อหาที่อยู่ด้านบนของ stack */

printf("ค่าปัจจุบันที่ด้านบนของสแต็ก: %d\n", a);

) ในขณะที่(*s != "q");

/* ผลักองค์ประกอบลงบนสแต็ก */

โมฆะผลักดัน (int i)

ถ้า(p > บอส) (

printf("สแต็คเต็ม\n");

/* รับองค์ประกอบด้านบนจากสแต็ก */

ถ้า(น< tos) {

printf("สแต็คว่างเปล่า\n");

คิว.

คิวคือรายการข้อมูลเชิงเส้นที่ได้รับการประมวลผลแบบเข้าก่อนออกก่อน หลักการนี้ (และคิวที่เป็นโครงสร้างข้อมูล) บางครั้งเรียกว่า FIFO ซึ่งหมายความว่าองค์ประกอบแรกที่อยู่ในคิวจะได้รับจากองค์ประกอบนั้นก่อน องค์ประกอบที่สองที่วางจะถูกลบออกในลำดับที่สอง เป็นต้น นี่เป็นวิธีเดียวที่จะทำงานกับคิวได้ ไม่อนุญาตให้เข้าถึงแต่ละองค์ประกอบโดยสุ่ม

ลองนึกภาพว่าคิวทำงานอย่างไร ขอแนะนำสองฟังก์ชัน: qstore() และ qretrieve() (จาก "store" - "save", "retrieve" - ​​​​"receive") ฟังก์ชัน qstore() วางองค์ประกอบไว้ที่ส่วนท้ายของคิว และฟังก์ชัน qretrieve() จะลบองค์ประกอบออกจากจุดเริ่มต้นของคิวและส่งกลับค่าของมัน ตารางแสดงลำดับของการดำเนินการดังกล่าว

การกระทำ เนื้อหาคิว
คิวสโตร์(A)
คิวสโตร์(B) เอบี
คิวสโตร์(C) เอ บี ซี
qretrieve() ส่งคืน A บี ซี
คิวสโตร์(D) บี ซี ดี
qretrieve() ส่งคืน B ซีดี
qretrieve() ส่งคืน C ดี

โปรดทราบว่าการดำเนินการดึงข้อมูลจะลบองค์ประกอบออกจากคิวและทำลายองค์ประกอบนั้น เว้นแต่จะถูกเก็บไว้ที่อื่น ดังนั้นหลังจากดึงข้อมูลองค์ประกอบทั้งหมดแล้ว คิวจะว่างเปล่า

ในการเขียนโปรแกรม คิวถูกใช้เพื่อแก้ไขปัญหาต่างๆ มากมาย งานประเภทหนึ่งที่ได้รับความนิยมมากที่สุดคือการจำลอง คิวยังใช้ในตัวกำหนดเวลางานของระบบปฏิบัติการและในการบัฟเฟอร์ I/O

/* ตัวกำหนดเวลากิจกรรมขนาดเล็ก */

#รวม

#รวม

#รวม

#รวม

ถ่าน *p, *qretrieve(โมฆะ);

เป็นโมฆะป้อน (เป็นโมฆะ), qstore (ถ่าน * q), ทบทวน (เป็นโมฆะ), ลบ_ap (เป็นโมฆะ);

สำหรับ(t=0; เสื้อ< MAX; ++t) p[t] = NULL; /* иницилизировать массив

พอยน์เตอร์ว่าง */

printf("ป้อน (E), รายการ (L), ลบ (R), ออก (Q): ");

*s = ท็อปเปอร์(*s);

/* แทรกการนัดหมายใหม่ลงในคิว */

เป็นโมฆะป้อน (เป็นโมฆะ)

printf("ป้อนการนัดหมาย %d: ", spos+1);

if(*s==0) ​​​​แตก; /* ไม่มีการบันทึก */

p = (ถ่าน *) malloc(strlen(s)+1);

printf("หน่วยความจำไม่เพียงพอ\n");

ถ้า(*s) qstore(p);

/* ดูเนื้อหาของคิว */

การตรวจสอบเป็นโมฆะ (เป็นโมฆะ)

สำหรับ(t=rpos; t< spos; ++t)

printf("%d. %s\n", t+1, p[t]);

/* ลบการนัดหมายออกจากคิว */

เป็นโมฆะ Delete_ap (เป็นโมฆะ)

if((p=qretrieve())==NULL) กลับ;

printf("%s\n", p);

/* ใส่การนัดหมาย */

เป็นโมฆะ qstore (ถ่าน * q)

printf("รายการเต็ม\n");

/* รับการนัดหมาย */

ถ่าน *qretrieve(เป็นโมฆะ)

ถ้า(rpos==spos) (

printf("ไม่มีการประชุมอีกต่อไป\n");

กลับพี;

รายการ.

รายการวงจรที่เชื่อมโยงเดี่ยวคือการประกาศโครงสร้างแบบเรียกซ้ำหรือเป็นตัวชี้ไปยังโครงสร้างประเภทนั้นเอง:

int data;//ช่องข้อมูล

s *ถัดไป;//องค์ประกอบถัดไป

) *first,*curr;//องค์ประกอบแรกและปัจจุบัน

การเริ่มต้น:

ครั้งแรก -> ถัดไป = สกุลเงิน;

เพื่อรับองค์ประกอบแรกให้ใช้ first->data

เพื่อเพิ่มองค์ประกอบใหม่: curr->next=new s;

curr=curr->next;//ไปที่อันสุดท้าย

และเพื่อให้ได้องค์ประกอบที่ 50 ให้วนซ้ำรายการ:

curr=first;//ไปที่อันดับแรก

สำหรับ(int i=0;i<50;i++)

ถ้า(curr->ถัดไป!=NULL)

curr=curr->ถัดไป;


ข้อมูลที่เกี่ยวข้อง.


ครั้งแรกบนเว็บไซต์นี้ เอาล่ะไปกันเลย

ฉันยังใหม่กับ C++ และกำลังเขียนหนังสือ "โครงสร้างข้อมูลโดยใช้ C++ 2nd ed, D.S. Malik"

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

Int *บอร์ด;

จากนั้นใช้ for-loop เพื่อสร้าง "คอลัมน์" เมื่อใช้อาร์เรย์ของพอยน์เตอร์เป็น "แถว"

วิธีที่สอง คุณใช้ตัวชี้ไปยังตัวชี้

Int **บอร์ด; บอร์ด = int ใหม่* ;

คำถามของฉันคือ: วิธีไหนดีกว่ากัน? วิธี ** นั้นง่ายกว่าสำหรับฉันที่จะเห็นภาพ แต่วิธีแรกสามารถใช้ได้ในลักษณะเดียวกันมาก ทั้งสองวิธีสามารถใช้เพื่อสร้างอาร์เรย์ 2 มิติแบบไดนามิกได้

แก้ไข: ไม่ชัดเจนเพียงพอตามที่ระบุไว้ข้างต้น นี่คือรหัสที่ฉันลอง:

แถว Int, คอลัมน์; ศาล<< "Enter row size:"; cin >>แถว; ศาล<< "\ncol:"; cin >>คอล; int *p_board; สำหรับ (int i=0; i< row; i++) p_board[i] = new int; for (int i=0; i < row; i++) { for (int j=0; j < col; j++) { p_board[i][j] = j; cout << p_board[i][j] << " "; } cout << endl; } cout << endl << endl; int **p_p_board; p_p_board = new int* ; for (int i=0; i < row; i++) p_p_board[i] = new int; for (int i=0; i < row; i++) { for (int j=0; j < col; j++) { p_p_board[i][j] = j; cout << p_p_board[i][j] << " "; } cout << endl; }

4 คำตอบ

วิธีแรกไม่สามารถใช้เพื่อสร้างได้ พลวัตอาร์เรย์ 2 มิติเพราะ:

Int *บอร์ด;

คุณได้จัดสรรอาร์เรย์ของพอยน์เตอร์ 4 ตัวให้กับ int ต่อกอง. ดังนั้นหากคุณเติมพอยน์เตอร์ทั้ง 4 ตัวเหล่านี้ด้วยอาเรย์แบบไดนามิก:

สำหรับ (int i = 0; i< 4; ++i) { board[i] = new int; }

สิ่งที่คุณจะได้คืออาร์เรย์ 2 มิติ คงที่จำนวนบรรทัด (ในกรณีนี้คือ 4) และ พลวัตจำนวนคอลัมน์ (ในกรณีนี้คือ 10) ดังนั้นไดนามิกจึงไม่ใช่ อย่างเต็มที่เนื่องจากเมื่อทำการจัดสรรอาร์เรย์บนสแต็กคุณ ต้องระบุ ขนาดคงที่, เช่น. รู้จักกันใน เวลา. พลวัตอาร์เรย์ถูกเรียกว่า พลวัตเพราะไม่จำเป็นต้องรู้ขนาดของมัน รวบรวมเวลาแต่สามารถกำหนดได้ด้วยตัวแปรบางตัวใน ระหว่างการดำเนินการ.

อีกครั้งเมื่อคุณทำ:

Int *บอร์ด;

ค่าคงที่ x = 4; //<--- `const` qualifier is absolutely needed in this case! int *board[x];

คุณระบุค่าคงที่ที่ทราบมา รวบรวมเวลา(ในกรณีนี้คือ 4 หรือ x) เพื่อให้คอมไพเลอร์สามารถทำได้ในขณะนี้ เลือกไว้ล่วงหน้าหน่วยความจำนี้สำหรับอาเรย์ของคุณ และเมื่อโปรแกรมของคุณถูกโหลดเข้าสู่หน่วยความจำ มันก็จะมีหน่วยความจำสำหรับอาเรย์บอร์ดเท่านี้อยู่แล้ว จึงเรียกว่า คงที่, เช่น. เพราะขนาด ฮาร์ดโค้ดและ ไม่สามารถเปลี่ยนแปลงแบบไดนามิกได้(ที่รันไทม์)

ในทางกลับกัน เมื่อคุณทำ:

Int **บอร์ด; บอร์ด = int ใหม่*;

อินท์ x = 10; //<--- Notice that it does not have to be `const` anymore! int **board; board = new int*[x];

คอมไพเลอร์ไม่ทราบว่าอาร์เรย์บอร์ดจะต้องใช้หน่วยความจำเท่าใดดังนั้นจึงไม่ทราบ จัดสรรไว้ล่วงหน้าทั้งหมด. แต่เมื่อคุณรันโปรแกรม ขนาดของอาเรย์จะถูกกำหนดโดยค่าของตัวแปร x (ที่รันไทม์) และพื้นที่ที่สอดคล้องกันสำหรับอาเรย์บอร์ดจะถูกจัดสรรให้กับสิ่งที่เรียกว่า พวง- พื้นที่หน่วยความจำที่โปรแกรมทั้งหมดที่ทำงานบนคอมพิวเตอร์ของคุณสามารถจัดสรรได้ ไม่ทราบล่วงหน้า(ณ เวลาคอมไพล์) สรุปความจำเพื่อการใช้งานส่วนตัว

ด้วยเหตุนี้ หากต้องการสร้างอาร์เรย์ 2D แบบไดนามิก คุณต้องใช้วิธีที่สอง:

Int **บอร์ด; บอร์ด = int ใหม่*; // อาร์เรย์ไดนามิก (ขนาด 10) ของพอยน์เตอร์เป็น int for (int i = 0; i< 10; ++i) { board[i] = new int; // each i-th pointer is now pointing to dynamic array (size 10) of actual int values }

เราเพิ่งสร้างอาร์เรย์ 2 มิติขนาด 10 คูณ 10 ขึ้นมา หากต้องการผ่านมันและเติมด้วยค่าจริง เช่น 1 เราสามารถใช้ลูปที่ซ้อนกันได้:

สำหรับ (int i = 0; i< 10; ++i) { // for each row for (int j = 0; j < 10; ++j) { // for each column board[i][j] = 1; } }

สิ่งที่คุณอธิบายสำหรับวิธีที่สองสร้างเฉพาะอาร์เรย์ 1D เท่านั้น:

Int *board = int ใหม่;

สิ่งนี้เพียงจัดสรรอาร์เรย์ด้วย 10 องค์ประกอบ บางทีคุณอาจหมายถึงบางสิ่งเช่นนี้:

Int **board = int ใหม่*; สำหรับ (int i = 0; i< 4; i++) { board[i] = new int; }

ในกรณีนี้ เราจัดสรร 4 int* จากนั้นแต่ละจุดไปยังอาร์เรย์ที่จัดสรรแบบไดนามิก 10 int

ตอนนี้เราเปรียบเทียบสิ่งนี้กับบอร์ด int*; . ข้อแตกต่างที่สำคัญคือเมื่อใช้อาร์เรย์ดังกล่าว จะต้องทราบจำนวน "แถว" ณ เวลาคอมไพล์ เนื่องจากอาร์เรย์ต้องมีขนาดเวลาคอมไพล์คงที่ คุณอาจประสบปัญหาหากคุณต้องการส่งคืนอาร์เรย์นี้จาก int* s เนื่องจากอาร์เรย์จะถูกทำลายเมื่อสิ้นสุดขอบเขต

วิธีการจัดสรรทั้งแถวและคอลัมน์แบบไดนามิกจำเป็นต้องมีการวัดที่ซับซ้อนมากขึ้นเพื่อหลีกเลี่ยงการรั่วไหลของหน่วยความจำ คุณควรเพิ่มหน่วยความจำดังนี้:

สำหรับ (int i = 0; i< 4; i++) { delete board[i]; } delete board;

เลยต้องแนะนำให้ใช้ภาชนะมาตรฐานแทน คุณสามารถใช้ std::array 4> หรืออาจเป็น std::vector > ซึ่งคุณเริ่มต้นด้วยขนาดที่เหมาะสม

ในทั้งสองกรณี มิติภายในของคุณสามารถตั้งค่าแบบไดนามิกได้ (เช่น นำมาจากตัวแปร) แต่ความแตกต่างอยู่ที่มิติภายนอก

คำถามนี้โดยพื้นฐานแล้วเทียบเท่ากับสิ่งต่อไปนี้:

คือ int* x = int ใหม่; "ดีกว่า" มากกว่า int x ?

คำตอบคือ "ไม่ เว้นแต่คุณจะต้องเลือกขนาดอาเรย์นั้นแบบไดนามิก"

รหัสนี้ทำงานได้ดีกับข้อกำหนดไลบรารีภายนอกน้อยมาก และแสดงการใช้งานพื้นฐานของ int **array

คำตอบนี้แสดงว่าอาร์เรย์ แต่ละมีขนาดไดนามิกและวิธีการกำหนดอาร์เรย์เชิงเส้นที่มีขนาดไดนามิกให้กับอาร์เรย์สาขาที่มีขนาดไดนามิก

โปรแกรมนี้รับอาร์กิวเมนต์จาก STDIN ในรูปแบบต่อไปนี้:

2 2 3 1 5 4 5 1 2 8 9 3 0 1 1 3

รหัสโปรแกรมอยู่ด้านล่าง...

#รวม int main() ( int **array_of_arrays; int num_arrays, num_queries; num_arrays = num_queries = 0; std::cin >> num_arrays >> num_queries; //std::cout<< num_arrays << " " << num_queries; //Process the Arrays array_of_arrays = new int*; int size_current_array = 0; for (int i = 0; i < num_arrays; i++) { std::cin >> size_current_array; int *tmp_array = int ใหม่; สำหรับ (int j = 0; j< size_current_array; j++) { int tmp = 0; std::cin >>ทีเอ็มพี; tmp_array[j] = tmp; ) array_of_arrays[i] = tmp_array; ) //ประมวลผลแบบสอบถาม int x, y; x = ย = 0; สำหรับ (int q = 0; q< num_queries; q++) { std::cin >> x >> ย; //std::cout<< "Current x & y: " << x << ", " << y << "\n"; std::cout << array_of_arrays[x][y] << "\n"; } return 0; }

นี่เป็นการใช้งานที่ง่ายมากของ int main และขึ้นอยู่กับ std::cin และ std::cout เท่านั้น แบร์โบน แต่ก็ดีพอที่จะแสดงวิธีการทำงานกับอาร์เรย์หลายมิติอย่างง่าย