Looping and Counting

Kategori: C++ , 10 Kasım 2019 , JanFranco


Bir önceki konumuzda kullanıcıdan bir girdi alıp, bu girdiyi yıldız karakterleri ile birlikte konsola yazdırmıştık. Her bir satırı ayrı ayrı tanımlayarak bu problemi çözmüştük. Bu konumuzda ise bu probleme daha esnek bir biçimde yaklaşacağız. Önceki yazımızdaki kodu tekrar ele alalım:


#include <iostream>
#include <string>

int main()
{
    // ask for the person's name
    std::cout << "Please enter your first name: ";

    // read the name
    std::string name;
    std::cin >> name;

    // build the message that we intend to write
    const std::string greeting = "Hello, " + name + "!";
    // we have to rewrite this part...

    return 0;
}
Kullanıcıdan girdiyi aldık ve bir karşılama mesajı oluşturduk. Bu işlemden sonrasını tekrar düzenleyeceğiz. İlk olarak kaç satır olacağını belirleyelim. Karşılama mesajı bir satır kullanıyor. Mesajın etrafında dikdörtgen oluşturacak şekilde yıldız karakterleri döşenecek. Dikdörtgenin başı ve sonu olacak ve bu kısımlar da iki satır kullanacak. Yani minimum 3 satır olacak. Mesaj satırı ile dikdörtegenin başı ve sonu arasında birer satır olacak. Bu satırın sayısını tanımlayalım. Bu değeri iki ile çarpıp (iki boşluk satır) 3 eklersek esnek bir biçimde dikdörtgeni tanımlamış oluruz:


const int pad = 1;
const int rows = pad * 2 + 3;
pad değişkeninin artırarak daha büyük bir dikdörtgeni rahatlıkla oluşturabileceğiz. Satır sayısını bu şekilde belirledik. Bir sonraki adımımız, daha esnek bir yapı olması adına, satırları tek tek bastırmak yerine bir döngü açmak olacaktır:


int r = 0;

while (r != rows) {
    ++r;
}
while döngüsü bu şekilde oluşturulur. while anahtar kelimesinden sonra bir condition belirleyerek, her adımda yapılacak işlemleri süslü paranterzler arasına alırız. Yukarıdaki satırlar bize şunu söylüyor, r değişkeni rows değişkenine eşit olana kadar r değerini bir artır. while döngüsünün çalışabilmesi için conditionın değeri true olmalı. Zıt olarak bu değer false olursa while döngüsü çalışmaz. Her bir adımda yapılan ++r işlemi aşağıdaki işlem ile aynıdır:


r = r + 1;
C dillerinde bir değişkeninin değerini bir azaltmak veya bir artırmak için kısaca ++ veya -- operatörlerini kullanabiliriz. Satır sayısını tanımlamıştık şimdi de sütun sayısını tanımlayalım:


const std::string::size_type cols = greeting.size() + pad * 2 + 2;
greeting bizim karşılama mesajımız. greeting.size() diyerek bu mesajın uzunluğunu aldık. Bu değere iki ile çarptığımız pad değerini ve 2 değerini ekledik. Sütun sayısını sonradan değiştirmeyeceğimiz için const olarak tanımladık. Ancak cols sabitinin tipini daha önce görmemiştik. std::string diyerek string sınıfının std namespace'e ait olduğunu söyleyebiliriz. string::size_type da aynı şekilde size_type sınıfı string sınıfına dahil demektir. Peki neden int olarak tanımlamadık? rows değişkeninin değerini bizim belirlediğimiz pad değeri ile oluşturduk. Ancak sütun sayısı kullanıcının girdiği isim değişkenine bağlı. Kullanıcı çok uzun bir girdi gönderebiliriz. Bu nedenle size_type tipi burada daha güvenlidir. Şimdi sütunlar için de bir döngü açalım:


std::string::size_type c = 0;

while (c != cols) {
    if (r == 0 || r == rows - 1 || c == 0 || c == cols - 1) {
	std::cout << "*";
    } else {

    }
}
Sütun döngüsünde if - else statementları ile bir koşul belirledik. Eğer r değeri 0 ise veya r değeri rows - 1 değerine eşit ise veya c değeri 0 ise veya c değeri cols - 1 değerine eşit ise yıldız karakteri bas demiş olduk. Eğer bu koşullardan herhangi biri sağlanmasa else bloğundaki kodlar çalışacak. If bloğunu tek başına da kullanabilirdik fakat burada problem gereği if - else bloklarını kullandık. Operatörlerden bahsetmek gerekirse, == operatörü eşitliği != operatörü eşit olmamayı temsil eder. || operatörü ise mantık operatörüdür, veya kelimesini temsil eder. Bu dört koşuldan herhangi biri true değerinde olduğunda if bloğundaki kodlar çalışacaktır. && operatörü ve kelimesini temsil eder. Burada veya yerine ve kullansaydık, bu dört koşulun tamamı true olursa if bloğu çalışacaktı. Bu bilgilerimizle problemi artık çözebiliriz fakat iki konu daha göreceğiz. Döngülerden bahsediyorsak for döngüsünden mutlaka bahsetmeliyiz:


for (init-statement condition; expression)
    statement
for döngüsü ile while döngüsü birbirine oldukça benzemekte ve aynı işi yapmakta. Hatta bu ikiyi döngüyü birbiri cinsinden yazabiliriz. Aşağıdaki while döngüsünü for döngüsü cinsinden yazalım:


r = 0;
while (r != rows) {
    ++r;
}

for (int r = 0; r != rows; ++r) {

}
Görüldüğü gibi kontrol değişkenini while döngüsünden önce tanımlıyoruz. Her bir adımda koşul kontrol ediliyor ve r değeri bir artıyor. For döngüsünde ise bu kontrol değişkenini ve bu kontrol değişkenine ne olacağını, koşulla birlikte aynı satırda yazıyoruz. Son olarak her seferinde std:: şeklinde namespace belirtmek zorunda değiliz. using ifadesi ile bir değişkenin std namespace'ine dahil olduğunu belirtirsek, tekrar tekrar aynı şeyi yazmamıza gerek kalmaz:


using std::cout;
Bu bilgileri kullanarak problemi çözelim:


#include <iostream>
#include <string>

// say what standard-library names we use
using std::cin; using std::endl;
using std::cout; using std::string;

int main()
{
    // ask for the person's name
    cout << "Please enter your first name: ";

    // read the name
    string name;
    cin >> name;

    // build the message that we intend to write
    const string greeting = "Hello, " + name + "!";

    // the number of blanks surrounding the greeting
    const int pad = 1;

    // the number of rows and columns to write
    const int rows = pad * 2 + 3;
    const string::size_type cols = greeting.size() + pad * 2 + 2;

    // write a blank line to separate the output from the input
    cout << endl;

    // write rows rows of output
    for (int r = 0; r != rows; ++r) {
        string::size_type c = 0;
        // invariant: we have written c characters so far in the current row
        while (c != cols) {
            // is it time to write the greeting?
            if (r == pad + 1 && c == pad + 1) {
                cout << greeting;
                c += greeting.size();
            } else {
                // are we on the border?
                if (r == 0 || r == rows - 1 || c == 0 || c == cols - 1)
                    cout << "*";
                else
                    cout << " ";
                ++c;
            }
        }
        cout << endl;
    }
    return 0;
}
Kullanıcıdan girdiyi aldık. Bir karşılama mesajı hazırladık. Satır ve sütun sayılarını belirledik. Bir for döngüsü açtık ve her bir satırda c adında bir değişken oluşturup değerini 0 olarak atadık. For döngüsünün her bir adımında çalışacak bir while döngüsü oluşturduk. Eğer p + 1. satırdaysak ve sütun değeri pad + 1 ise mesajı konsola yazdıracağız ve c değerini mesajın uzunluğu kadar artıracağız. Eğer mesajı bastıracağımız satırda değil isek sınırda olup olmadığımızı kontrol ediyoruz. Eğer sınırdaysak ve mesaj satırı değil ise * karakteri basıyoruz. Eğer sınırda değilsek, mesaj satırında da değilsek boş karakter basıyoruz ve c değerini bir artırıyoruz. Bu problem ile birlikte bir çok yeni konsept gördük. Problemin dışında, C++'da bulunan tüm operatörleri ve anlamlarını görelim:


x.y		x objesinin y elemanı
x[y]		x objesindeki y indisli eleman

x++		x değeri return edilir, bu işlemden sonra x değeri bir artırılır
x--		x değeri return edilir, bu işlemden sonra x değeri bir azaltılır
++x		x değeri bir artırılır, bu işlemden sonra x değeri return edilir
--x		x değeri bir azaltılır, bu işlemden sonra x değeri return edilir

!x		Logical not operasyonu, x true ise bu ifade false, false ise bu ifade true belirtir

x * y		x çarpı y
x / y		x bölü y
x % y		x mod y
x + y		x artı y
x - y		x eksi y

x >> y		x sağ tarafa doğru y kadar bit kaydırılır. Eğer x istream ise x değeri okunur, y üzerine yazılır		
x << y		x sol tarafa doğru y kadar bit kaydırılır. Eğer x ostream ise y, x değerinin üstüne yazılır

x relop y	< > <= >= operatörlerini kapsar, koşul sağlanırsa true, sağlanmazsa false döner

x == y		x, y değerine eşit ise true, değil ise false döner
x != y		x, y değerine eşit değil ise true, false ise true döner

x && y		x ve y aynı anda true ise true, değil ise false döner
x || y		x veya y true ise true, iki değer de false ise false döner

x = y		y değeri x değerine atanır
x op= y		x += 1, x -= 3, x /= 5 gibi işlemler olabilir, örneğin x += 1 ifadesi x = x + 1 ifadesi ile aynı anlama gelir
x ? y1 : y2	x true ise y1 return edilir, false ise y2 return edilir


Sonraki Yazı: Working with Batches of Data
Yorumlar

Henüz bir yorum bulunmuyor.
Yorum bırakın