Оператори за цикли
1.Въведение
Да се разгледа следната задача:
Задача 1: Да се състави програма, която въвежда цяло число x и извежда на екрана първите три цели числа, по-големи от x.
Примерен вход: x=21 Примерен изход: 22
23
24
#include<iostream.h> int main() { int x; cout<<"x="; cin>>x; cout<<x+1<<endl; cout<<x+2<<endl; cout<<x+3<<endl; return 0; }
При вход от клавиатурата 21 програмата ще изведе числата 22, 23 и 24.
Представете си как ще се реши задачата, ако нейното условие изискваше изход не на 3, а на 100 числа? Ами на 1000?
Не е логично да използваме горния начин, тъй като това означава да изпишем най-малко 100 реда код (съответно 1000 реда код). Разглеждайки подробно решението, забелязваме, че има зависимост между операторите, извеждащи числата. Тази зависимост може да се представи като цикличен алгоритъм.
Алгоритъм, в който дадена група от действия се изпълнява необходимият брой пъти, докато е изпълнено дадено условие, се нарича цикличен (цикъл).
Цикълът съдържа четири основни съставни части:
- Инициализация – задава се начална стойност на някои променливи, участващи в цикъла;
- Тяло на цикъла – съдържа действията, които се повтарят многократно;
- Актуализация – обновяване стойностите на участващите величини и подготовка за следващото изпълнение на цикъла;
- Условие за край на цикъла – гарантира прекратяване изпълнението на цикъла.
Едно изпълнение на тялото на цикъла се нарича итерация.
В зависимост от това дали броят на повторенията на тялото на цикъла е предварително известен или не, цикличните процеси се делят на два основни вида:
- индуктивни (броят на повторенията е известен предварително);
- итеративни (броят на повторенията не е известен предварително).
За създаване на циклични алгоритми в езика С++ се използват три оператора. При използването им от съществено значение е кои действия ще се повтарят и до кога ще се повтарят те.
2. Оператор за броячен цикъл for
Синтаксис:
for(<инициализация>;<условие>;<корекция>) <оператор>;
където:
<инициализация> задава началната стойност на една или няколко променливи;
<условие> е логически израз;
<корекция> е един или няколко оператора, които обикновено влияят на <условие>;
<оператор> е произволен допустим за езика С++ оператор, който се нарича тяло на цикъла. Допустимо е тялото на цикъла да бъде изградено от два и повече оператори, като в този случай те се ограждат в операторни скоби.
{
<оператор_1>;
<оператор_2>;
…
<оператор_N>;
}
Семантика:
- Изпълнението на оператора започва с частта <инициализация>.
- Изчислява се стойността на <условие>.
- Ако тази стойност е false, цикълът прекратява своето действие. Ако стойността е true, се изпълнява <оператор> (тялото на цикъла).
- Изпълняват се операторите в частта <корекция> и се преминава към стъпка 2.
Ще решим Задача 1 чрез цикъл for, но не конкретно за първите 3 числа, по-големи от x, а за произволен брой такива. Колко да бъдат те ще се зададе чрез променлива n в програмата.
Примерен вход: x=15 Примерен изход: 16
n=6 17
18
19
20
21
Решение:
#include<iostream.h> int main() { int x,n; cout<<"x="; cin>>x; cout<<"n="; cin>>n; for(int i=1;i<=n;i++) cout<<x+i<<endl; return 0; }
Цикълът for oсновно се използва за индуктивни циклични процеси, а променливата i от горния пример се нарича управляваща променлива на цикъла. Тя служи предимно за задаване броя на повторенията на цикъла. В много от задачите обаче тази променлива участва и в тялото му. Един пример за това е следната задача:
Задача 2: Да се състави програма, която въвежда от клавиатурата естествено число n и извежда всички естествени числа, по-малки от n и кратни на 5.
Примерен вход: n=14 Примерен изход: 5
10
Решение:
#include<iostream.h> int main() { unsigned int n; cout<<"n="; cin>>n; for(int i=1;i<=n;i++) if(i%5==0) cout<<i<<endl; return 0; }
По-ефективно решение може да се направи, като се знае, че първото естествено число, което се дели на 5 без остатък, е 5, а всяко следващо е с 5 по-голямо от предишното. Опитайте се да решите самостоятелно задачата по този начин.
Задача 3: Да се състави програма, която въвежда от клавиатурата петцифрено естествено число k и го извежда в обратен ред на цифрите му.
Примерен вход: k=78213 Примерен изход: 31287
За решението на задачата ще ползваме следния алгоритъм:
1). Последната цифра на k се отделя като остатък при деление на k с 10 и се извежда на екрана.
2). Посредством целочислено деление на k с 10 се получава нова стойност за k, която има една цифра по-малко.
3). Предните две действия се повтарят 5 пъти, колкото са цифрите на числото.
Решение:
//Program_3a.cpp; #include<iostream.h> int main() { unsigned long int k; cout<<"k="; cin>>k; for(int i=1;i<=5;i++) { cout<<k%10; //Извежда последната цифра k=k/10; //Премахва последната(изведена вече)цифра } return 0; }
3. Цикъл с предусловие
Синтаксис:
while(<условие>) <оператор>;
където:
<условие> е логически израз (най-често израз за сравнение), чийто резултат е от логически тип. Нарича се условие за край на цикъла.
<оператор> (тяло на цикъла) е произволен допустим за езика С++ оператор. В случай че в тялото на цикъла е необходимо да бъдат използвани два или повече оператора, се използва конструкцията блок:
{
<оператор_1>;
<оператор_2>;
…
<оператор_N>;
}
Семантика:
- Изчислява се стойността на логическия израз <условие>.
- Ако тази стойност е false цикълът прекратява своето действие. Ако стойността е true, се изпълнява тялото на цикъла и се преминава към стъпка 1.
Проверката на условието се извършва преди тялото на цикъла, което означава, че тялото може да не се изпълни нито веднъж. В тялото на цикъла трябва да има оператори, които водят до промяна стойността на логическия израз <условие>, за да не се получи зацикляне.
Ако трябва да се реши Задача 3 за число с произволен брой цифри, процесът вече е итеративен, т.е. не се знае броят на повторенията. Поради тази причина по-удобен за ползване e операторът за цикъл с предусловие. За решаване на задачата ще използваме алгоритъм, подобен на вече описания.
1). Последната цифра на k се отделя като остатък при деление на k с 10 и се извежда на екрана.
2). Посредством целочислено деление на k с 10 се получава нова стойност за k, която има една цифра по-малко.
3). Предните две действия се повтарят, докато k получи стойност нула. Това е условието за край на цикъла.
Защо тялото на този цикъл ще се изпълни толкова пъти, колкото са цифрите на числото?
Примерен вход: k=845 Примерен изход: 548
Примерен вход: k=392721 Примерен изход: 127293
Кодът на задачата изглежда по следния начин:
Решение:
//Program_3b.cpp; #include<iostream.h> int main() { unsigned long int k; cout<<"k="; cin>>k; while(k!=0) { cout<<k%10; //Извежда последната цифра k=k/10; //Премахва последната цифра } return 0; }
4. Цикъл със следусловие
Синтаксис:
do
<оператор>;
while(<условие>);
където:
<условие> е логически израз (най-често израз за сравнение), чийто резултат е от логически тип. Нарича се условие за край на цикъла.
<оператор> (тяло на цикъла) – произволен допустим за езика С++ оператор. В случай, че в тялото на цикъла е необходимо да бъдат използвани два или повече оператора, те се ограждат в операторни скоби:
{
<оператор_1>;
<оператор_2>;
…
<оператор_N>;
}
Семантика:
- Изпълнява се тялото на цикъла – <оператор>.
- Изчислява се стойността на логическия израз – <условие>.
- Ако тази стойност е false, цикълът прекратява своето действие. Ако стойността е true, се преминава към стъпка 1.
Проверката на условието се извършва след тялото на цикъла, което означава, че тялото се изпълнява поне веднъж. Задължително е в тялото на цикъла да има оператори, които водят до промяна стойността на логическия израз, за да не се получи зацикляне.
Задача 4: Да се напише програма, която въвежда от клавиатурата естествено число n и цифра p. Ако в записа на числото n се съдържа цифра p, да се изведе на монитора “да”, в противен случай – “не”.
Примерен вход: n=72715 Примерен изход: не
p=6
Примерен вход: n=59213 Примерен изход: да
p=2
Решение:
#include<iostream.h> int main() { unsigned long int n,p,k; cout<<"n="; cin>>n; cout<<"p="; cin>>p; do { k=n%10; //Намира последната цифра n=n/10; //Премахва последната цифра } while((k!=p)&&(n!=0)); if(k==p)cout<<"да"<<endl; else cout<<"не"<<endl; return 0; }
5. Основни алгоритми, реализиращи се с циклични оператори
- Проверка за коректност на входни данни
В много от задачите се налага да се въвеждат данни, които отговарят на предварително зададени условия. Следната задача показва коректно съставено условие за проверка дали въведено число е в даден интервал. За реализацията на задачата е подходящо да се ползва цикъл while.
Задача 5: От клавиатурата се въвежда естествено число n в интервала 5<=n<=50. Ако числото не е в този интервал да се изисква ново въвеждане. При коректно зададен вход за n да се изчисли и изведе квадрата му.
Решение:
//Program_5.cpp; #include<iostream.h> int main() { int n; cout<<„n="; cin>>n; while((n<5)||(n>50)) { cout<<„Некоректни данни! Въведи отново n!"<<endl; cout<<„n="; cin>>n; } cout<<n*n<<endl; return 0; }
Опитайте се да направите проверка за коректност на входни данни като използвате цикъл do … while.
- Намиране на максимален и минимален елемент в редица от числа
За намиране на максимален и минимален елемент може да се разгледат два случaя. В първия броят на числата в редицата е предварително известен, а във втория – броят на числата от редицата не е известен. За решението е удобно да се декларират три променливи с имена max, min и chislo. Първата да служи за съхранение на максималния елемент, втората – за минималния, а променливата chislo – за въвеждане на числата от редицата.
Задача 6: Да се напише програма, която въвежда от клавиатурата естествено число n и след него n на брой реални числа. Да се изведат максималното и минималното от тях.
Примерен вход: 5 Примерен изход: Min=-45
-6 -2 -45 -7 -1.3 Max=-1.3
Решение:
#include<iostream.h> int main() { int n; cin>>n; double max,min,chislo; cin>>chislo; min=chislo; // min и max се инициализират max=chislo; // с първата въведена стойност for(int i=1;i<=n-1;i++) { cin>>chislo; if(chislo>max) max=chislo; if(chislo<min) min=chislo; } cout<<"Min="<<min<<endl; cout<<"Max="<<max<<endl; return 0; }
Задача 7: Да се напише програма, която въвежда последователно от клавиатурата реални числа до момента, в който се въведе числото нула. Да се изведат на монитора минималното и максималното от въведените числа, без да се включва нулата.
Примерен вход: 5.1
6
2.2
8.4
2
–3
0
Примерен изход: Min=-3
Max=8.4
Решение:
#include<iostream.h> int main() { double max,min,chislo; cin>>chislo; min=chislo; // min и max се инициализират max=chislo; // с първата въведена стойност while(chislo!=0) { if(max<chislo) max=chislo; if(min>chislo) min=chislo; cin>>chislo; } cout<<"Min="<<min<<endl; cout<<"Max="<<max<<endl; return 0; }
- Намиране на сумата и произведението на редица от числа
За намиране сума на n на брой числа се използва следният алгоритъм:
- Декларира се променлива sum, в която ще се натрупва сумата.
- Променливата sum се инициализира с нула.
- Въвежда се поредното число и стойността му се добавя към тази на sum.
- Стъпка 3 се извършва n пъти, колкото е броят на числата.
- Извежда се стойността на променливата sum, която е натрупаната сума.
Този алгоритъм може да се използва и за намиране на произведението на числа. Променливата, в която ще се натрупва произведението, трябва да се инициализира с 1. Защо?
Задача 8: Да се състави програма, която въвежда от клавиатурата естествено число n и след него n на брой реални числа. Да се изведе сумата и произведението им.
За решението на задачата е удобно да се декларират три променливи с имена sum, pr и chislo. Първата служи за натрупване на сумата, а втората – за натрупване на произведението на числата. Променливата chislo служи за въвеждане на числата от редицата. Променливата sum се инициализира със стойност нула, а променливата pr – със стойност 1.
Примерен вход: 4 Примерен изход: Sum=16.7
1.2 Pr=26.5
-3
15
-0.5
Решение:
#include<iostream.h> int main() { double sum,pr,chislo; sum=0; //Инициализиране на променивата за сума pr=1; //Инициализиране на променивата за произведение int n; cin>>n; for(int i=1;i<=n;i++) { cin>>chislo; sum=sum+chislo;//Натрупване на сумата pr=pr*chislo;//Натрупване на произведението } cout<<"Sum="<<sum<<endl; cout<<"Pr="<<pr<<endl; return 0; }
6. Оператор break
Задача 9: Да се напише програма, която въвежда от клавиатурата реално число k и след него n на брой реални числа. Ако числото k се среща сред въведените след него n числа, на екрана да изведе съобщение “да”, в противен случай – “не”.
Тъй като броят на повторенията е известен предварително, е удобно да се използва операторът за цикъл for. При реализацията на алгоритъма в момента, в който се въведе число, равно на търсеното число k, цикълът може да се прекъсне, защото продължаването му става излишно. В такъв случай се използва операторът за прекъсване на цикъл – break.
Оператор break прекратява изпълнението на оператор за цикъл, който го съдържа.
За решението на задачата ще използваме допълнителна променлива, наречена флаг. Такава променлива (flag) се използва често в програмирането. Тя служи да маркира промяната на някакво условие, като променя своята стойност от 0 на 1 и обратно.
Решение:
#include<iostream.h> int main() { int k; cin>>k; int n,flag=0; double chislo; for(int i=1;i<=n;i++) { cin>>chislo; if(chislo==k) { flag=1; /*Ако числото е равно на въведеното flag присвоява стойност 1*/ break; //Прекъсва изпълнението на цикъла } } if(flag==1)cout<<"да"<<endl; else cout<<"не"<<endl; return 0; }
7. Вложени цикли
В тялото на един оператор за цикъл може да се съдържа друг оператор за цикъл. В този случай казваме, че имаме вложени цикли. Единият цикъл наричаме външен, а другия – вътрешен. При вложените циклични оператори трябва да се спазват следните правила:
- Управляващите променливи на двата цикъла са различни и не трябва да се актуализират едновременно.
- Вътрешният цикъл трябва да се съдържа изцяло в тялото на външния цикъл.
- От тялото на вътрешен цикъл управлението може да се предаде на оператор от тялото на външния цикъл, но обратното не е възможно.
- Външният и вътрешният цикъл могат да са както от един и същи вид, така и от различни видове.
- Променливите, декларирани в тялото на вътрешния цикъл, не се “виждат” извън него. Те могат да се ползват само в този цикъл.
Задачa 10: Да се напише програма, която въвежда от клавиатурата естествени числа, по-големи или равни на 3, като въвеждането продължава до въвеждане на числото нула. Програмата трябва да изведе броя на простите числа измежду въведените.
Примерен вход: 4 11 13 12 0
Примерен изход: Брой прости числа:2
В решението на задачата се използват три променливи – chislo, br и flag. В chislo се записва всяко поредно число. Променливата br се ползва за брояч – в началото има стойност нула, а при всяко намиране на просто число се увеличава с единица (br++). Променливата flag служи за маркиране на намерените прости числа.
Решението е реализирано с два вложени цикъла – във външния (do…while) се въвеждат числата, а във вътрешния (for) се проверява дали текущото число е просто.
Решение:
#include<iostream.h> int main() { unsigned int chislo,br=0,flag; do { flag=1; cin>>chislo; //Следва проверка дали числото е просто for(int i=2;i<=chislo/2;i++) if(chislo%i==0) { flag=0; break; /*При първото срещане на делител прекъсва цикъла for и променя стойността на флага.*/ } //Ако флагът не се е променил, значи числото е просто if(flag==1) br++; }while (chislo!=0); cout<<"Брой прости числа:"<<br<<endl; return 0; }