Geçtiğimiz günlerde C++ öğrenmeye başladım. Akışkanlar mekaniğinden uçuş mekaniğine, bölümümdeki birçok alanda fayda sağlayacak bir dil olduğunu ve kullandığımız birçok mühendislik programının C++ kullanılarak programlandığını öğrendim. Ayrıca hazır programları kullanmayı öğrenmeyi hep sığ ve sıkıcı bulduğumdan belki kendi programlarımı veya eklentilerimi geliştiririm diye düşündüm ve Udemy’de güzel bir C++ kursu bulup takip etmeye başladım.

C++, C dilinde C değişkeninin değerini bir arttır demek. Esasında C++, C dilinin nesne tabanlı programlama (Object Oriented Programming/OOP) özelliği eklenmiş hali ki o bir arttırma bunu temsil ediyor. Günümüzde popüler olan çoğu dil (Java, Python…) programcıya bu imkanı sunuyor ama C eski bir dil olduğundan bu özelliğe sahip değil. Bu özellik nesne ve sınıflar tanımlayarak programlama yapmanıza izin veriyor. Örneğin en başta C dilinde dinamik diziler yok, dizilerin boyutunu tanımladıktan sonra değiştiremiyorsunuz. C++ tipi dizilere vektör deniyor ve istediğiniz gibi dizi boyutlarını değiştirebiliyorsunuz, çünkü C++ vektörleri aslında nesne olarak tanımlanıyor. Aynı şey karakter dizileri (string) için de geçerli. C dilinde stringler tam manasıyla karakter dizileri ve boyutları sabit, kısıtlı imkanlara sahipler. C++ stringleri ise dinamik boyuta ve birçok uygulama imkanına sahipler ve aynı şekilde nesne olarak tanımlanıyorlar.

C++ hem C tipi stringleri ve dizileri hem de C++ tipi stringleri ve dizileri kullanma imkanı sunuyor, nesneye yönelik programlamanın gücüne sahip. Ayrıca C dilinin en büyük güçlerinden olan işaretçilere (pointer) de sahip. En sevdiğim dil C iken eksikleri kapatılmış bir C bulmak oldukça mutluluk verici.

Aldığım kursta stringler veya karakter dizileri konusunu bitirdiğimde sadece video izleyerek bir yere varamayacağımı biliyordum ve alıştırma olması için bir kod yazmaya karar verdim. Zaten kriptolojiye biraz ilgim vardı ve bu yüzden basit bir kriptoloji programı yazmaya karar verdim. Yapılacak en güzel program, bir ROT-13 şifreleme ve çözme programı yapmaktı.

ROT-13 (Rotate by 13 Places) algoritması temelde mesajdaki harflerin Latin alfabesinde kendisinden 13 karakter sonraki harfle yer değiştirmesiyle elde ediliyor. Bu tarz şifreli mesajlara “Cipher Message” deniyor ve bunların ilk kez Roma imparatoru Julius Ceasar tarafından kullanıldığı düşünülüyor. Bu kaydırma istediğiniz bir sayı kadar olabilir, buna göre algoritmanın ismi de ROT-8, ROT-12 şeklinde değişecektir. En yaygın olanın ROT-13 olma sebebi ise ROT-13 algoritmasının ayrıca kendi tersi olması. İngiliz alfabesinde 26 harf var ve 13 ileri gitmek 13 geri gitmekle aynı, o yüzden ROT-13 şifrelemesiyle çözmesi esasında aynı işlem.

ROT-13 programımı tamamladıktan sonra bunun basit olduğuna karar verdim ve bir adım öteye gitmeye karar verdim. Program sadece 13 karakter değil, herhangi sayıda karakter ileri gidebilmeli, şifreleme ve çözme işlemlerini yapabilmeliydi. Bu sayıyı ve şifreleme mi, çözme mi yapılacağını kullanıcıya sorup ona göre işlem yapmalıydı. Ben de kodumu bunun üzerine modifiye ettim ve bu özelliği ekledim.

Programımın nasıl çalıştığını detaylıca anlatıyorum:

İlk olarak konsola yazdırmamı ve konsoldan okumamı sağlayan fonksiyonları barındıran iostream kütüphanesini koda dahil ediyorum ve çokça kullanacağım std sınıfını varsayılan olarak ayarlıyorum. Böylelikle cout ve cin fonksiyonlarını kullanacağım zaman her defasında std::cout ve std::cin yazmak zorunda kalmayacağım. Normalde bu önerilmeyen bir şey olsa da amacım karakter dizilerine çalışmak olduğundan ve programım küçük olduğundan böyle kullandım.

Daha sonra her kodda bulunması gereken main fonksiyonunu açıyorum. Kullanıcıdan iki veri alıp gerekli değişkenlere atıyorum: Alfabede kaç harf gidilmek istendiği ve şifreleme mi çözme mi seçeneği. Kodun ilerisindeki kısımlarında bu değişkenler lazım olacak. Ayrıca henüz o konuyu öğrenmediğimden hatalı giriş kontrolü (Exception handling) özelliği koymadım.

Burada cin fonksiyonunun buffer’a ‘\n’ karakteri koyduğunu öğrendim. Yani cin fonksiyonundan sonra getline() fonksiyonunu kullanacaksanız (kodun devamında var) cin fonksiyonundan sonra cin.get() ifadesini kullanmalısınız. Aksi takdirde getline() fonksiyonu hiçbir şey yapmadan Enter tuşuna basılmış gibi boş olarak geçiyor.

Burada kullanıcının girdiği mesajı getline() fonksiyonu ile alıyorum. Burada başta cin kullanmıştım, ama denemelerimde cin fonksiyonunun ilk boşluktan sonraki karakterleri almadığını fark ettim, yani kelimeler ayrı yazıldığında sadece ilk kelimeyi alıyordu. Bu yüzden getline() kullandım. Getline() Enter tuşuna basılana kadarki her karakteri alıyor. Onda da az önce bahsettiğim sorunla karşılaştım: Fonksiyon sanki bir şey yazılmadan Enter’a basılmış gibi geçiyordu ve önceki cin fonksiyonlarından sonra kullandığım cin.get() ifadesiyle bu sorunu çözdüm.

Burada öncelikle sonradan gelecek for döngüsü için i değişkenini size_t olarak tanımladım. Daha önce bir iki kere integer olarak tanımladığımda sıkıntı yaşadığımdan size_t olarak tanımlamak uygun geldi.

Kodun en kilit kısmı bence sonraki iki satır ve bunu fark etmem kodun çok daha kısa sürmesini sağladı. Şöyle ki başta kullanıcı şifre çözme isterse (yani choice değişkeni 2 olursa) alfabede geriye gitmeye çalışmıştım ve bunun için iki tane for döngüsü gerekecekti: Biri şifreleme için karakterleri ileri götüren, diğeri çözme için karakterleri geri götüren. Başta böyle deneyip başarısız oldum ve çalışsa da kodun oldukça verimsiz olduğunun farkındaydım. Başka çözüm yolu aramaya başladım ve şunu fark ettim: Alfabede örneğin 10 geri gitmekle 16 ileri gitmek aynı şeydi. Yani çözmek için n geri gitmekle şifreleme için 26-n ileri gitmek aynı şey. Başka bir ifadeyle ROT-n encryption = ROT-(26-n) decryption. Ben de geri gitmek yerine geri gidilecek sayıyı 26’dan çıkardım ve çözüm işleminde de o sayı kadar ileri gittim, tek for döngüsüyle işi halletmiş oldum. For döngüsü de şu şekilde:

Burada iterasyon değişkeni i’ye üst sınır olarak girilen dizinin uzunluğu atanıyor. Bu şekilde dizideki tüm karakterlere işlem yapılmış olacak.

Karakterleri ileri götürmek için karakterlerin ASCII tablosundaki değerlerine girilen n sayısı kadar ekleme yolunu kullandım. ‘a’ karakterinin ASCII değeri 97 ve ‘z’ karakterinin ASCII değeri 122. İlk if, eğer küçük karakterlerden başka bir karakter girilirse hiçbir şey yapma diyor. Bunu özellikle boşluk karakteri için düşündüm. Ayrıca bu kodumun sadece küçük harf kabul ettiğini gösteriyor. Eğer toplam sonucu elde edilen değer 122’yi aşarsa, aşan miktar 97’ye ekleniyor, yani alfabenin başından sayılıyor. Aşma yoksa n normal şekilde ekleniyor. Modifiye edilen karakter aynı yere yazılıyor.

Burada değiştirilen mesaj ekrana yazdırılıyor ve kod normal şekilde bitiriliyor.

Bu kod benim için oldukça öğretici oldu ve string fonksiyonlarını kullanmayı öğrendim. Ne kadar kullanımını derslerde görsem de bizzat uygulamaya girince başka sorunlar ortaya çıkıyor ve programlamayı öğrenmek için en iyi yol programlamak. İlerde yazacağım diğer programları da paylaşmayı düşünüyorum.

Programı şu linkte görüntüleyip indirebilirsiniz: https://drive.google.com/file/d/1DoLdl9hwCg2Ooe5JIGuTWnGMP-mF3vME/view?usp=sharing

Aldığım kursun linki: https://www.udemy.com/course/beginning-c-plus-plus-programming/

Çalıştırmak isterseniz çevrimiçi derleyiciler mevcut. Kodu şu sitedeki yere kopyalayıp yapıştırıp kullanabilirsiniz: http://cpp.sh/