Զանգվածներ
!!! Վերանվանել «Հավաքածուներ» !!!
Զանգվածը նույն տիպն ունեցող տարրերի հավաքածու է, որոնք տեղավորված են հիշողության անընդհատ տիրույթում։ C++ լեզվի ստանդարտ գրադարանում իրականացված են երկու տեսակի զանգվածներ՝ array
և vector
դասերով։ array
դասով մոդելավորվում են ֆիքսված չափով զանգվածները, իսկ vector
դասով՝ դինամիկ ընդլայնվող զանգվածները։
Սկսենք array
դասից։ Ենթադրենք ունենք drone
անօդաչու թռչող սարքը (ԱԹՍ), որը կարող է օդում մնալ առավելագույնը երկու ժամ։ Ղեկավարող համակարգիչը (server) ամեն կես րոպեն մեկ գրանցում է ԱԹՍ-ի թռիչքի բարձրությունն ու արագությունը։ Այդ տվյալները հարմար է պահել double
տարրերի height
և speed
զանգվածներում։ Ահա դրանց սահմանումները.
array<double,120> speed = { 0 }; // արագություն
array<double,120> heigth = { 0 }; // բարձրություն
Այստեղ array
դասի օբյեկտ սահմանելիս առաջին պարամետրով նշում ենք զանգվածի տարրերի տիպը, իսկ երկրորդով՝ չափը։ Քանի որ լեզվի ներդրված տիպերի համար array
-ի բոլոր տարրերն սկզբնարժեքավորվում են անորոշ արժեքներով, speed
և height
զանգվածներն արժեքավորում ենք զրո արժեքներով։ ?? Համոզվելու համար կարելի է, օրինակ, արտածել բոլոր տարրերը.
for( auto e : speed )
cout << e << endl;
array
տիպի զանգվածի բոլոր տարրերին մի որևէ սկզբանական արժեք վերագրելու համար նախատեսված է նրա fill()
մեթոդը։
speed.fill(0);
Տվյալների հարցման և գրանցման ցիկլը, որ պետք է աշխատի առանձին հոսքում (տես Կատարման հոսքեր գլուխը), կունենա մոտավորապես այսպիսի տեսք։
int ix = 0;
while( drone.inFlight() ) {
speed[i] = drone.getSpeed(); // գրանցել արագությունը
height[i] = drone.getHeight(); // գրանցել բարձրությունը
this_thread::sleep_for(30s); // սպասել կես րոպե
++ix;
}
isFlight()
պրեդիկատը դրական պատասխան է տալիս այն դեպքում, երբ ԱԹՍ-ն օդում է, getSpeed()
ֆունկցիան վերադարձնում է արագությունը, իսկ getHeight()
-ը՝ բարձրությունը։ this_thread
անունների տիրույթի sleep_for()
ֆունկցիան հոսքի կատարումը կանգնեցնում (սպասեցնում) է իր արգումենտում նշված չափով։ Ցիկլի ավարտին ix
փոփոխականը ցույց կտա, թե քանի անգամ է տվյալների գրանցում կատարվել։
Հիմա, ենթադրենք, ավարտվել է ԱԹՍ-ի թռիչքը, և փորձարկողն ուզում է ինչ-որ վիճակագրական տվյալներ թռիչքի ընթացքից։ Հաշվենք թռիչքի միջին արագությունը. դրա համար պետք է գումարել արագության բոլոր գրառումները և բաժանել քանակի վրա.
double avgSpeed = 0.0;
for( auto e : speed )
avgSpeed += e;
avgSpeed /= ix;
cout << avgSpeed << endl;
height
զանգվածի վրայով անցնելով կարող ենք հաշվել ԱԹՍ-ի թռիչքի առավելագույն բարձրությունը.
double maxHeight = height[0];
for( int i = 1; i < ix; ++i )
if( height[i] > maxHeight )
maxHeight = height[i];
cout << maxHeight << endl;
Այս օրինակում height
զանգվածի տարրերին դիմելու համար օգտագործել ենք ինդեքսավորման (կամ՝ տարրին դիմելու) []
գործողությունը։
ԱԹՍ-ներին մի կողմ թողնենք և անցնենք «ռազմաճակատի» մյուս կողմը։ Դիցուք ունենք շուրջօրյա հերթապահության ռեժիմում աշխատող մի ռադիոտեղորոշիչ կայան (ՌՏԿ, ռադար), որը հսկում է 100 կմ օդային տարածք։ Ամեն անգամ, երբ ռադարի հսկողության տիրույթում հայտնվում է մի որևէ թռչող օբյեկտ, այն գրանցում է օբյեկտի ազիմուտը, հեռավորությունը, բարձրությունը և գրառման ժամանակը՝ համապատասխանաբար azimuth
, distance
, height
և timestamp
զանգվածներում։ Նորից պարզության համար ենթադրենք, որ մեր ՌՏԿ-ն կարողանում է հետևել միայն մեկ թռչող սարքի։
Խնդրի նկարագրությունից պարզ է, որ նշված զանգվածները չեն կարող սահմանվել ֆիքսված չափերով. ի սկզբանե հայտնի չէ, և չի էլ կարող հայտնի լինել, թե ինչ քանակով ու հաճախությամբ կարող են լինել օդային տարածքի խախտումները։ Նմանատիպ դեպքերի համար C++ լեզվի ստանդարտ գրադարանն առաջարկում է vector
դասը. այս դասի օբյեկտ զանգվածները հնարավորություն ունեն ըստ պահանջի ընդլայնվելու։
Եվ այսպես. սահմանենք վերը նշված չորս զանգվածները.
vector<double> azimuth; // ազիմուտ
vector<double> distance; // հեռավորություն
vector<double> height; // բարձրություն
vector<chrono::time_point> timestamp; // ժամանակ
Այս սահմանումներում ոչ մի չափ նշված չէ։ Եթե արտածենք զանգվածներից որևէ մեկի տարողությունը, ապա կտեսնենք, որ այն զրո է։ ??
cout << azimuth.capcaity() << endl; // զանգվածի տարողությունը
cout << azimuth.size() << endl; // տարրերի քանակը
Եթե պետք է vector
ցանգվածի մեջ նոր տարր ավելացնել, ապա օգտագործում ենք push_back()
մեթոդը։ Օրինակ, դիտարկենք ՌՏԿ֊ի աշխատանքային ցիկլը։ Այն կունենա մոտավորապես հետևյալ տեսքը․
// քանի դեռ ՌՏԿ-ն աշխատում է ...
while( radar.inService() ) {
// եթե օբյեկտ է հայտնաբերվել
if( auto obj = detected() ) {
// գրանցել հայտնաբերման ժամանակը ...
timestamp.push_back(chrono::high_resolution_clock::now());
// ... և օբյեկտի ազիմուտը
azimuth.push_back(obj.getAzimuth());
// ... և օբյեկտի հեռավորությունը
distance.push_back(obj.getDistance());
// ... և օբյեկտի թռիչքի բարձրությունը
height.push_back(obj.getHeight());
}
}
-- շարունակել վեկտորի տարրերի թվարկման մասին, at() մեթոդի մասին, erase()-ի մասին, դատարկ լինելը ստուգելու մասին --
-- մի երկու բառ էլ C զանգվածների մասին --