Автор работы: Пользователь скрыл имя, 07 Февраля 2013 в 06:33, творческая работа
Үнсіз келісім бойынша теңдікті тексеру == операторы арқылы орындалады, ал реттеу
<(кіші) операторы арқылы. Стандартты кітапхананың алгоритмдері <algorithm> тақырыбында анықталған. Бұдан да нақты мәліметтерді оқырмандар Б.5 және 20.7 қосымшаларында таба алады. Бұл алгоритмдер бір немесе екі реттілікпен жұмыс істей алады. Берілген реттілік жұп итераторлармен анықталады, ал нәтижелік реттілік оның бірінші элементіне орнатылған итератормен анықталады.
Copy operations
copy(b,e,b2) [b : e) реттілігін [b2 : b2 + (e-b)) реттілігіне көшіреді
unique_copy(b,e,b2) [b : e) реттілігін [b2 : b2 + (e-b)) реттілігіне көршілес көшірмелерді тастап көшіреді
copy_if(b,e,b2,p) р предикатын қанағаттандыратын элементтерді [b : e) реттілігінен [b2 : b2 + (e-b)) реттілігіне көшіреді
21.7.1 Copy() алгоритмі
Copy() алгоритмінің негізгі версиясы келесі түрде анықталған:
template<class In, class Out> Out copy(In first, In last, Out res)
{
while (first!=last) {
*res = *first; // элементті көшіреді
++res;
++first;
}
return res;
}
Итераторлар жұбын алып, сopy() алгоритмі итераторы бірінші элементке анықталған бір реттілікті екіншісіне көшіреді. Мысал қарастырайық:
void f(vector<double>& vd, list<int>& li)
// int типті тізім сандарын
// double типті вектор сандарына өшіреді
{
if (vd.sizeO < li.sizeO) error ("мақсатты контейнер тым кішкентай");
copy (li.begin() , li.end(), vd.begin());
// . . .
}
Кіретін (входной) реттіліктің типі нәтижелік реттіліктің типімен сәйкес келмеуіне назар аударыңыздар! Бұл жағдай STL кітапханасының алгоритмдерінің әмбебаптығын жоғарылатады: олар барлық реттіліктер түрімен олардың іске асырылуын артық жорамалдамай жұмыс істейді. Біз нәтижелік реттілікте енгізілетін элементтерді жазу үшін жеткілікті орын бар екендігін тексеруді ұмытқан жоқпыз. Мұндай тексеріс программисттің міндеті болып табылады. STL кітапханасының алгоритмдері максимал әмбебаптық пен ұтымды өнімділікке жету үшін программаланған; үнсіз келісім бойынша олар тұтынушыларды қорғайтын диапазондарды тексермейді және басқа тесттерді орындамайды. Қажет болғанда тұтынушы мұндай тексерісті өзі орындауы керек.
21.7.2 Итераторлар ағындары
Сіз «шығару ағынына көшіру» немесе «енгізу ағынынан көшіру» деген сөйлемдерді жиі еститін боласыз. Бұл кейбір енгізу-шығару түрлерінің тиімді әрі ыңғайлы сипаттау тәсілі. Бұл операцияларды орындау үшін сopy() алгоритмі қолданылады.
Реттіліктердің ерекшеліктерін еске салайық.
Енгізу және шығару ағындарын да тура солай сипаттауға болады. Мысал қарастырайық.
ostream_iterator<string> oo(cout); // *оо ағынын cout ағынымен
// жазу үшін байланыстырамыз
*оо = "Hello, "; //яғни cout << "Hello, "
++оо; // "келесі элементті шығару үшін дайын"
*оо = "World!\ n"; // яғни cout << "World!\n"
Стандарт кітапханада шығару ағынынмен жұмыс істейтін ostream_iterator деген тип бар; ostream_iterator<T> - бұл Т типті мәндерді жазу үшін қолданылатын итератор.
Сонымен қатар стандарт кітапханада Т типті мәндерді оқу үшін іstream_iterator<T> деген тип бар.
istream_iterator<string> ii(cin); // *ii оқуы — бұл cin - нан
// тіркесті оқу
string s1 = *ii; // яғни cin>>sl
++ii; // "келесі элементті енгізу үшін дайын"
string s2 = *ii; // яғни cin>>s2
ostream_iterator және іstream_iterator қолдана отырып, сopy() алгоритмі арқылы мәліметтерді енгізуге және шығаруға болады. Мысалы, тез арада жасалынған сөздікті келесі түрде жасауға болады:
int main ()
{
string from, to;
cin » from >> to; // бастапқы және мақсатты
// файлдардың аттарын енгіземіз
ifstream is (from.c_str()) ; // енгізу ағынын ашамыз
ofstream os(to.c_str());
// шығару ағынын ашамыз
istream_iterator<string> ii(is); // ағыннан енгізу итераторын құрамыз
istream_iterator<string> eos; // енгізудің сигналды белгісі
ostream_iterator<string> 00(os, "\n"); // итератор құрамыз
// ағынға шығару
vector<string> b(ii,eos); // b — вектор, енгізу ағынының мәліметтерімен
// инициализацияланады
sort (b.begin () ,b.end()); // буферді сорттау
copy(b.begin() ,b.end() ,оо); // шығару үшін көшіру буфері
}
Еos итераторы – бұл "енгізу соңын" білдіретін сигналды белгі. istream ағыны енгізу соңына жеткенде оның үнсіздік бойынша берілетін және eos деп аталынатын istream_iterator итераторы istream_iterator – ға тең болады.
Біз vector классының объектісін итераторлар жұбы арқылы инициализациялайтынымызға назар аударыңыз. Контейнерді инициализациялайтын (а, b) итераторлар жұбы келесіні білдіреді: "[a:b) реттілігін контейнерге санау(считать)". Бұл үшін біз (ii,eos) итераторлар жұбын қолданамыз – енгізудің басы мен аяғы. Бұл бізге >> операторын және push_back() функциясын айқын қолданбауға мүмкіндік береді. Біз басқа варианттарды қолданбауға ұсыныс береміз.
vector<string> b(max_size); // бастапқы мәліметтердің көлемін болжамай-ақ
// қойыңыз
сору(ii,eos,b.begin());
Енгізу ағынының көлемін болжап білуге тырысатын адамдар, әдетте, оны жете бағаламайды және буферді толтырып тастайды, соның себебінен өзіне әрі тұтынушыға проблема тудырады. Буфердің толып кетуі мәліметтердің түгелдігіне қауіп төндіреді.
Программаны жұмыс істейтін күйіне келтіріп, оны бірнеше жүз сөзден тұратын шағын файл арқылы тестілеп көріңіз. Содан кейін бастапқы мәліметтер көлемі болжап білінетін"қолдануға ұсынылмайтын версияны" тестілеп көріңіз және b енгізу буфері толып кеткен жағдайда не болатынын бақылаңыз. Сіз жаман ештеңе байқамаған әрі сол программаны тұтынушыға ұсынған жерді ең жаман сценарий екендігіне назар аударыңыз!
Жаттығулар