Paglikha ng dalawang-dimensional na dynamic na array sa c. Dalawang-dimensional na dynamic na array

Karaniwan, ang halaga ng memorya na kinakailangan para sa isang partikular na variable ay tinukoy bago ang proseso ng compilation sa pamamagitan ng pagdedeklara ng variable na iyon. Kung may pangangailangan na lumikha ng isang variable na ang laki ay hindi alam nang maaga, pagkatapos ay ginagamit ang dynamic na memorya. Pagpapareserba At pagpapalaya Ang mga problema sa memorya sa mga programang C++ ay maaaring mangyari anumang oras. Ang mga operasyon ay isinasagawa pamamahagi memorya sa dalawang paraan:

  • gamit ang function malloc, calloc, realloc At libre;
  • sa pamamagitan ng operator bago At tanggalin.

Function malloc reserba magkadikit na bloke ng mga memory cell para sa imbakan tinukoy na bagay at nagbabalik ng pointer sa unang cell ng block na ito. Ang tawag sa function ay ganito ang hitsura:

walang bisa *malloc(laki);

Dito laki- isang unsigned integer value na tumutukoy sa laki ng inilalaan na memory area sa bytes. Kung matagumpay ang reserbasyon ng memorya, babalik ang function uri ng variable walang bisa*, na maaaring bawasan sa anuman kinakailangang uri panturo.

Function - calloc inilaan din para sa paglalaan ng memorya. Ang entry sa ibaba ay nangangahulugan na ito ay mai-highlight num mga elemento sa pamamagitan ng laki byte.

void *calloc(nime, size);

Ang function na ito ay nagbabalik ng isang pointer sa napiling lugar o NULL kapag imposibleng maglaan ng memorya. Ang isang espesyal na tampok ng function ay upang i-reset ang lahat ng mga napiling elemento sa zero.

Function reallocbaguhin ang laki naunang inilaan na memorya. Tinutugunan nila siya ng ganito:

char *realloc (walang laman *p, laki);

Dito p- pointer sa lugar ng memorya kung saan kailangang baguhin ang laki laki. Kung ang address ng lugar ng memorya ay nagbabago bilang isang resulta ng pag-andar, kung gayon bagong address babalik bilang resulta. Kung aktwal na halaga unang parameter NULL, pagkatapos ay ang function realloc gumagana ang parehong bilang ang function malloc, iyon ay, naglalaan ito ng isang lugar ng memorya ng laki laki byte.

Upang palayain ang nakalaan na memorya, gamitin ang function libre. Tinutugunan nila siya ng ganito:

walang bisa (walang bisa *p size);

Dito p- pointer sa isang lokasyon ng memorya na dating inilalaan ng mga function malloc, calloc o realloc.

Mga operator bago At tanggalin katulad na mga function malloc At libre. Bago naglalaan ng memorya, at ang tanging argumento nito ay isang expression na tumutukoy sa bilang ng mga byte na irereserba. Ang operator ay nagbabalik ng isang pointer sa simula ng inilalaan na bloke ng memorya. Operator tanggalin nagpapalaya ng memorya, ang argumento nito ay ang address ng unang cell ng block na kailangang palayain.

Dynamic na hanay- array variable na haba, memorya kung saan inilalaan sa panahon ng pagpapatupad ng programa. Ang paglalaan ng memorya ay isinasagawa ng mga function calloc, malloc o operator bago. Ang address ng unang elemento ng inilalaang memorya ay naka-imbak sa isang variable na ipinahayag bilang isang pointer. Halimbawa, ang sumusunod na pahayag ay nangangahulugan na ang isang pointer ay inilarawan mas at ito ay itinalaga ang address ng simula ng magkadikit na lugar dynamic na memorya, na naka-highlight gamit ang operator bago:

int *mas=new int;

Ang halaga ng memory na inilaan ay sapat upang mag-imbak ng 10 int value.

Sa katunayan, sa variable mas nakaimbak ang address zero elemento dynamic na hanay. Samakatuwid, ang address ng susunod, unang elemento sa inilalaan na lugar ng memorya ay mas+1, a mas Ang +i ay ang address ng i-th na elemento. Ang i-th na elemento ng isang dynamic na array ay maaaring ma-access gaya ng dati gamit ang mas[i], o sa ibang paraan *(mas +i) . Mahalagang tiyakin na hindi ka lalampas sa mga hangganan ng inilalaang lugar ng memorya.

kailan dynamic na hanay(sa anumang oras sa panahon ng pagpapatakbo ng programa) ay hindi na kailangan, pagkatapos ay ang memorya ay maaaring mapalaya gamit ang function libre o operator tanggalin.

Iminumungkahi kong isaalang-alang ang ilang gawain na nagpapatibay sa araling ito:

Problema 1

Hanapin ang kabuuan ng mga tunay na elemento ng isang dynamic na array.

//Halimbawa ng paggamit malloc function at libreng #include "stdafx.h" #include gamit ang namespace std; int main() ( setlocale(LC_ALL,"Rus"); int i, n; float *a; //pointer to float float s; cout<<"\n"; cin>>n; //pagpasok ng laki ng array //paglalaan ng memorya para sa hanay ng n tunay na elemento a=(float *)malloc(n*sizeof(float)); cout<<"Введите массив A \n"; //ввод элементов массива for (i=0; i>*(a+i); ) //pag-iipon ng kabuuan ng mga elemento ng array para sa (s=0, i=0; i

//Isang halimbawa ng paggamit ng malloc at mga libreng function

#include "stdafx.h"

#isama

gamit ang namespace std ;

int main()

int i, n;

lumutang * a ; //pointer para lumutang

lumutang s ;

cout<< "\n" ; cin >> n ; //ipasok ang laki ng array

//maglaan ng memorya para sa isang hanay ng mga n tunay na elemento

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

cout<< "Ipasok ang array A\n";

// input array elements

para sa (i = 0 ; i< n ; i ++ )

cin >> * (a + i);

//akumulasyon ng kabuuan ng mga elemento ng array

para sa (s = 0 , i = 0 ; i< n ; i ++ )

s += * (a + i) ;

//output ang halaga ng halaga

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

//libreng memorya

libre(a);

system("pause");

bumalik 0;

Problema 2

Baguhin ang isang dynamic na hanay ng mga integer upang ang mga positibong elemento nito ay maging negatibo at vice versa. Upang malutas ang problema, i-multiply natin ang bawat elemento sa -1.

//Halimbawa ng paggamit ng bago at tanggalin ang mga operator #include "stdafx.h" #include gamit ang namespace std; int main() ( setlocale(LC_ALL,"Rus"); int i, n; //ipasok ang bilang ng mga elemento ng array cout<<"n="; cin>>n; //memory allocation int *a=new int[n]; cout<<"Введите элементы массива:\n"; //ввод массива for (i=0; i>a[i]; //output ang tinukoy na array para sa (i=0; i

//Halimbawa ng paggamit ng bago at tanggalin ang mga operator

#include "stdafx.h"

#isama

gamit ang namespace std ;

int main()

setlocale(LC_ALL, "Rus");

int i, n;

//ipasok ang bilang ng mga elemento ng array

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

//paglalaan ng memorya

int * a = bagong int [ n ] ;

cout<< "Ipasok ang mga elemento ng array:\n";

// array ng input

Habang nangongolekta ng impormasyon para isulat ang artikulong ito, naalala ko ang una kong kakilala sa mga pointer - Nalungkot ako... Samakatuwid, pagkatapos basahin ang ilang mga seksyon sa paksang ito mula sa iba't ibang mga libro tungkol sa programming sa C++, napagpasyahan na kumuha ng ibang ruta at ipakita ang paksa ng C++ Pointers sa pagkakasunud-sunod kung saan itinuturing kong kinakailangan. Bibigyan kita kaagad ng maikling kahulugan at titingnan natin ang mga payo sa pagkilos gamit ang mga halimbawa. Ang susunod na artikulo () ay magbabalangkas ng mga nuances, ang paggamit ng mga pointer na may C-style na mga string (character arrays) at ang mga pangunahing bagay na dapat tandaan.

Ang isang pointer sa C++ ay isang variable na nag-iimbak ng address ng data (mga halaga) sa memorya, at hindi ang data mismo.

Matapos tingnan ang mga sumusunod na halimbawa, mauunawaan mo ang pangunahing bagay - kung bakit kailangan namin ng mga payo sa programming, kung paano ipahayag at gamitin ang mga ito.

Sabihin nating sa isang programa kailangan nating lumikha ng integer array, ang eksaktong sukat na hindi natin alam bago magsimulang tumakbo ang program. Ibig sabihin, hindi namin alam kung ilang numero ang kakailanganing ipasok ng user sa array na ito. Siyempre, maaari nating i-play ito nang ligtas at magdeklara ng hanay ng ilang libong elemento (halimbawa, 5,000). Ito (sa aming pansariling opinyon) ay dapat sapat para gumana ang user. Oo - sa katunayan - ito ay maaaring sapat na. Ngunit huwag nating kalimutan na ang array na ito ay kukuha ng maraming espasyo sa RAM (5,000 * 4 (int type) = 20,000 bytes). Na-secure na namin ang aming sarili, at pupunuin lang ng user ang 10 elemento ng aming array. Lumalabas na mayroon talagang 40 bytes na ginagamit, at 19,960 bytes ang nag-aaksaya ng memorya.

hindi makatwirang paggamit ng RAM

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

#isama

gamit ang namespace std ;

int main()

> arrWithDigits[i];

) cout

cout<< const int SizeOfArray = 5000 ;<< sizeof (arrWithDigits ) << " байт" << endl ;

int arrWithDigits [ SizeOfArray ] = ( );

cout<< "Ang array na inookupahan sa memorya";

int na halaga = 0 ;

cout<< "Ilang numero ang ilalagay mo sa array?"<< amount * sizeof (int ) << " байт" << endl ;

cin >> halaga ;< amount ; i ++ )

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

"Kailangan talaga"

cout<< endl ;

cin >> halaga ;< amount ; i ++ )

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

cout<< endl ;

bumalik 0;

para sa (int i = 0 ; i cin >> arrWithDigits [i]; Sa isang karaniwang function ng library sizeof() pagpasa sa ipinahayag na hanay arrWithDigits linya 10. Ito ay babalik sa lugar ng tawag ang laki sa bytes na ang array na ito ay sumasakop sa memorya. Sa tanong na "Ilang numero ang ilalagay mo sa array?" ang sagot ay 10. Sa linya 15, ang expression halaga * sizeof(int) ay magbabalik ng 4 (laki sa bytes ng uri ng int). Susunod, ipasok ang mga numero mula sa keyboard at ipapakita ng programa ang mga ito sa screen. Lumalabas na ang natitirang 4990 elemento ay mag-iimbak ng mga zero. Kaya walang saysay na ipakita sa kanila.

Ang pangunahing impormasyon sa screen: ang array ay tumagal ng 20,000 bytes, ngunit sa katotohanan ay nangangailangan ito ng 40 bytes. Paano makaalis sa ganitong sitwasyon? Maaaring naisin ng isang tao na muling isulat ang programa upang maipasok ng user ang laki ng array mula sa keyboard at, pagkatapos na ipasok ang halaga, magdeklara ng array na may kinakailangang bilang ng mga elemento. Ngunit hindi ito magagawa nang walang mga payo. Tulad ng naaalala mo, ang laki ng array ay dapat na pare-pareho. Iyon ay, ang isang integer constant ay dapat masimulan bago ideklara ang array at hindi namin mai-prompt ang input nito mula sa keyboard. Eksperimento at suriin.


Dito, pinaiilaw kami ng operator ng kulay pula >> dahil ang isang palaging halaga ay hindi mababago.

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


Dito kami ay binigyan ng babala na ang laki ng array ay hindi maaaring maging halaga ng isang regular na variable. Kinakailangan ang patuloy na halaga!

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

Sa sumusunod na code ay gagamit kami ng pointer at mga operator na bago sa iyo bago(naglalaan ng memorya) at tanggalin(nagpapalaya ng memorya).

matalinong paggamit ng RAM gamit ang mga pointer

#isama #isama gamit ang namespace std; int main() ( setlocale(LC_ALL, "rus"); int sizeOfArray = 0; // laki ng array (ipinasok ng user) cout<< "Чтобы создать массив чисел, введите его размер: "; cin >> sizeOfArray;< sizeOfArray; i++) { arrWithDigits[i] = i + 1; cout << arrWithDigits[i] << " "; } cout << endl; delete arrWithDigits; // освобождение памяти return 0; }

#isama

#isama

gamit ang namespace std ;

int main()

// PANSIN! int* arrWithDigits - deklarasyon ng isang pointer // sa isang piraso ng memorya na ilalaan ng bagong int* arrWithDigits = new int ;

para sa (int i = 0; i setlocale(LC_ALL, "rus");

cout<< int sizeOfArray = 0 ;;

// laki ng array (ipinasok ng user)

"Upang lumikha ng hanay ng mga numero, ilagay ang laki nito: "

cin >> sizeOfArray ;

// PANSIN! int* arrWithDigits - deklarasyon ng pointer

cin >> halaga ;< sizeOfArray ; i ++ )

// sa isang piraso ng alaala na ilalaan ng bago

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

cout<< endl ;

int * arrWithDigits = bagong int [ sizeOfArray ] ; arrWithDigits[i] = i+1;

bumalik 0;

tanggalin ang arrWithDigits ; // pagpapalaya ng memorya Ang gumagamit ay nagpasok ng isang halaga mula sa keyboard - linya 12. Ang pointer ay tinukoy sa ibaba: int * arrWithDigits Ang ibig sabihin ng entry na ito int * arrWithDigits arrWithDigits * ay isang pointer. Ito ay nilikha upang iimbak ang address ng cell kung saan matatagpuan ang integer. Sa aming kaso = ituturo ang array cell na may index na 0. Ang sign bago- katulad ng ginamit para sa pagpaparami. Batay sa konteksto, ang compiler ay "maiintindihan" na ito ay isang pointer deklarasyon at hindi isang multiplikasyon. Susunod na dumating ang tanda at operator, na naglalaan ng isang piraso ng memorya. Naaalala namin na ang aming memorya ay dapat na inilalaan para sa isang array, at hindi para sa isang solong numero. Itala bago bagong int [sizeOfArray] maaaring ma-decipher tulad nito:(para sa pag-iimbak ng mga integer) (sa dami sizeOfArray ).

Kaya, sa linya 16 ito ay tinukoy dynamic na hanay. Nangangahulugan ito na ang memorya para dito ay ilalaan (o hindi ilalaan) habang tumatakbo ang programa, at hindi sa panahon ng compilation, gaya ng nangyayari sa mga regular na array. Iyon ay, ang paglalaan ng memorya ay nakasalalay sa pag-unlad ng programa at mga desisyon na direktang ginawa sa pagpapatakbo nito. Sa aming kaso, depende ito sa kung ano ang ipinasok ng user sa variable sizeOfArray

Ginagamit ng linya 25 ang operator tanggalin. Inilalabas nito ang inilaan na operator bago alaala. kasi bago inilalaan ang memorya para sa pag-iimbak ng array, pagkatapos kapag pinalaya ito, kailangan mong gawing malinaw sa tagatala na kinakailangan upang palayain ang memorya ng array, at hindi lamang ang zero cell nito, na itinuturo sa int * arrWithDigits. Samakatuwid, sa pagitan tanggalin at ang pangalan ng pointer ay inilalagay sa mga square bracket tanggalin ang arrWithDigits ; Tandaan na sa tuwing ang memorya ay inilalaan gamit bago, kailangan mong palayain ang memorya na ito gamit ang tanggalin. Siyempre, kapag natapos ang programa, ang memorya na inookupahan nito ay awtomatikong mapapalaya. Ngunit ugaliing gumamit ng mga operator bago At tanggalin magkapares. Pagkatapos ng lahat, ang isang programa ay maaaring maglaman ng 5-6 na mga array, halimbawa. At kung magpapalaya ka ng memory sa tuwing hindi na ito kailangan sa hinaharap sa isang tumatakbong programa, mas matalinong gagamitin ang memorya.

Sabihin nating sa aming programa napuno namin ang isang array na may sampung halaga. Susunod, kinakalkula namin ang kanilang kabuuan at naitala ito sa ilang variable. At iyon na - hindi na kami gagana sa array na ito. Ang programa ay patuloy na gumagana at ang mga bagong dynamic na array ay nilikha dito para sa ilang layunin. Sa kasong ito, ipinapayong palayain ang memorya na inookupahan ng unang array. Pagkatapos, kapag naglalaan ng memorya para sa iba pang mga array, ang memorya na ito ay maaaring magamit muli sa programa.

Isaalang-alang natin ang paggamit ng mga pointer bilang mga parameter ng mga function. Upang makapagsimula, i-type at i-compile ang sumusunod na code. Sa loob nito, ang function ay tumatanggap ng dalawang variable at nag-aalok na gumawa ng mga pagbabago sa kanilang mga halaga.

subukang baguhin ang mga variable na ipinasa sa isang function

#isama #isama gamit ang namespace 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;<< "Введите новое значение второй переменной: "; cin >cout

#isama

#isama

gamit ang namespace std ;

> varForCh2; )

int main()

// PANSIN! int* arrWithDigits - deklarasyon ng isang pointer // sa isang piraso ng memorya na ilalaan ng bagong int* arrWithDigits = new int ;

void changeData(int varForCh1, int varForCh2);

int variableForChange_1 = 0 ;

cout<< "variableForChange_1 = " << variableForChange_1 << endl ;

cout<< "variableForChange_2 = " << variableForChange_2 << endl ;

cout<< endl ;

int variableForChange_2 = 0 ;

cout<< endl ;

cout<< "variableForChange_1 = " << variableForChange_1 << endl ;

cout<< "variableForChange_2 = " << variableForChange_2 << endl ;

bumalik 0;

changeData(variableForChange_1, variableForChange_2);

cout<< "Magpasok ng bagong halaga para sa unang variable: ";

cin >> varForCh1 ;

cout<< "Magpasok ng bagong halaga para sa pangalawang variable: ";

cin >> varForCh2 ;

Patakbuhin ang programa at magpasok ng mga bagong variable na halaga. Bilang resulta, makikita mo na sa pagkumpleto ng function, ang mga variable ay hindi nagbago at katumbas ng 0.

Tulad ng naaalala mo, ang function ay hindi gumagana nang direkta sa mga variable, ngunit lumilikha ng kanilang eksaktong mga kopya. Ang mga kopyang ito ay masisira pagkatapos na lumabas ang function. Iyon ay, ang function ay nakatanggap ng ilang variable bilang isang parameter, lumikha ng isang kopya nito, nagtrabaho kasama nito at sinira ito. Ang variable mismo ay mananatiling hindi nagbabago.

Gamit ang mga pointer, maaari naming ipasa ang mga variable na address sa isang function. Pagkatapos ay magagawang gumana nang direkta ang function sa variable na data sa address. Gumawa tayo ng mga pagbabago sa nakaraang programa.

pagbabago ng mga variable na halaga gamit ang mga pointer

#isama #isama gamit ang namespace 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;<< "Введите новое значение второй переменной: "; cin >cout

> *varForCh2; ) Layunin ng lecture

: pag-aaral ng mga deklarasyon, paglalaan at pagpapalabas ng memorya para sa mga one-dimensional na dynamic na array, pag-access sa mga elemento, natutunang lutasin ang mga problema gamit ang isang-dimensional na dynamic na array sa C++ na wika. Kapag gumagamit ng maraming mga istraktura ng data, madalas na nangyayari na dapat silang magkaroon ng isang variable na laki depende sa laki ng istraktura ng data. lead time mga programa. Sa mga kasong ito kinakailangan na gamitin dynamic na paglalaan ng memorya

. Ang isa sa mga pinaka-karaniwang tulad ng mga istruktura ng data ay mga array, kung saan ang laki ay hindi unang tinukoy o naayos. Ayon sa pamantayan ng wika ang array ay isang koleksyon ng mga elemento, bawat isa ay may parehong mga katangian. Ang lahat ng mga elementong ito ay inilalagay sa mga katabing lokasyon ng memorya sa isang hilera, simula sa address na tumutugma sa simula ng array. Iyon ay, ang kabuuang bilang ng mga elemento ng array at ang laki ng memorya na inilaan para dito ay ganap at natatanging tinukoy ng kahulugan ng array. Ngunit hindi ito palaging maginhawa. Minsan kinakailangan na ang inilaan na memorya para sa isang array ay sukat upang malutas ang isang partikular na problema, at ang laki nito ay hindi alam nang maaga at hindi maaaring ayusin. Ang pagbuo ng mga array na may variable na laki (dynamic arrays) ay maaaring ayusin gamit ang mga pointer at tool.

Dynamic na hanay dynamic na paglalaan ng memorya ay isang array na ang laki ay hindi naayos nang maaga at maaaring magbago sa panahon ng pagpapatupad ng programa. Upang baguhin ang laki dynamic na hanay Ang C++, na sumusuporta sa mga ganitong array, ay nagbibigay ng espesyal built-in na mga function o mga operasyon. Mga dynamic na array magbigay ng pagkakataon para sa mas nababaluktot na trabaho sa data, dahil pinapayagan ka nitong huwag hulaan ang mga nakaimbak na volume ng data, ngunit upang ayusin ang laki ng array alinsunod sa aktwal na kinakailangang mga volume.

Pagdedeklara ng mga one-dimensional na dynamic na array

Sa ilalim ng deklarasyon ng one-dimensional ay isang array na ang laki ay hindi naayos nang maaga at maaaring magbago sa panahon ng pagpapatupad ng programa. Upang baguhin ang laki maunawaan ang deklarasyon ng isang pointer sa isang variable ng isang naibigay na uri upang ang variable na ito ay magamit bilang dynamic na hanay.

Syntax:

I-type ang *ArrayName;

Uri – uri ng mga elementong ipinapahayag ay isang array na ang laki ay hindi naayos nang maaga at maaaring magbago sa panahon ng pagpapatupad ng programa. Upang baguhin ang laki. Mga elemento ay isang array na ang laki ay hindi naayos nang maaga at maaaring magbago sa panahon ng pagpapatupad ng programa. Upang baguhin ang laki hindi maaaring magkaroon ng mga function at elemento type void.

Halimbawa:

int *a; doble *d;

Sa mga halimbawang ito, ang a at d ay mga pointer sa simula ng inilalaan na lokasyon ng memorya. Kinukuha ng mga pointer ang halaga ng address ng inilalaang lugar ng memorya para sa mga halaga ng uri ng int at dobleng uri, ayon sa pagkakabanggit.

Kaya, kapag dynamic na naglalaan ng memorya para sa mga dynamic na array, dapat mong ilarawan ang kaukulang pointer kung saan itatalaga ang halaga ng address ng simula ng inilalaan na lugar ng memorya.

Paglalaan ng memorya para sa isang one-dimensional na dynamic na array

Upang maglaan ng memorya para sa isang-dimensional dynamic na hanay Sa C++ mayroong 2 paraan.

1) sa pamamagitan ng operasyon new , na naglalaan ng isang seksyon ng dynamic na memorya ng naaangkop na laki para sa pag-iimbak ng array at hindi pinapayagan ang mga elemento ng array na masimulan.

Syntax:

ArrayName = bagong Uri [ConstantTypeExpression];

ArrayName – array identifier, iyon ay, ang pangalan ng pointer para sa inilalaan na memory block.

TypeExpressionConstant- nagtatakda ng bilang ng mga elemento ( dimensyon) ng array. Ang isang expression ng pare-parehong uri ay sinusuri sa oras ng pag-compile.

Halimbawa:

int *mas; mas = bagong int ; /*maglaan ng dynamic na memorya ng 100*sizeof(int) bytes*/ double *m = bagong double [n]; /*maglaan ng dynamic na memorya ng n*sizeof(double) bytes*/ long (*lm); lm = bagong haba ; /*maglaan ng dynamic na memorya ng 2*4*sizeof(long) bytes*/

Kapag naglalaan ng dynamic na memorya, ang mga sukat ng array ay dapat na ganap na tinukoy.

2) gamit ang function ng library malloc (calloc) , na ginagamit upang maglaan ng dynamic na memorya.

Syntax:

ArrayName = (Uri *) malloc(N*sizeof(Uri));

ArrayName = (Uri *) calloc(N, sizeof(Uri));

ArrayName – array identifier, iyon ay, ang pangalan ng pointer para sa inilalaan na memory block.

Uri – ang uri ng isang pointer sa isang array.

N – bilang ng mga elemento ng array.

Halimbawa:

lumutang *a; a=(float *)malloc(10*sizeof(float)); // or a=(float *)calloc(10,sizeof(float)); /*maglaan ng dynamic na memorya ng 10*sizeof(float) bytes*/

Dahil ang malloc(calloc) function ay bumalik hindi na-type na pointer void * , pagkatapos ay kinakailangan na i-convert ang resulta

// deklarasyon ng dalawang-dimensional na dynamic na hanay ng 10 elemento:

float **ptrarray = bagong float* ; // dalawang linya sa array

para sa (int count = 0; count< 2; count++)

ptrarray = bagong float ; // at limang hanay

// kung saan ang ptrarray ay isang hanay ng mga pointer sa isang inilalaang lugar ng memory para sa isang hanay ng mga totoong numero ng uri ng float

Una, idineklara ang second-order pointer float **ptrarray, na tumutukoy sa array ng float* pointer, kung saan ang laki ng array ay dalawa . Pagkatapos nito, sa for loop, ang bawat linya ng array ay ipinahayag sa linya 2 ang memorya ay inilalaan para sa limang elemento. Ang resulta ay isang dalawang-dimensional na dynamic na array ptrarray.

// freeing memory na inilaan para sa isang two-dimensional dynamic array:

para sa (int count = 0; count< 2; count++)

tanggalin ang ptrarray;

// kung saan ang 2 ay ang bilang ng mga linya sa array

#isama
#isama
#isama
void main()
{

int *a; // pointer sa array

system("chcp 1251");

scanf("%d", &n);

scanf("%d", &m);

// Paglalaan ng memorya

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

// Pagpasok ng mga elemento ng array

para sa(i=0; i

para sa(j=0; j

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

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

// Output array elements

para sa(i=0; i

para sa(j=0; j

printf("%5d ", *(a+i*m+j)); // 5 kakilala para sa isang elemento ng array

getchar(); getchar();
}

Resulta ng pagpapatupad

Ilagay ang bilang ng mga linya: 3

Ilagay ang bilang ng mga column: 4

Ang isa pang paraan upang dynamic na maglaan ng memorya para sa isang two-dimensional array ay posible rin - gamit ang isang array ng mga pointer. Upang gawin ito kailangan mo:
- maglaan ng isang bloke ng RAM para sa isang hanay ng mga pointer;
- maglaan ng mga bloke ng RAM para sa mga one-dimensional na array, na mga hilera ng nais na matrix;
- isulat ang mga address ng mga linya sa isang hanay ng mga pointer.

Ang malloc() function ay nagbabalik ng isang pointer sa unang byte ng isang memory area na may sukat na laki na inilaan mula sa isang dynamic na inilaan na lugar ng memorya. Kung walang sapat na memorya sa dynamic na lugar ng memorya, ibabalik ang isang null pointer.

#isama
#isama
#isama
void main()
{

int**a; // pointer sa pointer sa string

system("chcp 1251");

printf("Ipasok ang bilang ng mga linya: ");

scanf("%d", &n);

printf("Ipasok ang bilang ng mga hanay: ");

scanf("%d", &m);

// Paglalaan ng memory para sa mga pointer sa mga string

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

// Pagpasok ng mga elemento ng array

para sa(i=0; i

// Paglalaan ng memorya para sa pag-iimbak ng mga string

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

para sa(j=0; j

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

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

// Output array elements

para sa(i=0; i

para sa(j=0; j

printf("%5d ", a[i][j]); // 5 kakilala para sa isang elemento ng array

libre(a[i]); // pagpapalaya ng memorya para sa string

getchar(); getchar();
}

Ang resulta ng pagpapatupad ng programa ay katulad ng nakaraang kaso.

Gamit ang dynamic na paglalaan ng memory para sa mga row pointer, maaari kang maglaan ng mga libreng array. Libre ay isang dalawang-dimensional na hanay (matrix), ang laki ng mga hilera na maaaring magkaiba. Ang bentahe ng paggamit ng isang libreng array ay hindi mo kailangang maglaan ng masyadong maraming memorya ng computer upang mapaunlakan ang isang string ng maximum na posibleng haba. Sa katunayan, ang isang libreng array ay isang one-dimensional na hanay ng mga pointer sa isang-dimensional na array ng data.

Mga payo.

Ang pointer ay isang variable na ang value ay ang address kung saan matatagpuan ang data. Ang isang address ay ang bilang ng memory cell sa o kung saan matatagpuan ang data.

Ayon sa uri ng data sa SI, ang mga pointer ay nahahati sa:

Ang naka-type na pointer ay isang pointer na naglalaman ng address ng data ng isang partikular na uri (system o user).

Ang hindi na-type na pointer ay isang pointer na naglalaman ng isang data address ng isang hindi natukoy na uri (isang address lamang).

Pagpapahayag ng pointer;

Pagtatakda ng pointer;

pag-access sa isang halaga na matatagpuan sa isang pointer. Ang deklarasyon (paglalarawan) ng isang pointer sa wikang SI ay may sumusunod na anyo:

I-type ang *name [=value];

Kapag idineklara, ang isang pointer sa SI ay maaaring masimulan sa pamamagitan ng pagpahiwatig ng katumbas na halaga sa pamamagitan ng isang tanda ng pagtatalaga. Ang halagang ito ay dapat na isang address, na nakasulat sa isa sa mga sumusunod na anyo:

Null (id NULL);

Isa pang pointer;

Variable address (sa pamamagitan ng operasyon ng pagkuha ng address);

Isang expression na kumakatawan sa pointer arithmetic;

Ang address na resulta ng isang dynamic na paglalaan ng memorya.

#isama

int var; // regular na integer variable

int *ptrVar; // integer pointer (ptrVar ay dapat na uri ng int, dahil ito ay tumutukoy sa isang variable ng uri int)

ptrVar = // itinalaga sa pointer ang address ng memory cell kung saan namamalagi ang halaga ng var variable

scanf("%d", &var); // ang variable var ay naglalaman ng value na ipinasok mula sa keyboard

printf("%d\n", *ptrVar); // output value sa pamamagitan ng pointer

Resulta ng pagpapatupad: 6 6

Lektura Blg. 3.

Mga pag-andar.

Ang isang function ay isang syntactically na tinukoy na pinangalanang module ng programa na nagsasagawa ng isang partikular na aksyon o grupo ng mga aksyon. Ang bawat function ay may sariling interface at pagpapatupad. Function interface – function header, na tumutukoy sa pangalan ng function, isang listahan ng mga parameter nito at ang uri ng return value.

Ang paglalarawan ng isang function sa wikang SI ay isinasagawa saanman sa programa sa labas ng paglalarawan ng iba pang mga function at binubuo ng tatlong elemento:

1. function prototype;

2. function header;

3. function na katawan.

Ang isang function na prototype ay isang opsyonal na bahagi ng paglalarawan ng function, na nilayon upang ideklara ang isang function na ang interface ay tumutugma sa prototype na ito Ang prototype na deklarasyon ay may sumusunod na form.

Pangalan ng uri (listahan ng mga pormal na uri ng parameter);

Ang mga parameter ng function ay mga halaga na ipinasa sa function kapag tinawag ito.

Header ng function – paglalarawan ng bahagi ng interface ng function, na naglalaman ng: ang uri ng return value, ang pangalan ng function at isang listahan ng mga pormal na parameter ng function. Ang syntax para sa pagdedeklara ng isang function header ay:

Pangalan ng uri (listahan ng mga pormal na parameter)

Mga halimbawa ng mga header ng function:

Int function(int i, double x, double y)

Void func(int ind, char *string)

Dobleng function(walang bisa)

Ang katawan ng isang function ay ang bahagi ng pagpapatupad na naglalaman ng code ng programa na pinaandar kapag tinawag ang function. Ang function body ay palaging dumarating kaagad pagkatapos ng function head (hindi sila maaaring paghiwalayin) at nakapaloob sa mga kulot na brace.

Pagpapatupad ng isang function sa SI upang kalkulahin ang factorial ng isang numero.

Double factorial(unsigned);

Double factorial(unsigned num)

Dobleng katotohanan = 1.0;

Para kay(unsigned i=1;i<=num;i++)

Katotohanan *= (doble)i;

Ibalik ang katotohanan;

Mga istruktura.

Ang istraktura ay isang kumplikadong uri ng data na kumakatawan sa isang hanay ng mga elemento ng iba't ibang uri na inayos sa memorya. Ang bawat elemento sa istraktura ay may sariling pangalan at tinatawag na isang patlang.

Ang deklarasyon sa SI ng isang istraktura ay mukhang:

Struct [type name]

Patlang_1;

Patlang_2;

Patlang_N;

   ) [listahan ng mga variable];

Ang deklarasyon ng mga patlang ng istraktura ay posible lamang nang walang pagsisimula. Kung ang ilang mga field na sumusunod sa isa't isa sa paglalarawan ng istraktura ay may parehong uri, pagkatapos ay upang ilarawan ang mga ito maaari mong gamitin ang syntax para sa pagdedeklara ng ilang mga variable ng parehong uri.

Mga file.

Ang file ay isang pinangalanang lugar ng data sa ilang storage medium. Mga uri ng file (na may kaugnayan sa wikang SI):
   teksto;
   binary.
Mga pangunahing operasyon na isinagawa sa mga file:
1.Pagbubukas ng mga file.
2.Pagbasa at pagsulat ng datos.
3.Pagsasara ng mga file.

Mga karagdagang operasyon:
1.File navigation.
2. Paghawak ng mga error kapag nagtatrabaho sa mga file.
3.Pagtanggal at pagpapalit ng pangalan ng mga file.
4.Paglalarawan ng baryabol

Mga mode ng pagbubukas mga file na may SI

Pag-redirect ng stream
  FILE * freopen(const char *filename, const char *mode, FILE *stream);

Nagbabalik ang function:
  Pointer sa file - lahat ay maayos,
  NULL – override error.

Pagsasara ng file
  int fclose(FILE *stream);

Nagbabalik ang function:
  0 – matagumpay na naisara ang file.
  1 – nagkaroon ng error sa pagsasara ng file.

Pagtatapos ng pagsusuri ng file
  int feof(FILE *stream);
  stream - pointer sa isang bukas na file.

Nagbabalik ang function:
  0 - kung ang dulo ng file ay hindi pa naabot.
  !0 – naabot na ang dulo ng file.

Pagbubukas ng mga text file
Ang pangalawang parameter ay karagdagang tumutukoy sa karakter t (opsyonal):
  rt, wt, at, rt+, wt+, at+

Pagbabasa mula sa isang text file

Formatted na Pagbasa
  int fscanf(FILE *stream, const char * format, ...);

Nagbabalik ang function:
  >0 – bilang ng matagumpay na nabasang mga variable,
  0 – wala sa mga variable ang matagumpay na nabasa,
  EOF – naabot ang error o dulo ng file.
Nagbabasa ng linya

Nagbabalik ang function:
  buffer - lahat ay maayos,
Nagbabasa ng linya
  char * fgets(char * buffer, int maxlen, FILE *stream);

Nagbabalik ang function:
  buffer - lahat ay maayos,
  NULL – naabot ang error o dulo ng file.
Pagbasa ng simbolo
  int fgetc(FILE *stream);
Nagbabalik ang function:
  code ng simbolo - kung maayos ang lahat,
  EOF – kung may error o naabot na ang dulo ng file.
Paglalagay ng character pabalik sa stream
  int ungetc(int c, FILE *stream);
Nagbabalik ang function:
  code ng simbolo - kung matagumpay ang lahat,
  EOF – may naganap na error.

Sumulat sa text SI file

Naka-format na output
  int fprintf(FILE *stream, const char *format, ...);
Nagbabalik ang function:
  bilang ng mga character na nakasulat - kung maayos ang lahat,
  negatibong halaga – kung may error.
Pagsusulat ng string
  int fputs(const char *string, FILE *stream);
Nagbabalik ang function:
  bilang ng mga character na nakasulat - lahat ay maayos,
  EOF – may naganap na error.
Sumulat ng isang simbolo
  int fputc(int c, FILE *stream);
Nagbabalik ang function:
  code ng naitala na simbolo - maayos ang lahat,
  EOF – may naganap na error.
Pagbubukas ng mga binary file
  Ang pangalawang parameter ay karagdagang tumutukoy sa simbolo b (kinakailangan): rb, wb, ab, rb+, wb+, ab+
Pagbabasa mula sa mga binary file
  size_t fread(walang bisa *buffer, size_t size, size_t num, FILE *stream);
Ibinabalik ng function ang bilang ng mga bloke na nabasa. Kung mas mababa ito sa num, may naganap o naabot na error
dulo ng file.

Pagsusulat sa isang binary file
  size_t fwrite(const void *buffer, size_t size, size_t num, FILE *stream);
Ibinabalik ng function ang bilang ng mga bloke na nakasulat. Kung mas mababa ito sa num, may naganap na error.

Pag-navigate sa file

Pagbabasa ng kasalukuyang offset sa isang file:
  long int ftell(FILE *stream);
Pagbabago ng kasalukuyang offset sa isang file:
  int fseek(FILE *stream, mahabang int offset, int pinanggalingan);

SEEK_SET (0) – mula sa simula ng file.
  SEEK_CUR (1) – mula sa kasalukuyang posisyon.
  SEEK_END (2) – mula sa dulo ng file.
Nagbabalik ang function:
  0 - lahat ay maayos,
  !0 – may naganap na error.
Ilipat sa simula ng file:
  void rewind(FILE *stream);
Pagbabasa ng kasalukuyang posisyon sa isang file:
  int fgetpos(FILE *stream, fpos_t *pos);
Pagtatakda ng kasalukuyang posisyon sa file:
  int fsetpos(FILE *stream, const fpos_t *pos);
Bumalik ang mga function:
  0 - lahat ay matagumpay,
  !0 – may naganap na error.
istraktura ng fpos_t:
  typedef struct fpos_t (
   mahaba off;
   mbstate_t wstate;
  ) fpos_t;

Pagkuha ng error sign:
  int ferror(FILE *stream);
Ang function ay nagbabalik ng isang hindi-zero na halaga kung may naganap na error.
Error reset function:
  void clearerr(FILE *stream);
Function ng mensahe ng error:
  void perror(const char *string);

Buffering

Buffer clear function:
  int fflush(FILE *stream);
Nagbabalik ang function:
  0 - lahat ay maayos.
  EOF – may naganap na error.
Buffer management function:
  void setbuf(FILE *stream, char * buffer);

Lumilikha ng buffer ng laki na BUFSIZ. Ginagamit bago ang input o output sa stream.

Pansamantalang mga file

Pansamantalang paggana ng paglikha ng file:
  FILE * tmpfile(walang bisa);
Lumilikha ng pansamantalang file sa wb+ mode. Pagkatapos isara ang file, ang huli ay awtomatikong tatanggalin.
Pansamantalang pagpapaandar ng pagbuo ng pangalan ng file:
  char * tmpnam(char *buffer);

Pagtanggal at pagpapalit ng pangalan

Function sa Pagtanggal ng File:
  int tanggalin(const char *filename);
Pag-andar ng pagpapalit ng pangalan ng file:
  int rename(const char *fname, const char *nname);
Bumalik ang mga function:
  0 - kung matagumpay,
  !0 – kung hindi.

Lektura Blg. 4.

salansan.

Ang isang stack ay ang kabaligtaran ng isang pila dahil ito ay gumagana sa isang last-in, first-out (LIFO) na batayan. Upang mailarawan ang isang stack, mag-isip ng isang stack ng mga plato. Ang unang plato na nakalagay sa mesa ay huling gagamitin, at ang huling plato na nakalagay sa itaas ay unang gagamitin. Ang mga stack ay kadalasang ginagamit sa software ng system, kabilang ang mga compiler at interpreter.

Kapag nagtatrabaho sa mga stack, ang mga operasyon ng pagpasok at pagkuha ng isang elemento ay ang mga pangunahing. Ang mga operasyong ito ay tradisyonal na tinatawag na "push" at "pop". Samakatuwid, upang ipatupad ang isang stack, kailangan mong magsulat ng dalawang function: push(), na "nagtutulak" ng isang halaga sa stack, at pop(), na "nagpapa-pop" ng isang halaga mula sa stack. Kailangan mo ring maglaan ng isang lugar ng memorya na gagamitin bilang isang stack. Para sa layuning ito, maaari kang maglaan ng array o dynamic na maglaan ng isang piraso ng memorya gamit ang mga function ng C language na ibinigay para sa dynamic na paglalaan ng memorya. Tulad ng isang queue, ang fetch function ay kumukuha ng isang elemento mula sa listahan at inaalis ito kung hindi pa ito nakaimbak sa ibang lugar. Nasa ibaba ang pangkalahatang anyo ng push() at pop() na mga function na gumagana sa isang integer array. Maaaring ayusin ang iba pang mga uri ng data stack sa pamamagitan ng pagbabago sa pinagbabatayan na uri ng data ng array.

int tos=0; /* tuktok ng stack */

/* Itulak ang isang elemento sa stack. */

void push(int i)

if(to >= MAX) (

printf("Puno na ang stack\n");

/* Kunin ang nangungunang elemento ng stack. */

kung (tos< 0) {

printf("Walang laman ang stack\n");

ibalik ang stack;

Ang tos variable ("tuktok ng stack") ay naglalaman ng index ng tuktok ng stack. Kapag ipinapatupad ang mga function na ito, kinakailangang isaalang-alang ang mga kaso kapag ang stack ay puno o walang laman. Sa aming kaso, ang tanda ng isang walang laman na stack ay ang tos ay katumbas ng zero, at ang tanda ng isang stack overflow ay ang tos ay tumataas nang labis na ang halaga nito ay tumuturo sa isang lugar sa kabila ng huling cell ng array.

Isang halimbawa ng pagtatrabaho sa isang stack.

Ang stack ay matatagpuan sa dynamic na inilaan na memorya, at hindi sa isang nakapirming laki ng array. Bagama't hindi kinakailangan ang paggamit ng dynamic na memory allocation sa ganitong simpleng halimbawa, makikita natin kung paano gumamit ng dynamic na memory upang mag-imbak ng data ng stack.

/* Isang simpleng calculator na may apat na hakbang. */

#isama

#isama

int *p; /* pointer sa libreng memory area */

int *tos; /* pointer sa tuktok ng stack */

int *bos; /* pointer sa ibaba ng stack */

void push(int i);

p = (int *) malloc(MAX*sizeof(int)); /* kumuha ng memory para sa stack */

printf("Error habang naglalaan ng memory\n");

bos = p + MAX-1;

printf("Apat na hakbang na calculator\n");

printf("Pindutin ang "q" para lumabas\n");

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

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

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

printf("Hatiin sa 0.\n");

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

case ".": /* ipakita ang mga nilalaman ng tuktok ng stack */

printf("Kasalukuyang halaga sa tuktok ng stack: %d\n", a);

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

/* Pagtulak ng elemento sa stack. */

void push(int i)

kung(p > bos) (

printf("Puno na ang stack\n");

/* Kunin ang nangungunang elemento mula sa stack. */

kung (p< tos) {

printf("Walang laman ang stack\n");

Nakapila.

Ang queue ay isang linear na listahan ng impormasyon na pinoproseso sa first-in, first-out na batayan; ang prinsipyong ito (at ang queue bilang isang istraktura ng data) ay tinatawag ding FIFO. Nangangahulugan ito na ang unang elemento na inilagay sa queue ay matatanggap mula dito, ang pangalawang elemento na inilagay ay aalisin pangalawa, atbp. Ito ang tanging paraan upang gumana sa isang pila; Ang random na pag-access sa mga indibidwal na elemento ay hindi pinahihintulutan.

Upang isipin kung paano gumagana ang isang queue, ipakilala natin ang dalawang function: qstore() at qretrieve() (mula sa "store" - "save", "retrieve" - ​​​​"receive"). Ang qstore() function ay naglalagay ng elemento sa dulo ng queue, at ang qretrieve() function ay nag-aalis ng isang elemento mula sa simula ng queue at nagbabalik ng halaga nito. Ipinapakita ng talahanayan ang pagkakasunud-sunod ng mga naturang operasyon.

Aksyon Mga Nilalaman ng Queue
qstore(A) A
qstore(B) A B
qstore(C) A B C
qretrieve() ay nagbabalik ng A B C
qstore(D) B C D
qretrieve() ay nagbabalik ng B C D
qretrieve() ay nagbabalik ng C D

Tandaan na ang pagpapatakbo ng pagkuha ay nag-aalis ng isang elemento mula sa pila at sinisira ito maliban kung ito ay nakaimbak sa ibang lugar. Samakatuwid, pagkatapos na makuha ang lahat ng mga elemento, ang pila ay walang laman.

Sa programming, ang mga pila ay ginagamit upang malutas ang maraming mga problema. Ang isa sa mga pinakasikat na uri ng naturang mga gawain ay ang simulation. Ginagamit din ang mga pila sa mga operating system task scheduler at sa I/O buffering.

/* Mini event scheduler */

#isama

#isama

#isama

#isama

char *p, *qretrieve(walang bisa);

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

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

walang laman na mga pointer */

printf("Enter (E), List (L), Delete (R), Exit (Q): ");

*s = topper(*s);

/* Magpasok ng bagong appointment sa pila. */

walang bisa pumasok(walang bisa)

printf("Ipasok ang appointment %d: ", spos+1);

if(*s==0) ​​​​break; /* walang recording na ginawa */

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

printf("Hindi sapat ang memorya.\n");

if(*s) qstore(p);

/* Tingnan ang mga nilalaman ng pila. */

walang bisang pagsusuri(walang bisa)

para sa(t=rpos; t< spos; ++t)

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

/* Alisin ang appointment sa pila. */

void delete_ap(void)

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

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

/* Maglagay ng appointment. */

void qstore(char *q)

printf("Buong Listahan\n");

/* Kumuha ng appointment. */

char *qretrieve(walang bisa)

if(rpos==spos) (

printf("Wala nang meeting.\n");

ibalik ang p;

Listahan.

Ang isang solong naka-link na cyclic na listahan ay isang recursive na deklarasyon ng mga istruktura, o sa halip ay isang pointer dito sa mismong uri ng istraktura:

int data; // field ng data

s *susunod;//susunod na elemento

) *una,*curr;//una at kasalukuyang elemento

Pagsisimula:

una->susunod=curr;

para makuha ang unang elemento gamitin muna->data

para magdagdag ng bagong elemento: curr->next=new s;

curr=curr->next;//pumunta sa huli

at upang makuha, halimbawa, ang ika-50 elemento, i-loop sa listahan:

curr=first;//pumunta sa una

para sa(int i=0;i<50;i++)

if(curr->next!=NULL)

curr=curr->next;


Kaugnay na impormasyon.


First timer sa website na ito, kaya eto na.

Ako ay bago sa C++ at kasalukuyang nagtatrabaho sa aklat na "Data Structures Using C++ 2nd ed, D.S. Malik".

Sa aklat, nag-aalok si Malik ng dalawang paraan upang lumikha ng isang dynamic na two-dimensional array. Sa unang paraan, idineklara mo ang isang variable bilang isang hanay ng mga pointer, kung saan ang bawat pointer ay uri ng integer. hal

Int *board;

At pagkatapos ay gumamit ng for-loop upang lumikha ng "mga haligi" kapag gumagamit ng isang hanay ng mga pointer bilang "mga hilera".

Pangalawang paraan, gumamit ka ng isang pointer sa isang pointer.

Int **board; board = bagong int* ;

Ang tanong ko ay: aling paraan ang mas mahusay? Ang ** paraan ay mas madali para sa akin upang mailarawan, ngunit ang unang paraan ay maaaring gamitin sa halos parehong paraan. Ang parehong mga pamamaraan ay maaaring gamitin upang lumikha ng mga dynamic na 2-dimensional na array.

I-edit: Hindi sapat na malinaw tulad ng nakasaad sa itaas. Narito ang code na sinubukan ko:

Int row, col; cout<< "Enter row size:"; cin >> hilera; cout<< "\ncol:"; cin >>col; int *p_board; para sa (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 na sagot

Ang unang paraan ay hindi maaaring gamitin upang lumikha pabago-bago 2D arrays dahil:

Int *board;

mahalagang inilaan mo ang isang hanay ng 4 na mga payo sa int bawat stack. Kaya kung pupunan mo na ngayon ang bawat isa sa 4 na pointer na ito ng isang dynamic na array:

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

kung ano ang napunta sa iyo ay isang 2D array na may static ang bilang ng mga linya (sa kasong ito 4) at pabago-bago bilang ng mga column (sa kasong ito 10). Kaya, ang dynamics ay hindi ganap, dahil kapag naglalaan ng array sa stack mo dapat ipahiwatig pare-pareho ang sukat, ibig sabihin. Kilala sa oras. Dynamic ang array ay tinatawag pabago-bago, dahil hindi kailangang malaman ang laki nito sa oras ng pag-compile, ngunit sa halip ay maaaring tukuyin ng ilang variable sa sa panahon ng pagpapatupad.

Muli kapag ginawa mo:

Int *board;

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

nagbibigay ka ng patuloy na kilala sa oras ng pag-compile(sa kasong ito 4 o x) upang ang compiler ay maaari na ngayon paunang piliin ang memorya na ito para sa iyong array, at kapag na-load ang iyong program sa memorya, magkakaroon na ito ng ganitong halaga ng memory para sa board array, kaya naman tinawag itong static, ibig sabihin. ang laki kasi hard coded At hindi maaaring magbago nang pabago-bago(sa runtime).

Sa kabilang banda, kapag ginawa mo:

Int **board; board = bagong int*;

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

hindi alam ng compiler kung gaano karaming memory ang kakailanganin ng board array, kaya hindi naglalaan nang maaga Lahat. Ngunit kapag pinatakbo mo ang iyong programa, ang laki ng array ay matutukoy ng halaga ng x variable (sa runtime), at ang kaukulang espasyo para sa board array ay ilalaan sa tinatawag na isang bungkos- isang lugar ng memorya kung saan ang lahat ng mga program na tumatakbo sa iyong computer ay maaaring maglaan hindi kilala nang maaga(sa oras ng pag-compile) ay nagbubuod ng memorya para sa personal na paggamit.

Bilang resulta, upang aktwal na lumikha ng isang dynamic na 2D array, kailangan mong pumunta sa pangalawang paraan:

Int **board; board = bagong int*; // dynamic array (size 10) ng mga pointer sa int para sa (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 }

Kakagawa lang namin ng 10 by 10 square 2D array Para mapuntahan ito at punan ito ng mga aktwal na value, tulad ng 1, maaari kaming gumamit ng mga nested loops.

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

Ang inilalarawan mo para sa pangalawang paraan ay gumagawa lamang ng 1D array:

Int *board = bagong int;

Naglalaan lamang ito ng array na may 10 elemento. Marahil ay ganito ang ibig mong sabihin:

Int **board = bagong int*; para sa (int i = 0; i< 4; i++) { board[i] = new int; }

Sa kasong ito, naglalaan kami ng 4 int* s at pagkatapos ay ang bawat punto sa isang dynamic na inilalaan na hanay ng 10 int s.

Kaya ngayon ihahambing namin ito sa int* board; . Ang pangunahing pagkakaiba ay kapag gumagamit ng ganoong array, ang bilang ng mga "row" ay dapat malaman sa oras ng pag-compile. Ito ay dahil ang mga array ay dapat na may mga nakapirming laki ng oras ng pag-compile. Maaari ka ring magkaroon ng problema kung gusto mong ibalik ang array na ito mula sa int* s, dahil masisira ang array sa dulo ng saklaw nito.

Ang isang paraan na dynamic na naglalaan ng parehong mga row at column ay nangangailangan ng mas kumplikadong mga hakbang upang maiwasan ang mga pagtagas ng memorya. Dapat mong palayain ang memorya tulad nito:

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

Kailangan kong magrekomenda sa halip na gumamit ng karaniwang lalagyan. Maaari mong gamitin ang std::array 4> o marahil std::vector > na pinasimulan mo sa naaangkop na laki.

Sa parehong mga kaso, ang iyong panloob na dimensyon ay maaaring dynamic na itakda (ibig sabihin, kinuha mula sa isang variable), ngunit ang pagkakaiba ay nasa panlabas na dimensyon.

Ang tanong na ito ay karaniwang katumbas ng sumusunod:

Ay int* x = bagong int; "mas mahusay" kaysa sa int x ?

Ang sagot ay "hindi, maliban kung kailangan mong piliin ang laki ng array na iyon nang pabago-bago."

Ang code na ito ay gumagana nang maayos sa napakakaunting mga panlabas na kinakailangan sa library at nagpapakita ng pangunahing paggamit ng int **array .

Ang sagot na ito ay nagpapakita na ang array bawat isa ay may dynamic na laki at kung paano magtalaga ng dynamic na laki ng linear array sa isang dynamic na laki ng branch array.

Ang program na ito ay kumukuha ng mga argumento mula sa STDIN sa sumusunod na format:

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

Ang code para sa programa ay nasa ibaba...

#isama 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;< size_current_array; j++) { int tmp = 0; std::cin >int *tmp_array = bagong int;< num_queries; q++) { std::cin >para sa (int j = 0; j<< "Current x & y: " << x << ", " << y << "\n"; std::cout << array_of_arrays[x][y] << "\n"; } return 0; }

>tmp;