C++ Ders5 - Donguler
-
Upload
semsettin-karakus -
Category
Documents
-
view
218 -
download
0
description
Transcript of C++ Ders5 - Donguler
Döngüler(while–for)
Seçimden Tekrara Geçiş� if önermesi ve if/else önermesi bir kod bloğunu belli bir koşula bağlı
olarak seçmemizi sağlarcout << "Lütfen negatif olmayan bir sayı giriniz: " << endl;cin >> sayı; if (sayı < 0){
cout << sayı << " negatif. Yanlış girildi!" << endl;}
� Bu yukarıdaki kod eğer girilen ilk sayı negatif ise yeni bir sayı daha girmenizi isteyemez.
------------------------------------------------------------------------------------------------------
� Öte yandan aşağıdaki while döngüsü koşul doğru (true) olduğu sürece altındaki kod bloğunu sürekli olarak çalıştırırcout << " Lütfen negatif olmayan bir sayı giriniz: " << endl;cin >> sayı; while (sayı < 0){
cout << sayı << " negatif! Tekrar deneyiniz." << endl;cin >> sayı;
}
while döngüsünün anlamı
if (koşul) while (koşul){ {önerme listesi; önerme listesi;
} }
koşul
önerme listesi
sonraki önerme
true
false
koşul
önerme listesi
sonraki önerme
true
false
Toplam Örneği: neden döngüler?� 10 positif sayının toplamını bulmak istiyoruz
� Şu şekilde yazabiliriz:
int sayı1, sayı2, sayı3, sayı4, sayı5;
int toplam;
cin >> sayı1 >> sayı2 >> sayı3 >> sayı4 >> sayı5;
toplam = sayı1 + sayı2 + sayı3 + sayı4 + sayı5;
cin >> sayı1 >> sayı2 >> sayı3 >> sayı4 >> sayı5;
toplam += sayı1 + sayı2 + sayı3 + sayı4 + sayı5;
Toplam Örneği
� Ya toplamını hesaplamak istediğimiz� 100 sayı olsaydı?
� Belirsiz sayıda sayı olsaydı?
� Đhtiyacımız olan şey istediğimiz kadar sayıda değer okuyup onların toplamını hesaplamak aslında.
� Bunu yapmak döngülerle mümkün
� Güzel çözüm döngü kullanmak olacaktır.� Kodu sıfırdan yaz. sum10nums.cpp
� Bu tür döngülere sayan (counting) döngüler diyoruz� Đterasyon sayısı biliniyor
Basit bir başka örnek
� 1 ile 10 arasındaki tamsayıların toplamını hesaplamak
int toplam = 0; // bu program parcasıint i = 1; // 1 ıle 10 arasındakıwhile (i <= 10) // tamsayıların toplamını{ // hesaplıyor
toplam += i;i += 1;
}
Örneği adım adım gözden geçirme
int toplam = 0;
int i = 1;
while (i <= 10)
{
toplam += i;
i = i + 1;
}
cout << toplam;
i<=10
toplam+=i;i=i+1;
true
cout<<toplam;
false
1i
toplam 0
2
1
Örneği adım adım gözden geçirme
int toplam = 0;
int i = 1;
while (i <= 10)
{
toplam += i;
i = i + 1;
}
cout << toplam;
i<=10
toplam+=i;i=i+1;
true
cout<<toplam;
false
2i
toplam 1
3
3
Örneği adım adım gözden geçirme
int toplam = 0;
int i = 1;
while (i <= 10)
{
toplam += i;
i = i + 1;
}
cout << toplam;
i<=10
toplam+=i;i=i+1;
true
cout<<toplam;
false
3i
toplam 3
4
6
Örneği adım adım gözden geçirme
int toplam = 0;
int i = 1;
while (i <= 10)
{
toplam += i;
i = i + 1;
}
cout << toplam;
i<=10
toplam+=i;i=i+1;
true
cout<<toplam;
false
10i
toplam45
11
55
while döngüsünün sentaksı
<başlangıç durumu>
while (<koşul>)
{
<önerme_1>;
...
<önerme_N>;
<güncelleme>
}
while döngüsü toplam örneği
� 1..10 arasındaki sayıların toplamı
int toplam = 0;
int i = 1;
while (i <= 10)
{
toplam += i;
i = i + 1;
}
cout << toplam;
initialization
önermeler
update
koşul
Döngünün Anatomisi� Döngünün bloğunda ve koşulunda kullanılan değişkenlerin ilk
değerlerini verin (döngüden önce)� Genel bir kural yok. Duruma bağlı olarak ilk değerlerini atayın.
� Döngünün koşulu her döngü tekrarından önce değerlendirilir� Döngünün bloğundaki her bir önermeden sonra değerlendirilmez� Er döngü tekrarından önce koşulun değerlendirmesinde değişkenlerin
o anki değerleri kullanılır
� Döngünün önermeleri döngü koşulunda kullanılan bazıdeğişkenleri mutlaka değiştirmelidir ki döngü eninde sonunda son bulsun� Eğer döngünün koşulu hep true ise, döngü sonsuza girer
� Sonsuz döngülerden sakınmak gerekir
� Döngü tasarımındaki basit kural:� Başlangıç durumu, döngü koşul ve güncelleme kısımları döngünün
yeterli sayıda tekrarlaması için dikkatlice tasarlanmalıdır. Ama döngüne bir az ne de bir fazla tekrarlamamalıdır.
� Maalesef hatasız bir döngü tasarlamak için direk bir yöntem yoktur
for döngüsü sentaksı
for (<başlangıç>; <koşul>; <güncelleme>)
{
<önerme_1>;...< önerme_N>;
}
� Başlangıç, koşul ve güncelleme kısımları birleştirilmiştir
� Sayı sayan ve bir indeksi olan döngüler için idealdir.
for döngüsünün while ile karşılaştırması
<başlangıç>
while (<koşul>)
{
<önerme_1>;
...
<önerme_N>;
<güncelleme>
}
for (<başlangıç>;
<koşul>;
<güncelleme> )
{
<önerme_1>;...<önerme_N>;
}
for döngüsü örneği
• Aynı döngüyü bu kez for ile yazalım: 1..10 arasındaki sayıların toplamı
int toplam = 0;
int i = 1;
while (i <= 10)
{
toplam += i;
i = i + 1;
}
int toplam = 0;
for (int i=1; i <= 10; i=i+1)
{
toplam += i;
}
for döngüsü
� Başlangıç önermeleri� Döngüden önce çalıştırılır
� Koşul ifadesi� boolean ifade� her döngü içine girmeden önce kontrol edilir
� Eğer doğru ise döngü önermeleri çalıştırılır, yanlış ise döngü sonlandırılır
� Güncelleme önermesi� En son önermeden sonra çalıştırılır
� Birden fazla başlangıç durumu önermesi ve güncelleme önermeleri virgül ile ayrılabilirfor(len = s.length(), k=0; k < len; k+=1)
� Başlangıç durumu önermesi ve/veya koşul ve/veyagüncelleme kısımları eksik olabilir� Ama noktalı virgül her zaman orada olmalıdır
Kötü Döngüler1. for (int i = 10; i < 5; i++)
{
cout << "Kaç kez ekrana yazarım?";
}
2. for (int i = 10; i >= 1; i++)
{
cout << "Kaç kez ekrana yazarım?";
}
3. int i = 1;
while (i < 20)
{
cout << "Kaç kez ekrana yazarım?";
}
Bad loops� Never executes
� Never stops (infinite loops)� Example: consider the following modified code from sum10nums� What’s the problem in the loop below? What is missing?
toplam = 0; count = 1;while (count <= 10){
cin >> num;toplam += num;
}
� count never reaches 10, because count is not updated in the loop
Sonsuz Döngüler� Sonsuz döngülerden sakınmalısınız
� Döngünün koşulu hep doğru kalırsa başınıza gelir� Aynı döngü önermeleri tekrarlar durur
� Bazen ekranda birşeyler görürsünüz, bazen görmezsiniz bile� Ctrl-C ile durdurabilirsiniz programınızı
� Ya bir güncelleme önermesini unutmuşşunuzdur� Ya da yanlış yazılan bir koşul ifadesidir
Sonsuz Döngüler� Aşağıdaki kodun problemi nedir?
� Sonsuz döngü var kesin diyemeyiz, girilen sayıya bağlı� örneğin, sayı tek ise, döngü sonsuzdur
cin >> sayı;int basla = 0;while (basla != sayı){
basla += 2;cout << basla << endl;
}
� Nasıl düzeltelim? � Döngüye başlamadan önce sayının çift sayı mı tek sayı mı
olduğunu kontrol edebiliriz.if (sayı % 2 == 0){ while (basla != sayı)
{ basla += 2;cout << basla << endl;
}}
Diğer Problemler
� Easy to iterate one more or one less times
� Test each loop with the inputs that cause:� zero iterations of the loop body
� one iteration of the loop body
� maximum number of iterations
� one less than the maximum number of iterations
� Use the debugger and watch the variables.
Matematiksel Döngüler� Şimdi matematiksel bazı uygulamalar yapacağız
� Faktoriyel hesaplaması
� Asal sayı bulunması
Factoriyel
� n! = 1x2x…xn is “n factoriyel”;matematikte, istatistikte kullanılır
long factorial(long n)// pre: 0 <= n// post: returns n! (1 x 2 x … x n)
� Toplam hesabına benziyor, ama bu sefer döngüde çarpımı hesaplayacağız. En sonundaki çarpımıdöndüreceğiz. � Döngü n kere çalıştırılacak, sırasıyla 1, 2, …, n çarpılır� Diyelim ki product diye bir sonuç tutalım, product n! diye
bitecek döngünün sonunda. En sonunda da bu sonuç olarak döndürülür.
Factorial
long Factorial(int num)// precondition: num >= 0// postcondition returns num! (1 x 2 x … x num){
long product = 1;int count = 0;while (count < num) {
count += 1;product *= count;
}return product;
}
� Issues� Why did we use long? What happens if we use int instead?� What happens if we initialize count to 1?
� Let’s see fact.cpp
Asal Sayılar� 1 asal değildir, 2 is prime, 3 is prime, 5 is prime, 17 is prime, … 137,
193?� We do not need to check even numbers other than 2 (2 is a special case)� To check 193, divide it by 3, 5, 7, 9, 11, 13
� Note that 14x14 = 196, so 13 largest potential factor?� We will use modulus operator to check divisibility
� We’ll check odd numbers as potential divisors� Watch out for 2, it is a special case� How far should we go to check potential divisors?
� up to and including sqrt(number) + 1
� If there was a bigger factor, a smaller factor would exist. And this smaller one must have been checked before. So we do not need to go beyond this limit.
� +1 is there to make sure that there will be no problems with precision
� See primes.cpp for code
Primeness Check – Details
� Special even number check is added before the loop to eliminate even numbers to be checked in the loop� In order to make the code more efficient
int limit = int(sqrt(n) + 1);
� To assign a double value to an int, a typecast is used, to tell the compiler that the loss of precision is intentional� Make typecasts explicit to tell the compiler you know what you are doing
� Compiler warnings are avoided
� We will see typecast in more detail later
for loop compared with while
<initialization>
while (<test>)
{
<statement1>;
...
<statementN>;
<update>
}
for (<initialization>;
<test>;
<update> )
{
<statement1>;...<statementN>;
}
Example
� Rewrite the while loop of main of primes.cpp using for
k = low;while (k <= high){
if (IsPrime(k)){
cout << k << endl;numPrimes += 1;
}k += 1;
}
for (k = low; k <= high; k += 1){
if (IsPrime(k)){
cout << k << endl;numPrimes += 1;
}}
Shorthand for increment/decrement
� Lots of code requires incrementing a variable by one� Three methods, using = and +, using +=, and using ++
� effectively they are same
num = num + 1;num += 1;num++; // post increment
� It is also possible to write ++num;� pre-increment
� These differ on when the increment is performed, but this difference doesn’t matter when used as an abbreviation for the statement n += 1; in a single statement
� Similarly there are post-decrement (and pre-decrement)num = num - 1; num -= 1; num--;
The do-while loop� Similar to while loop, but the test is after the execution of the loop body� The while loop may never execute, do-while loop executes at least once
<initialization>
do
{
<statement1>;...<statementN>;
<update>
} while (<condition>);
� Example: Prompt for a number between 0 and 100, loop until such a number is entered (user should enter at least one number)
do{
cout << "enter number in range [0..100] ";cin >> num;
} while (num < 0 || num > 100 );
Don’t forget
Priming� Priming: reading an initial value before the loop
� do not get confused with prime numbers; this is something else
� Problem: enter numbers, add them up, stop when -1 entered
int toplam = 0;int num;cin >> num; // prime the loopwhile (num != -1){ toplam += num;
cin >> num;} cout << "total = " << toplam << end;
� Code duplication exists here: input (and perhaps prompt) code isrepeated before the loop and in the loop
Pseudo infinite solution using break
� To avoid repeating code, include it in the body of the loop only, use a test to break out of the loop� break statement exits (inner-most) loop
� I don’t prefer this kind of loops (I’d prefer code duplication)� Because the loop condition is not clear, hence prevents readability
� Try not to use break in this course� Save it for later when you develop really complicated loops
int toplam = 0;int num;while (true) // seemingly infinite loop{ cin >> num;
if (num == -1){ break; // get out of loop}toplam += num;
} cout << "total = " << toplam << end;
Fence Post Problem
� The problem that occurs when one or more operations of the loop body are executed one less then the others.
� Example: Display integers between 1 and 10 separated by comma
1,2,3,4,5,6,7,8,9,10� no comma after 10; no comma before 1.
for (n=1; n <= 10; n++)
{ cout << n << ",";
} Problem: comma after 10
for (n=1; n < 10; n++)
{ cout << n << ",";
}
cout << n; No problem, but code duplicates
� Think of other solutions! (see page 175 of Tapestry)
Downward-counting loop
� Calculate n to the power of m: nm=nxnx…xn
� Example: 25=2x2x2x2x2=32
int power = 1;
int n, m;
cin >> n >> m;
for (int i = m; i <= 1; i--)
{
power = power * n;
}
Nested loops
� Sometimes one loop occurs in another� Generating 2-dimensional tabular data
� multiplication table
� Sorting vectors (which will be studied much later)
� Display some geometric figures using character * (or any other character)� display rectangles, triangles
� Although other loops can be nested as well, most of the time, for loops are used in nested manner
Nested loops - Example� Write a function to display a rectangle of stars (height and width are
parameters)� e.g. if height is 4 and width is 7, the output should look like
****************************
for (i=1; i<= height; i++){
for (j=1; j<=width; j++) // inner loop prints 1 line of stars{
cout << "*";}cout << endl; // end of line is put to the end of each line
}
� See drawfigures.cpp for the complete function and its use in main
Nested loops - Example� Write a function to display a perpendicular isosceles triangle of stars
(perpendicular side length is parameter)� e.g. if side length is 6 , the output should look like
*********************
for (i=1; i <= side; i++){
for (j=1; j<=i; j++) // inner loop prints 1 line of stars{
cout << "*";}cout << endl; // end of line is put to the end of each line
}
� See drawfigures.cpp for the complete function and its use in main
Same loop: downward-counting
for (i=1; i <= side; i++)
{
for (j=1; j<=i; j++)
{
cout << "*";
}
cout << endl;
}
for (i=1; i <= side; i++)
{
for (j=i; j>=1; j--)
{
cout << "*";
}
cout << endl;
}
Drawfigures – Other Considerations� What about having a function to display a line of stars (number
of stars is a parameter)� useful for both rectangle and triangle
void PrintLine (int numstars)// pre: numstars > 0// post: displays numstars stars in one line{
int i;for (i=1; i<= numstars; i++){ cout << "*";}cout << endl; // end of line is put to the end of the line
}
� in rectangle function, inner loop is replaced by a function callfor (i=1; i<=height ; i++){
PrintLine(width);}
� use of PrintLine in triangle function is similar
Example – Multiplication Table� On ith line print, i*1, i*2, i*3, ... , i*i
� Total number of lines is an input. Display lines starting with 1.� See multiply.cpp
#include <iostream>#include <iomanip> // for setwusing namespace std;
int main(){
int i,k,numlines;const int WIDTH = 4;
cin >> numlines;
for (i=1; i <= numlines; i++){
for (k=1; k <= i; k++){
cout << setw(WIDTH) << i*k;}cout << endl;
}return 0;
}
Constants� Sometimes very useful
� provides self documentation� re-use the same value across the program� avoid accidental value changes
� like variables, but their value is assigned at declaration and can never change afterwards� declared by using const before the type name (any type is OK)const double PI = 3.14159;
const string thisclass = "CS201"
const int WIDTH = 4;
� later you can use their valuecout << (PI * 4 * 4);
� but cannot change their valuePI = 3.14; causes a syntax error
Formatting Output� We use stream manipulator setw to specify the total number of
spaces that the next output will use� setw(field length)
� written in cout and affects only the next output value
not the whole cout line
� output is displayed using field length spaces in right justified manner (any empty space is on the left)
� defined in header file <iomanip>, so you have to have #include <iomanip>
� Examplecout << setw(9) << "cs201";
� output shown is four blanks and cs201