Mencipta tatasusunan dinamik dua dimensi dalam c. Tatasusunan dinamik dua dimensi

Biasanya, jumlah memori yang diperlukan untuk pembolehubah tertentu ditentukan sebelum proses penyusunan dengan mengisytiharkan pembolehubah itu. Sekiranya terdapat keperluan untuk mencipta pembolehubah yang saiznya tidak diketahui terlebih dahulu, maka memori dinamik digunakan. Tempahan Dan pembebasan masalah ingatan dalam program C++ boleh berlaku pada bila-bila masa. Operasi dijalankan pengedaran ingatan dalam dua cara:

  • menggunakan fungsi tersebut malloc, calloc, realloc Dan percuma;
  • melalui operator baru Dan padam.

Fungsi malloc rizab blok bersebelahan sel memori untuk penyimpanan objek yang ditentukan dan mengembalikan penunjuk ke sel pertama blok ini. Panggilan ke fungsi kelihatan seperti:

void *mallok(saiz);

Di sini saiz- nilai integer tidak bertanda yang menentukan saiz kawasan memori yang diperuntukkan dalam bait. Jika tempahan memori berjaya, fungsi itu kembali pembolehubah jenis batal *, yang boleh dikurangkan kepada mana-mana jenis yang diperlukan penunjuk.

Fungsi - calloc juga bertujuan untuk peruntukan memori. Entri di bawah bermakna ia akan diserlahkan bilangan unsur oleh saiz bait.

void *calloc(nime, size);

Fungsi ini mengembalikan penunjuk ke kawasan yang dipilih atau NULL apabila mustahil untuk memperuntukkan ingatan. Ciri khas fungsi ini adalah untuk menetapkan semula semua elemen yang dipilih kepada sifar.

Fungsi reallocubah saiz ingatan yang diperuntukkan sebelum ini. Mereka memanggilnya seperti ini:

char *realloc (kosong *p, saiz);

Di sini hlm- penunjuk ke kawasan memori yang saiznya perlu ditukar saiz. Jika alamat kawasan memori berubah akibat daripada fungsi, maka alamat baru akan kembali sebagai hasilnya. Jika nilai sebenar parameter pertama NULL, kemudian fungsi realloc berfungsi sama seperti fungsinya malloc, iaitu, ia memperuntukkan kawasan memori saiz saiz bait.

Untuk membebaskan memori yang diperuntukkan, gunakan fungsi percuma. Mereka memanggilnya seperti ini:

kosong percuma(kosong *saiz p);

Di sini hlm- penunjuk ke lokasi memori yang diperuntukkan sebelum ini oleh fungsi malloc, calloc atau realloc.

Operator baru Dan padam fungsi yang serupa malloc Dan percuma. Baru memperuntukkan memori, dan satu-satunya hujahnya ialah ungkapan yang menyatakan bilangan bait yang akan dikhaskan. Operator mengembalikan penunjuk ke permulaan blok memori yang diperuntukkan. Operator padam membebaskan memori, hujahnya ialah alamat sel pertama blok yang perlu dibebaskan.

Tatasusunan dinamik- tatasusunan panjang berubah-ubah, memori yang diperuntukkan semasa pelaksanaan program. Peruntukan memori dijalankan oleh fungsi calloc, malloc atau pengendali baru. Alamat elemen pertama lokasi memori yang diperuntukkan disimpan dalam pembolehubah yang diisytiharkan sebagai penunjuk. Sebagai contoh, pernyataan berikut bermaksud bahawa penunjuk diterangkan mas dan ia diberikan alamat permulaan kawasan bersebelahan ingatan dinamik, diserlahkan menggunakan operator baru:

int *mas=int baharu;

Jumlah memori yang diperuntukkan adalah mencukupi untuk menyimpan 10 nilai int.

Malah, dalam pembolehubah mas alamat disimpan unsur sifar tatasusunan dinamik. Oleh itu, alamat elemen pertama seterusnya dalam kawasan memori yang diperuntukkan ialah mas+1, a mas+i ialah alamat unsur ke-i. Elemen ke-i tatasusunan dinamik boleh diakses seperti biasa dengan mas[i], atau dengan cara lain *(mas +i) . Adalah penting untuk memastikan bahawa anda tidak melebihi sempadan kawasan memori yang diperuntukkan.

Bila tatasusunan dinamik(pada bila-bila masa semasa operasi program) tidak lagi diperlukan, maka memori boleh dibebaskan menggunakan fungsi tersebut percuma atau pengendali padam.

Saya mencadangkan untuk mempertimbangkan beberapa tugasan yang mengukuhkan pelajaran ini:

Masalah 1

Cari jumlah unsur sebenar tatasusunan dinamik.

//Contoh penggunaan fungsi malloc dan percuma #include "stdafx.h" #include menggunakan ruang nama std; int main() ( setlocale(LC_ALL,"Rus"); int i, n; float *a; //penunjuk ke float float s; cout<<"\n"; cin>>n; //memasukkan saiz tatasusunan //memperuntukkan memori untuk tatasusunan n elemen nyata a=(float *)malloc(n*sizeof(float)); cout<<"Введите массив A \n"; //ввод элементов массива for (i=0; i>*(a+i); ) //mengumpul jumlah elemen tatasusunan untuk (s=0, i=0; i

//Contoh penggunaan malloc dan fungsi bebas

#include "stdafx.h"

#termasuk

menggunakan ruang nama std ;

int utama()

int i, n;

terapung * a ; //penunjuk untuk terapung

terapung s ;

cout<< "\n" ; cin >> n ; //masukkan saiz tatasusunan

//memperuntukkan memori untuk tatasusunan n elemen sebenar

a = (float * ) malloc (n * sizeof (float ) );

cout<< "Masukkan tatasusunan A\n";

//masukan elemen tatasusunan

untuk (i = 0 ; i< n ; i ++ )

cin >> * (a + i);

//pengumpulan jumlah elemen tatasusunan

untuk (s = 0 , i = 0 ; i< n ; i ++ )

s += * (a + i) ;

//keluarkan nilai amaun

cout<< "S=" << s << "\n" ;

//membebaskan ingatan

percuma(a);

sistem("jeda");

pulangan 0;

Masalah 2

Ubah suai tatasusunan integer yang dinamik supaya unsur positifnya menjadi negatif dan begitu juga sebaliknya. Untuk menyelesaikan masalah, kami akan mendarabkan setiap elemen dengan -1.

//Contoh menggunakan operator baharu dan padamkan #include "stdafx.h" #include menggunakan ruang nama std; int main() ( setlocale(LC_ALL,"Rus"); int i, n; //masukkan bilangan elemen tatasusunan cout<<"n="; cin>>n; //memori allocation int *a=new int[n]; cout<<"Введите элементы массива:\n"; //ввод массива for (i=0; i>a[i]; //keluarkan tatasusunan yang ditentukan untuk (i=0; i

//Contoh menggunakan operator baharu dan padam

#include "stdafx.h"

#termasuk

menggunakan ruang nama std ;

int utama()

setlocale(LC_ALL, "Rus");

int i, n;

//masukkan bilangan elemen tatasusunan

cout<< "n=" ; cin >> n ;

//peruntukan ingatan

int * a = new int [n] ;

cout<< "Masukkan elemen tatasusunan:\n";

// tatasusunan input

Semasa mengumpul maklumat untuk menulis artikel ini, saya teringat kenalan pertama saya dengan petunjuk - Saya sangat sedih... Oleh itu, selepas membaca beberapa bahagian mengenai topik ini dari pelbagai buku tentang pengaturcaraan dalam C++, ia telah memutuskan untuk mengambil laluan yang berbeza dan membentangkan topik Penunjuk C++ mengikut susunan yang saya anggap perlu. Saya akan memberi anda takrifan ringkas serta-merta dan kami akan melihat petunjuk dalam tindakan menggunakan contoh. Artikel seterusnya () akan menggariskan nuansa, penggunaan penunjuk dengan rentetan gaya C (tatasusunan aksara) dan perkara utama yang perlu diingat.

Penunjuk dalam C++ ialah pembolehubah yang menyimpan alamat data (nilai) dalam ingatan, dan bukan data itu sendiri.

Selepas melihat contoh berikut, anda akan memahami perkara utama - mengapa kita memerlukan petunjuk dalam pengaturcaraan, cara mengisytiharkan dan menggunakannya.

Katakan dalam atur cara kita perlu mencipta tatasusunan integer, saiz sebenar yang tidak kita ketahui sebelum atur cara bermula. Iaitu, kita tidak tahu berapa banyak nombor yang pengguna perlu masukkan ke dalam tatasusunan ini. Sudah tentu, kita boleh memainkannya dengan selamat dan mengisytiharkan tatasusunan beberapa ribu elemen (contohnya, 5,000). Ini (menurut pendapat subjektif kami) sepatutnya cukup untuk pengguna berfungsi. Ya - sememangnya - ini mungkin cukup. Tetapi jangan lupa bahawa tatasusunan ini akan mengambil banyak ruang dalam RAM (5,000 * 4 (jenis int) = 20,000 bait). Kami telah menjamin diri kami sendiri, dan pengguna hanya akan mengisi 10 elemen tatasusunan kami. Ternyata sebenarnya terdapat 40 bait sedang digunakan, dan 19,960 bait membazirkan memori.

penggunaan RAM yang tidak munasabah

#termasuk menggunakan ruang nama std; int main() ( setlocale(LC_ALL, "rus"); const int SizeOfArray = 5000; int arrWithDigits = (); cout<< "Массив занял в памяти " << sizeof(arrWithDigits) << " байт" << endl; int amount = 0; cout << "Сколько чисел вы введёте в массив? "; cin >>jumlah; cout<< "Реально необходимо " << amount * sizeof(int) << " байт" << endl; for (int i = 0; i < amount; i++) { cout << i + 1 << "-е число: "; cin >> arrWithDigits[i]; ) cout<< endl; for (int i = 0; i < amount; i++) { cout << arrWithDigits[i] << " "; } cout << endl; return 0; }

#termasuk

menggunakan ruang nama std ;

int utama()

const int SizeOfArray = 5000 ;

int arrWithDigits [ SizeOfArray ] = ( );

cout<< "Susun atur yang diduduki dalam ingatan"<< sizeof (arrWithDigits ) << " байт" << endl ;

int jumlah = 0;

cout<< "Berapa nombor yang akan anda masukkan ke dalam tatasusunan?";

cin >> jumlah ;

cout<< "Sangat perlu"<< amount * sizeof (int ) << " байт" << endl ;

untuk (int i = 0 ; i< amount ; i ++ )

cout<< i + 1 << "-е число: " ;

cin >> arrWithDigits [ i ] ;

cout<< endl ;

untuk (int i = 0 ; i< amount ; i ++ )

cout<< arrWithDigits [ i ] << " " ;

cout<< endl ;

pulangan 0;

Kepada fungsi perpustakaan standard saiz() melepasi tatasusunan yang diisytiharkan arrWithDigits baris 10. Ia akan kembali ke tempat panggilan saiz dalam bait yang tatasusunan ini menduduki dalam ingatan. Kepada soalan "Berapa banyak nombor yang akan anda masukkan ke dalam tatasusunan?" jawapannya ialah 10. Dalam baris 15, ungkapan jumlah * saiz(int) akan menjadi bersamaan dengan 10 * 4, sejak fungsi sizeof(int) akan mengembalikan 4 (saiz dalam bait jenis int). Seterusnya, masukkan nombor dari papan kekunci dan program akan memaparkannya pada skrin. Ternyata baki 4990 elemen akan menyimpan sifar. Jadi tidak ada gunanya menunjukkan kepada mereka.

Maklumat utama pada skrin: tatasusunan mengambil 20,000 bait, tetapi sebenarnya ia memerlukan 40 bait. Bagaimana untuk keluar dari situasi ini? Seseorang mungkin ingin menulis semula atur cara supaya pengguna memasukkan saiz tatasusunan daripada papan kekunci dan, selepas memasukkan nilai, mengisytiharkan tatasusunan dengan bilangan elemen yang diperlukan. Tetapi ini tidak boleh dilakukan tanpa petunjuk. Seperti yang anda ingat, saiz tatasusunan mestilah pemalar. Iaitu, pemalar integer mesti dimulakan sebelum tatasusunan diisytiharkan dan kami tidak boleh menggesa inputnya daripada papan kekunci. Eksperimen dan semak.


Di sini pengendali menyalakan kami dengan warna merah >> kerana nilai tetap tidak boleh diubah.

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


Di sini kita diberi amaran bahawa saiz tatasusunan tidak boleh menjadi nilai pembolehubah biasa. Nilai berterusan diperlukan!

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

Dalam kod berikut kami akan menggunakan penunjuk dan pengendali yang baharu kepada anda baru(memperuntukkan ingatan) dan padam(membebaskan ingatan).

penggunaan pintar RAM menggunakan penunjuk

#termasuk #termasuk menggunakan ruang nama std; int main() ( setlocale(LC_ALL, "rus"); int sizeOfArray = 0; // saiz tatasusunan (dimasukkan oleh pengguna) cout<< "Чтобы создать массив чисел, введите его размер: "; cin >> sizeOfArray; // PERHATIAN! int* arrWithDigits - pengisytiharan penunjuk // kepada sekeping memori yang akan diperuntukkan int baharu* arrWithDigits = new int ; untuk (int i = 0; i< sizeOfArray; i++) { arrWithDigits[i] = i + 1; cout << arrWithDigits[i] << " "; } cout << endl; delete arrWithDigits; // освобождение памяти return 0; }

#termasuk

#termasuk

menggunakan ruang nama std ;

int utama()

setlocale(LC_ALL, "rus");

int sizeOfArray = 0 ; // saiz tatasusunan (dimasukkan oleh pengguna)

cout<< "Untuk membuat susunan nombor, masukkan saiznya: ";

cin >> sizeOfArray ;

// PERHATIAN! int* arrWithDigits - pengisytiharan penunjuk

// kepada sekeping memori yang baru akan diperuntukkan

int * arrWithDigits = new int [ sizeOfArray ] ;

untuk (int i = 0 ; i< sizeOfArray ; i ++ )

arrWithDigits[i] = i+1;

cout<< arrWithDigits [ i ] << " " ;

cout<< endl ;

padamkan arrWithDigits ; // membebaskan ingatan

pulangan 0;

Pengguna memasukkan nilai dari papan kekunci - baris 12. Penunjuk ditakrifkan di bawah: int * arrWithDigits Entri ini bermaksud begitu arrWithDigits ialah penunjuk. Ia dicipta untuk menyimpan alamat sel di mana integer akan ditempatkan. Dalam kes kita arrWithDigits akan menunjuk ke sel tatasusunan dengan indeks 0. Tanda * - sama seperti digunakan untuk pendaraban. Berdasarkan konteks, pengkompil akan "memahami" bahawa ini adalah pengisytiharan penunjuk dan bukan pendaraban. Seterusnya datang tanda = dan pengendali baru, yang memperuntukkan secebis ingatan. Kami ingat bahawa memori kami harus diperuntukkan untuk tatasusunan, dan bukan untuk satu nombor. Rekod int baharu [sizeOfArray] boleh ditafsirkan seperti ini: baru(peruntukkan ingatan) int(untuk menyimpan integer) (dalam kuantiti sizeOfArray ).

Oleh itu, dalam baris 16 ia ditakrifkan tatasusunan dinamik. Ini bermakna bahawa memori untuknya akan diperuntukkan (atau tidak diperuntukkan) semasa program sedang berjalan, dan bukan semasa penyusunan, seperti yang berlaku dengan tatasusunan biasa. Iaitu, peruntukan memori bergantung kepada pembangunan program dan keputusan yang dibuat secara langsung dalam operasinya. Dalam kes kami, ia bergantung pada apa yang pengguna masukkan ke dalam pembolehubah sizeOfArray

Talian 25 menggunakan operator padam. Ia melepaskan operator yang diperuntukkan baru ingatan. Kerana baru memori yang diperuntukkan untuk menyimpan tatasusunan, kemudian apabila membebaskannya, anda perlu menjelaskan kepada pengkompil bahawa perlu membebaskan memori tatasusunan, dan bukan hanya sel sifarnya, yang ditunjuk kepada arrWithDigits. Oleh itu, antara padam dan nama penunjuk diletakkan dalam kurungan segi empat sama padamkan arrWithDigits ; Ingat bahawa setiap kali memori diperuntukkan menggunakan baru, anda perlu membebaskan memori ini menggunakan padam. Sudah tentu, apabila program ditamatkan, memori yang didudukinya akan dibebaskan secara automatik. Tetapi jadikan ia satu tabiat yang baik untuk menggunakan pengendali baru Dan padam berpasangan dengan. Lagipun, program boleh mengandungi 5-6 tatasusunan, sebagai contoh. Dan jika anda mengosongkan memori setiap kali ia tidak lagi diperlukan pada masa hadapan dalam program yang sedang berjalan, memori akan digunakan dengan lebih bijak.

Katakan dalam program kami, kami mengisi tatasusunan dengan sepuluh nilai. Seterusnya, kami mengira jumlah mereka dan merekodkannya dalam beberapa pembolehubah. Dan itu sahaja - kami tidak akan bekerja dengan tatasusunan ini lagi. Program ini terus berfungsi dan tatasusunan dinamik baharu dicipta di dalamnya untuk tujuan tertentu. Dalam kes ini, adalah dinasihatkan untuk membebaskan memori yang diduduki oleh tatasusunan pertama. Kemudian, apabila memperuntukkan memori untuk tatasusunan lain, memori ini boleh digunakan semula dalam atur cara.

Mari kita pertimbangkan penggunaan penunjuk sebagai parameter fungsi. Untuk bermula, taip dan susun kod berikut. Di dalamnya, fungsi menerima dua pembolehubah dan menawarkan untuk membuat perubahan pada nilainya.

cuba menukar pembolehubah yang dihantar ke fungsi

#termasuk #termasuk menggunakan ruang nama std; void changeData(int varForCh1, int varForCh2); int main() ( setlocale(LC_ALL, "rus"); int variableForChange_1 = 0; int variableForChange_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; cout<< "Введите новое значение второй переменной: "; cin >> varForCh2; )

#termasuk

#termasuk

menggunakan ruang nama std ;

void changeData (int varForCh1 , int varForCh2 );

int utama()

setlocale(LC_ALL, "rus");

int variableForChange_1 = 0 ;

int variableForChange_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 ;

pulangan 0;

void changeData(int varForCh1, int varForCh2)

cout<< "Masukkan nilai baharu untuk pembolehubah pertama: ";

cin >> varForCh1 ;

cout<< "Masukkan nilai baharu untuk pembolehubah kedua: ";

cin >> varForCh2 ;

Jalankan program dan masukkan nilai pembolehubah baharu. Akibatnya, anda akan melihat bahawa setelah selesai fungsi, pembolehubah tidak berubah dan sama dengan 0.

Seperti yang anda ingat, fungsi itu tidak berfungsi secara langsung dengan pembolehubah, tetapi mencipta salinan tepatnya. Salinan ini dimusnahkan selepas fungsi keluar. Iaitu, fungsi menerima beberapa pembolehubah sebagai parameter, mencipta salinannya, bekerja dengannya dan memusnahkannya. Pembolehubah itu sendiri akan kekal tidak berubah.

Menggunakan penunjuk, kita boleh menghantar alamat pembolehubah kepada fungsi. Kemudian fungsi itu akan dapat berfungsi secara langsung dengan data berubah-ubah di alamat. Jom buat perubahan pada program sebelumnya.

menukar nilai pembolehubah menggunakan penunjuk

#termasuk #termasuk menggunakan ruang nama std; void changeData(int* varForCh1, int* varForCh2); int main() ( setlocale(LC_ALL, "rus"); int variableForChange_1 = 0; int variableForChange_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; cout<< "Введите новое значение второй переменной: "; cin >> *varForCh2; )

Tujuan kuliah: pengisytiharan kajian, peruntukan dan pelepasan memori untuk tatasusunan dinamik satu dimensi, mengakses elemen, belajar menyelesaikan masalah menggunakan tatasusunan dinamik satu dimensi dalam bahasa C++.

Apabila menggunakan banyak struktur data, selalunya berlaku bahawa ia mesti mempunyai saiz berubah bergantung pada saiz struktur data. masa memimpin program. Dalam kes ini adalah perlu untuk digunakan peruntukan memori dinamik. Salah satu struktur data sedemikian yang paling biasa ialah tatasusunan, yang saiznya tidak ditentukan atau ditetapkan pada mulanya.

mengikut standard bahasa Tatasusunan ialah koleksi elemen, setiap satunya mempunyai atribut yang sama. Semua elemen ini diletakkan di lokasi memori bersebelahan dalam satu baris, bermula dari alamat yang sepadan dengan permulaan tatasusunan. Iaitu, jumlah bilangan elemen tatasusunan dan saiz memori yang diperuntukkan untuknya ditentukan secara lengkap dan unik oleh takrif tatasusunan. Tetapi ini tidak selalunya mudah. Kadangkala memori yang diperuntukkan untuk tatasusunan diperlukan untuk menyelesaikan masalah tertentu, dan saiznya tidak diketahui terlebih dahulu dan tidak boleh diperbaiki. Pembentukan tatasusunan dengan saiz berubah (tatasusunan dinamik) boleh diatur menggunakan penunjuk dan alat peruntukan memori dinamik.

Tatasusunan dinamik ialah tatasusunan yang saiznya tidak ditetapkan terlebih dahulu dan boleh berubah semasa pelaksanaan program. Untuk mengubah saiz tatasusunan dinamik bahasa pengaturcaraan C++, yang menyokong tatasusunan sedemikian, menyediakan khas fungsi terbina dalam atau operasi. Tatasusunan dinamik memberi peluang untuk kerja yang lebih fleksibel dengan data, kerana ia membolehkan anda tidak meramalkan volum data yang disimpan, tetapi untuk melaraskan saiz tatasusunan mengikut volum yang sebenarnya diperlukan.

Mengisytiharkan tatasusunan dinamik satu dimensi

Di bawah pengisytiharan satu dimensi tatasusunan dinamik memahami pengisytiharan penunjuk kepada pembolehubah jenis tertentu supaya pembolehubah ini boleh digunakan sebagai tatasusunan dinamik.

Sintaks:

Taip *ArrayName;

Jenis – jenis elemen yang diisytiharkan tatasusunan dinamik. elemen tatasusunan dinamik tidak boleh ada fungsi dan unsur taip void.

Sebagai contoh:

int *a; ganda *d;

Dalam contoh ini, a dan d adalah penunjuk kepada permulaan lokasi memori yang diperuntukkan. Penunjuk mengambil nilai alamat kawasan memori yang diperuntukkan untuk nilai jenis int dan jenis double, masing-masing.

Oleh itu, apabila memperuntukkan memori secara dinamik untuk tatasusunan dinamik, anda harus menerangkan penunjuk yang sepadan yang nilai alamat permulaan kawasan memori yang diperuntukkan akan diberikan.

Peruntukan memori untuk tatasusunan dinamik satu dimensi

Untuk memperuntukkan ingatan untuk satu dimensi tatasusunan dinamik Dalam C++ terdapat 2 cara.

1) secara operasi new , yang memperuntukkan bahagian memori dinamik dengan saiz yang sesuai untuk menyimpan tatasusunan dan tidak membenarkan elemen tatasusunan dimulakan.

Sintaks:

ArrayName = Jenis baru [ConstantTypeExpression];

ArrayName – pengecam tatasusunan, iaitu nama penunjuk untuk blok memori yang diperuntukkan.

TypeExpressionConstant– menetapkan bilangan elemen ( dimensi) tatasusunan. Ungkapan jenis malar dinilai pada masa penyusunan.

Sebagai contoh:

int *mas; mas = new int ; /*peruntukkan memori dinamik 100*sizeof(int) bytes*/ double *m = double [n] baharu; /*peruntukkan memori dinamik n*sizeof(double) bytes*/ panjang (*lm); lm = panjang baru ; /*peruntukkan memori dinamik 2*4*saiz(panjang) bait*/

Apabila memperuntukkan memori dinamik, dimensi tatasusunan mesti ditentukan sepenuhnya.

2) menggunakan fungsi perpustakaan malloc (calloc) , yang digunakan untuk memperuntukkan memori dinamik.

Sintaks:

ArrayName = (Jenis *) malloc(N*saiz(Jenis));

ArrayName = (Jenis *) calloc(N, saiz(Jenis));

ArrayName – pengecam tatasusunan, iaitu nama penunjuk untuk blok memori yang diperuntukkan.

Taip – ​​jenis penunjuk kepada tatasusunan.

N – bilangan elemen tatasusunan.

Sebagai contoh:

terapung *a; a=(float *)mallok(10*saiz(float)); // atau a=(float *)calloc(10,sizeof(float)); /*peruntukkan memori dinamik 10*saiz(terapung) bait*/

Oleh kerana fungsi malloc(calloc) kembali penunjuk tidak ditaip void * , maka ia adalah perlu untuk menukar yang terhasil

// pengisytiharan tatasusunan dinamik dua dimensi bagi 10 elemen:

terapung **ptrarray = apungan baharu* ; // dua baris dalam tatasusunan

untuk (int count = 0; count< 2; count++)

ptrarray = terapung baru; // dan lima lajur

// di mana ptrarray ialah tatasusunan penunjuk ke kawasan memori yang diperuntukkan untuk tatasusunan nombor nyata jenis apungan

Pertama, apungan penunjuk tertib kedua **ptrarray diisytiharkan, yang merujuk kepada tatasusunan penunjuk apungan*, dengan saiz tatasusunan ialah dua . Selepas itu, dalam gelung for, setiap baris tatasusunan diisytiharkan masuk baris 2 memori diperuntukkan untuk lima elemen. Hasilnya ialah ptrarray tatasusunan dinamik dua dimensi. Mari kita pertimbangkan contoh membebaskan memori yang diperuntukkan untuk tatasusunan dinamik dua dimensi.

// membebaskan memori yang diperuntukkan untuk tatasusunan dinamik dua dimensi:

untuk (int count = 0; count< 2; count++)

padam ptrarray;

// dengan 2 ialah bilangan baris dalam tatasusunan

#termasuk
#termasuk
#termasuk
batal utama()
{

int *a; // penunjuk kepada tatasusunan

sistem("chcp 1251");

scanf("%d", &n);

scanf("%d", &m);

// Peruntukan memori

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

// Memasukkan elemen tatasusunan

untuk(i=0; i

untuk(j=0; j

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

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

// Elemen tatasusunan output

untuk(i=0; i

untuk(j=0; j

printf("%5d ", *(a+i*m+j)); // 5 kenalan untuk elemen tatasusunan

getchar(); getchar();
}

Hasil pelaksanaan

Masukkan bilangan baris: 3

Masukkan bilangan lajur: 4

Satu lagi cara untuk memperuntukkan memori secara dinamik untuk tatasusunan dua dimensi juga boleh dilakukan - menggunakan tatasusunan penunjuk. Untuk melakukan ini, anda perlu:
- memperuntukkan blok RAM untuk pelbagai penunjuk;
- memperuntukkan blok RAM untuk tatasusunan satu dimensi, yang merupakan baris matriks yang diperlukan;
- tulis alamat baris ke dalam tatasusunan penunjuk.

Fungsi malloc() mengembalikan penunjuk ke bait pertama kawasan memori saiz saiz yang diperuntukkan daripada kawasan memori yang diperuntukkan secara dinamik. Jika tidak ada memori yang mencukupi dalam kawasan memori dinamik, penuding nol dikembalikan.

#termasuk
#termasuk
#termasuk
batal utama()
{

int**a; // penuding ke penuding kepada rentetan

sistem("chcp 1251");

printf("Masukkan bilangan baris: ");

scanf("%d", &n);

printf("Masukkan bilangan lajur: ");

scanf("%d", &m);

// Memperuntukkan memori untuk penunjuk kepada rentetan

a = (int**)malloc(n*saiz(int*));

// Memasukkan elemen tatasusunan

untuk(i=0; i

// Memperuntukkan memori untuk menyimpan rentetan

a[i] = (int*)mallok(m*saiz(int));

untuk(j=0; j

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

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

// Elemen tatasusunan output

untuk(i=0; i

untuk(j=0; j

printf("%5d ", a[i][j]); // 5 kenalan untuk elemen tatasusunan

percuma(a[i]); // membebaskan memori untuk rentetan

getchar(); getchar();
}

Hasil daripada melaksanakan program adalah serupa dengan kes sebelumnya.

Menggunakan peruntukan memori dinamik untuk penunjuk baris, anda boleh memperuntukkan tatasusunan percuma. Percuma ialah tatasusunan dua dimensi (matriks), saiz baris yang boleh berbeza. Kelebihan menggunakan tatasusunan percuma ialah anda tidak perlu memperuntukkan terlalu banyak memori komputer untuk menampung rentetan panjang maksimum yang mungkin. Malah, tatasusunan percuma ialah tatasusunan satu dimensi penunjuk kepada tatasusunan data satu dimensi.

penunjuk.

Penunjuk ialah pembolehubah yang nilainya ialah alamat tempat data berada. Alamat ialah nombor sel memori di dalam atau dari mana data berada.

Menurut jenis data dalam SI, penunjuk dibahagikan kepada:

Penunjuk yang ditaip ialah penunjuk yang mengandungi alamat data jenis tertentu (sistem atau pengguna).

Penunjuk yang tidak ditaip ialah penunjuk yang mengandungi alamat data jenis yang tidak ditentukan (hanya alamat).

Perisytiharan penunjuk;

Menetapkan penunjuk;

mengakses nilai yang terletak pada penunjuk. Pengisytiharan (huraian) penunjuk dalam bahasa SI mempunyai bentuk berikut:

Taip *nama [=value];

Apabila diisytiharkan, penunjuk dalam SI boleh dimulakan dengan menunjukkan nilai yang sepadan melalui tanda tugasan. Nilai ini mestilah alamat, ditulis dalam salah satu bentuk berikut:

Null (id NULL);

Satu lagi penunjuk;

Alamat berubah (melalui operasi mengambil alamat);

Ungkapan yang mewakili aritmetik penunjuk;

Alamat yang merupakan hasil daripada peruntukan memori dinamik.

#termasuk

int var; // pembolehubah integer sekata

int *ptrVar; // penunjuk integer (ptrVar mestilah jenis int, kerana ia akan merujuk kepada pembolehubah jenis int)

ptrVar = // memberikan penunjuk alamat sel memori di mana nilai pembolehubah var terletak

scanf("%d", &var); // pembolehubah var mengandungi nilai yang dimasukkan daripada papan kekunci

printf("%d\n", *ptrVar); // nilai keluaran melalui penunjuk

Keputusan pelaksanaan: 6 6

Kuliah No 3.

Fungsi.

Fungsi ialah modul program bernama yang dikenal pasti secara sintaksis yang melaksanakan tindakan atau kumpulan tindakan tertentu. Setiap fungsi mempunyai antara muka dan pelaksanaannya sendiri. Antara muka fungsi – pengepala fungsi, yang menentukan nama fungsi, senarai parameternya dan jenis nilai pulangan.

Penerangan fungsi dalam bahasa SI dijalankan di mana-mana dalam program di luar penerangan fungsi lain dan terdiri daripada tiga elemen:

1. prototaip fungsi;

2. pengepala fungsi;

3. badan berfungsi.

Prototaip fungsi ialah bahagian pilihan bagi perihalan fungsi, bertujuan untuk mengisytiharkan fungsi yang antara mukanya sepadan dengan prototaip tertentu. Pengisytiharan prototaip mempunyai bentuk berikut:

Jenis nama(senarai jenis parameter formal);

Parameter fungsi ialah nilai yang dihantar ke fungsi apabila ia dipanggil.

Pengepala fungsi – perihalan bahagian antara muka fungsi, yang mengandungi: jenis nilai pulangan, nama fungsi dan senarai parameter formal fungsi. Sintaks untuk mengisytiharkan pengepala fungsi ialah:

Jenis nama (senarai parameter formal)

Contoh pengepala fungsi:

Fungsi int(int i, double x, double y)

Fungsi tidak sah(int ind, char *rentetan)

Fungsi ganda (tidak sah)

Badan fungsi ialah bahagian pelaksanaan yang mengandungi kod program yang dilaksanakan apabila fungsi dipanggil. Badan fungsi sentiasa datang sejurus selepas kepala fungsi (ia tidak boleh dipisahkan) dan disertakan dengan pendakap kerinting.

Pelaksanaan fungsi dalam SI untuk mengira faktorial nombor.

Faktorial berganda (tidak ditandatangani);

Faktorial berganda (nombor tidak ditandatangani)

Fakta berganda = 1.0;

Untuk(tidak bertanda i=1;i<=num;i++)

Fakta *= (double)i;

Kembalikan fakta;

Struktur.

Struktur ialah jenis data kompleks yang mewakili satu set elemen pelbagai jenis yang dipesan dalam ingatan. Setiap elemen dalam struktur mempunyai nama sendiri dan dipanggil medan.

Pengisytiharan dalam SI struktur kelihatan seperti:

Struktur [nama jenis]

Medan_1;

Medan_2;

Medan_N;

) [senarai pembolehubah];

Pengisytiharan medan struktur hanya boleh dilakukan tanpa permulaan. Jika beberapa medan yang mengikuti satu sama lain dalam penerangan struktur mempunyai jenis yang sama, maka untuk menerangkannya, anda boleh menggunakan sintaks untuk mengisytiharkan beberapa pembolehubah jenis yang sama.

Fail.

Fail ialah kawasan bernama data pada beberapa medium storan. Jenis fail (berbanding dengan bahasa SI):
teks;
binari.
Operasi asas yang dilakukan pada fail:
1.Membuka fail.
2.Membaca dan menulis data.
3. Menutup fail.

Operasi tambahan:
1. Navigasi fail.
2. Mengendalikan ralat semasa bekerja dengan fail.
3.Memadam dan menamakan semula fail.
4.Penerangan tentang pembolehubah

Mod pembukaan fail dengan SI

Ubah hala strim
FILE * freopen(const char *nama fail, const char *mod, FILE *strim);

Fungsi mengembalikan:
Penunjuk ke fail - semuanya baik-baik saja,
NULL – mengatasi ralat.

Menutup fail
int fclose(FAIL *strim);

Fungsi mengembalikan:
0 – fail ditutup dengan jayanya.
1 – ralat berlaku semasa menutup fail.

Akhir pemeriksaan fail
int feof(FAIL *strim);
strim - penunjuk ke fail terbuka.

Fungsi mengembalikan:
0 – jika penghujung fail masih belum dicapai.
!0 – akhir fail dicapai.

Membuka fail teks
Parameter kedua juga menentukan aksara t (pilihan):
rt, wt, at, rt+, wt+, at+

Membaca daripada fail teks

Bacaan Berformat
int fscanf(FAIL *strim, const char * format, ...);

Fungsi mengembalikan:
>0 – bilangan pembolehubah yang berjaya dibaca,
0 – tiada pembolehubah berjaya dibaca,
EOF – ralat atau akhir fail dicapai.
Membaca baris

Fungsi mengembalikan:
penimbal - semuanya baik-baik saja,
Membaca baris
char * fgets(char * buffer, int maxlen, FILE *strim);

Fungsi mengembalikan:
penimbal - semuanya baik-baik saja,
NULL – ralat atau akhir fail dicapai.
Membaca simbol
int fgetc(FAIL *strim);
Fungsi mengembalikan:
kod simbol - jika semuanya baik-baik saja,
EOF – jika ralat berlaku atau penghujung fail dicapai.
Meletakkan semula watak ke dalam strim
int ungetc(int c, FILE *strim);
Fungsi mengembalikan:
kod simbol - jika semuanya berjaya,
EOF – ralat berlaku.

Tulis ke teks fail SI

Output berformat
int fprintf(FAIL *strim, const char *format, ...);
Fungsi mengembalikan:
bilangan aksara yang ditulis - jika semuanya normal,
nilai negatif – jika terdapat ralat.
Menulis rentetan
int fputs(const char *rentetan, FILE *strim);
Fungsi mengembalikan:
bilangan aksara yang ditulis - semuanya baik-baik saja,
EOF – ralat berlaku.
Tulis simbol
int fputc(int c, FAIL *strim);
Fungsi mengembalikan:
kod simbol yang direkodkan - semuanya baik-baik saja,
EOF – ralat berlaku.
Membuka fail binari
Parameter kedua juga menyatakan simbol b (diperlukan): rb, wb, ab, rb+, wb+, ab+
Membaca daripada fail binari
size_t fread(void *buffer, size_t size, size_t num, FILE *strim);
Fungsi ini mengembalikan bilangan blok yang dibaca. Jika kurang daripada num, maka ralat berlaku atau dicapai
akhir fail.

Menulis ke fail binari
size_t fwrite(const void *buffer, size_t size, size_t num, FILE *strim);
Fungsi ini mengembalikan bilangan blok yang ditulis. Jika kurang daripada num, maka ralat berlaku.

Navigasi fail

Membaca offset semasa dalam fail:
long int ftell(FAIL *strim);
Menukar offset semasa dalam fail:
int fseek(FAIL *strim, offset int panjang, asal int);

SEEK_SET (0) – dari permulaan fail.
SEEK_CUR (1) – dari kedudukan semasa.
SEEK_END (2) – dari hujung fail.
Fungsi mengembalikan:
0 - semuanya baik-baik saja,
!0 – ralat berlaku.
Pindah ke permulaan fail:
void rewind(FAIL *strim);
Membaca kedudukan semasa dalam fail:
int fgetpos(FAIL *strim, fpos_t *pos);
Menetapkan kedudukan semasa dalam fail:
int fsetpos(FAIL *strim, const fpos_t *pos);
Fungsi kembali:
0 - semuanya berjaya,
!0 – ralat berlaku.
struktur fpos_t:
typedef struct fpos_t (
lama pergi;
mbstate_t wstate;
) fpos_t;

Mendapat tanda ralat:
int ferror(FAIL *strim);
Fungsi mengembalikan nilai bukan sifar jika ralat berlaku.
Fungsi set semula ralat:
void clearerr(FAIL *strim);
Fungsi mesej ralat:
void perror(const char *string);

Penimbalan

Fungsi jelas penampan:
int fflush(FAIL *strim);
Fungsi mengembalikan:
0 - semuanya baik-baik saja.
EOF – ralat berlaku.
Fungsi pengurusan penimbal:
void setbuf(FILE *strim, char * buffer);

Mencipta penimbal bersaiz BUFSIZ. Digunakan sebelum input atau output ke strim.

Fail-fail sementara

Fungsi penciptaan fail sementara:
FAIL * tmpfile(kosong);
Mencipta fail sementara dalam mod wb+. Selepas menutup fail, yang terakhir dipadamkan secara automatik.
Fungsi penjanaan nama fail sementara:
char * tmpnam(char *buffer);

Memadam dan menamakan semula

Fungsi Padam Fail:
int remove(const char *nama fail);
Fungsi menamakan semula fail:
int rename(const char *fname, const char *nname);
Fungsi kembali:
0 - jika berjaya,
!0 – jika tidak.

Kuliah No 4.

Timbunan.

Tindanan adalah bertentangan dengan baris gilir kerana ia beroperasi berdasarkan asas masuk terakhir, keluar dahulu (LIFO). Untuk menggambarkan timbunan, fikirkan timbunan pinggan. Pinggan pertama yang diletakkan di atas meja akan digunakan terakhir, dan pinggan terakhir yang diletakkan di atas akan digunakan dahulu. Tindanan sering digunakan dalam perisian sistem, termasuk penyusun dan jurubahasa.

Apabila bekerja dengan tindanan, operasi memasukkan dan mendapatkan semula elemen adalah yang utama. Operasi ini secara tradisinya dipanggil "push" dan "pop". Oleh itu, untuk melaksanakan tindanan, anda perlu menulis dua fungsi: push(), yang "menolak" nilai ke dalam tindanan, dan pop (), yang "menimbulkan" nilai dari tindanan. Anda juga perlu memperuntukkan kawasan memori yang akan digunakan sebagai timbunan. Untuk tujuan ini, anda boleh memperuntukkan tatasusunan atau memperuntukkan sekeping memori secara dinamik menggunakan fungsi bahasa C yang disediakan untuk peruntukan memori dinamik. Seperti baris gilir, fungsi ambil mengambil elemen daripada senarai dan mengalih keluarnya jika ia belum disimpan di tempat lain. Di bawah ialah bentuk umum fungsi push() dan pop() yang beroperasi pada tatasusunan integer. Jenis tindanan data lain boleh diatur dengan menukar jenis data asas tatasusunan.

int tos=0; /* bahagian atas timbunan */

/* Tolak elemen pada tindanan. */

tolak kosong(int i)

jika(kepada >= MAX) (

printf("Timbunan sudah penuh\n");

/* Dapatkan elemen teratas timbunan. */

jika (tos< 0) {

printf("Timbunan kosong\n");

timbunan kembali;

Pembolehubah tos ("atas tindanan") mengandungi indeks bahagian atas tindanan. Apabila melaksanakan fungsi ini, perlu mengambil kira kes apabila timbunan penuh atau kosong. Dalam kes kami, tanda tindanan kosong ialah tos bersamaan dengan sifar, dan tanda limpahan tindanan ialah tos meningkat dengan begitu banyak sehingga nilainya menghala ke suatu tempat di luar sel terakhir tatasusunan.

Contoh bekerja dengan timbunan.

Tindanan akan ditempatkan dalam memori yang diperuntukkan secara dinamik, dan bukan dalam tatasusunan saiz tetap. Walaupun menggunakan peruntukan memori dinamik tidak diperlukan dalam contoh mudah, kita akan melihat cara menggunakan memori dinamik untuk menyimpan data tindanan.

/* Kalkulator mudah dengan empat langkah. */

#termasuk

#termasuk

int *p; /* penunjuk ke kawasan memori kosong */

int *tos; /* penunjuk ke bahagian atas timbunan */

int *bos; /* penunjuk ke bahagian bawah timbunan */

tolak batal(int i);

p = (int *) malloc(MAX*saiz(int)); /* dapatkan memori untuk timbunan */

printf("Ralat semasa memperuntukkan memori\n");

bos = p + MAX-1;

printf("Empat langkah kalkulator\n");

printf("Tekan "q" untuk keluar\n");

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

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

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

printf("Bahagi dengan 0.\n");

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

kes ".": /* tunjukkan kandungan bahagian atas timbunan */

printf("Nilai semasa di bahagian atas tindanan: %d\n", a);

) while(*s != "q");

/* Menolak elemen pada tindanan. */

tolak kosong(int i)

jika(p > bos) (

printf("Timbunan sudah penuh\n");

/* Dapatkan elemen teratas daripada timbunan. */

jika (hlm< tos) {

printf("Timbunan kosong\n");

Beratur.

Baris gilir ialah senarai linear maklumat yang diproses secara masuk dahulu, keluar dahulu; prinsip ini (dan baris gilir sebagai struktur data) kadangkala juga dipanggil FIFO. Ini bermakna elemen pertama yang diletakkan dalam baris gilir akan diterima daripadanya terlebih dahulu, elemen kedua yang diletakkan akan dialih keluar kedua, dsb. Ini adalah satu-satunya cara untuk bekerja dengan baris gilir; akses rawak kepada elemen individu tidak dibenarkan.

Untuk membayangkan bagaimana baris gilir berfungsi, mari kita perkenalkan dua fungsi: qstore() dan qretrieve() (daripada "store" - "save", "retrieve" - ​​​​"receive"). Fungsi qstore() meletakkan elemen pada penghujung baris gilir, dan fungsi qretrieve() mengalih keluar elemen dari permulaan baris gilir dan mengembalikan nilainya. Jadual menunjukkan urutan operasi tersebut.

Tindakan Kandungan Beratur
qstore(A) A
qstore(B) A B
qstore(C) A B C
qretrieve() mengembalikan A B C
qstore(D) B C D
qretrieve() mengembalikan B C D
qretrieve() mengembalikan C D

Perlu diingat bahawa operasi ambil mengalih keluar elemen daripada baris gilir dan memusnahkannya melainkan ia disimpan di tempat lain. Oleh itu, selepas semua elemen diambil, baris gilir akan kosong.

Dalam pengaturcaraan, baris gilir digunakan untuk menyelesaikan banyak masalah. Salah satu jenis tugas yang paling popular ialah simulasi. Baris gilir juga digunakan dalam penjadual tugas sistem pengendalian dan dalam penimbalan I/O.

/* Penjadual acara mini */

#termasuk

#termasuk

#termasuk

#termasuk

char *p, *qretrieve(kosong);

void enter(void), qstore(char *q), review(void), delete_ap(void);

untuk(t=0; t< MAX; ++t) p[t] = NULL; /* иницилизировать массив

petunjuk kosong */

printf("Masukkan (E), Senarai (L), Padam (R), Keluar (Q): ");

*s = topper(*s);

/* Masukkan janji temu baharu ke dalam baris gilir. */

batal masuk (kosong)

printf("Masukkan janji temu %d: ", spos+1);

if(*s==0) ​​​​break; /* tiada rakaman dibuat */

p = (char *) malloc(strlen(s)+1);

printf("Memori tidak mencukupi.\n");

jika(*s) qstore(p);

/* Lihat kandungan baris gilir. */

ulasan batal (tidak sah)

untuk(t=rpos; t< spos; ++t)

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

/* Alih keluar janji temu daripada baris gilir. */

void delete_ap(void)

if((p=qretrieve())==NULL) return;

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

/* Masukkan janji temu. */

void qstore(char *q)

printf("Senarai Penuh\n");

/* Dapatkan temu janji. */

char *qretrieve(void)

jika(rpos==spos) (

printf("Tiada mesyuarat lagi.\n");

kembali p;

Senaraikan.

Senarai kitaran yang dipautkan secara tunggal ialah pengisytiharan struktur rekursif, atau lebih tepatnya penunjuk kepadanya dalam struktur jenis itu sendiri:

int data; // medan data

s *seterusnya;//elemen seterusnya

) *pertama,*curr;//elemen pertama dan semasa

Permulaan:

pertama->seterusnya=curr;

untuk mendapatkan elemen pertama gunakan dahulu->data

untuk menambah elemen baharu: curr->next=new s;

curr=curr->next;//pergi ke yang terakhir

dan untuk mendapatkan, sebagai contoh, elemen ke-50, gelung melalui senarai:

curr=first;//pergi ke first

untuk(int i=0;i<50;i++)

if(curr->next!=NULL)

curr=curr->next;


Maklumat berkaitan.


Pemasa pertama di laman web ini, jadi begini.

Saya baharu dalam C++ dan sedang mengusahakan buku "Struktur Data Menggunakan C++ ed 2nd, D.S. Malik".

Dalam buku itu, Malik menawarkan dua cara untuk mencipta tatasusunan dua dimensi dinamik. Dalam kaedah pertama, anda mengisytiharkan pembolehubah sebagai tatasusunan penunjuk, di mana setiap penunjuk adalah jenis integer. cth

Int *papan;

Dan kemudian gunakan gelung untuk untuk mencipta "lajur" apabila menggunakan tatasusunan penunjuk sebagai "baris".

Kaedah kedua, anda menggunakan penunjuk ke penunjuk.

Int **papan; papan = new int* ;

Soalan saya ialah: kaedah mana yang lebih baik? Kaedah ** lebih mudah untuk saya gambarkan, tetapi kaedah pertama boleh digunakan dengan cara yang sama. Kedua-dua kaedah boleh digunakan untuk mencipta tatasusunan 2 dimensi dinamik.

Edit: Tidak cukup jelas seperti yang dinyatakan di atas. Inilah kod yang saya cuba:

Baris int, kol; cout<< "Enter row size:"; cin >>baris; cout<< "\ncol:"; cin >>col; int *p_board; untuk (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 jawapan

Kaedah pertama tidak boleh digunakan untuk mencipta dinamik Tatasusunan 2D kerana:

Int *papan;

anda pada dasarnya telah memperuntukkan tatasusunan 4 penunjuk kepada int setiap timbunan. Jadi jika anda kini mengisi setiap 4 penunjuk ini dengan tatasusunan dinamik:

Untuk (int i = 0; i< 4; ++i) { board[i] = new int; }

apa yang anda berakhir ialah tatasusunan 2D dengan statik bilangan baris (dalam kes ini 4) dan dinamik bilangan lajur (dalam kes ini 10). Oleh itu, dinamik tidak sepenuhnya, kerana apabila memperuntukkan tatasusunan pada timbunan anda mesti menunjukkan saiz tetap, iaitu Dikenali di masa. Dinamik tatasusunan dipanggil dinamik, kerana saiznya tidak perlu diketahui dalam masa menyusun, tetapi boleh ditakrifkan oleh beberapa pembolehubah dalam semasa pelaksanaan.

Sekali lagi apabila anda melakukan:

Int *papan;

Const int x = 4; //<--- `const` qualifier is absolutely needed in this case! int *board[x];

anda menyediakan pemalar yang diketahui dalam masa menyusun(dalam kes ini 4 atau x) supaya pengkompil boleh sekarang pra-pilih memori ini untuk tatasusunan anda, dan apabila atur cara anda dimuatkan ke dalam memori, ia akan mempunyai jumlah memori ini untuk tatasusunan papan, itulah sebabnya ia dipanggil statik, iaitu kerana saiznya berkod keras Dan tidak boleh berubah secara dinamik(pada masa larian).

Sebaliknya, apabila anda melakukan:

Int **papan; papan = new int*;

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

pengkompil tidak tahu berapa banyak memori yang diperlukan oleh tatasusunan papan, jadi ia tidak memperuntukkan terlebih dahulu Semua. Tetapi apabila anda menjalankan program anda, saiz tatasusunan akan ditentukan oleh nilai pembolehubah x (pada masa jalan), dan ruang yang sepadan untuk tatasusunan papan akan diperuntukkan kepada apa yang dipanggil sekumpulan- kawasan memori di mana semua program yang berjalan pada komputer anda boleh memperuntukkan tidak diketahui terlebih dahulu(pada masa penyusunan) meringkaskan ingatan untuk kegunaan peribadi.

Akibatnya, untuk benar-benar mencipta tatasusunan 2D dinamik, anda perlu menggunakan kaedah kedua:

Int **papan; papan = new int*; // tatasusunan dinamik (saiz 10) penunjuk kepada int untuk (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 }

Kami baru sahaja mencipta tatasusunan 2D persegi 10 kali 10. Untuk meneruskannya dan mengisinya dengan nilai sebenar, seperti 1, kami boleh menggunakan gelung bersarang:

Untuk (int i = 0; i< 10; ++i) { // for each row for (int j = 0; j < 10; ++j) { // for each column board[i][j] = 1; } }

Perkara yang anda terangkan untuk kaedah kedua hanya menghasilkan tatasusunan 1D:

Int *papan = int baharu;

Ini hanya memperuntukkan tatasusunan dengan 10 elemen. Mungkin anda maksudkan sesuatu seperti ini:

Int **papan = new int*; untuk (int i = 0; i< 4; i++) { board[i] = new int; }

Dalam kes ini, kami memperuntukkan 4 int* s dan kemudian setiap titik kepada tatasusunan yang diperuntukkan secara dinamik sebanyak 10 int s.

Jadi sekarang kita bandingkan ini dengan papan int*; . Perbezaan utama ialah apabila menggunakan tatasusunan sedemikian, bilangan "baris" mesti diketahui pada masa penyusunan. Ini kerana tatasusunan mesti mempunyai saiz masa kompilasi tetap. Anda juga mungkin menghadapi masalah jika anda mungkin ingin mengembalikan tatasusunan ini dari int* s, kerana tatasusunan akan dimusnahkan pada penghujung skopnya.

Kaedah yang memperuntukkan kedua-dua baris dan lajur secara dinamik memerlukan langkah yang lebih kompleks untuk mengelakkan kebocoran memori. Anda harus membebaskan memori seperti ini:

Untuk (int i = 0; i< 4; i++) { delete board[i]; } delete board;

Saya perlu mengesyorkan menggunakan bekas standard sebaliknya. Anda boleh menggunakan std::array 4> atau mungkin std::vector > yang anda mulakan dengan saiz yang sesuai.

Dalam kedua-dua kes, dimensi dalaman anda boleh ditetapkan secara dinamik (iaitu diambil daripada pembolehubah), tetapi perbezaannya adalah dalam dimensi luar.

Soalan ini pada asasnya bersamaan dengan yang berikut:

Adakah int* x = int baharu; "lebih baik" daripada int x ?

Jawapannya ialah "tidak, melainkan anda perlu memilih saiz tatasusunan itu secara dinamik."

Kod ini berfungsi dengan baik dengan sangat sedikit keperluan perpustakaan luaran dan menunjukkan penggunaan asas int **array .

Jawapan ini menunjukkan bahawa array setiap satu mempunyai saiz dinamik dan juga cara menetapkan tatasusunan linear bersaiz dinamik kepada tatasusunan cawangan bersaiz dinamik.

Program ini mengambil hujah daripada STDIN dalam format berikut:

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

Kod untuk program adalah di bawah...

#termasuk 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 >> susunan_semasa_saiz; int *tmp_array = int baharu; untuk (int j = 0; j< size_current_array; j++) { int tmp = 0; std::cin >>tmp; tmp_array[j] = tmp; ) array_of_arrays[i] = tmp_array; ) //Proses Pertanyaan int x, y; x = y = 0; untuk (int q = 0; q< num_queries; q++) { std::cin >> x >> y; //std::cout<< "Current x & y: " << x << ", " << y << "\n"; std::cout << array_of_arrays[x][y] << "\n"; } return 0; }

Ini adalah pelaksanaan int main yang sangat mudah dan hanya bergantung pada std::cin dan std::cout . Barebones, tetapi cukup baik untuk menunjukkan cara bekerja dengan tatasusunan berbilang dimensi yang mudah.