C# Hesap Makinası Yapımı

Bu makalemde sizlere basit düzeyden ileri düzeye doğru ilerleyen 7 adet hesap makinesi uygulaması geliştireceğim.

Her bir projede C# programlama dilinin temel kavramlarından başlayarak OOP kavramlarına kadar ilerleyeceğiz.

Bu makalede ki amacım C# programlama dilinin tüm seviyelerini (temelden – ileriye doğru) tek bir proje üzerinden sizlere sunabilmek. Umarım beğenirsiniz.

Proje 1-Basit Bir Hesap Makinesi

Kavramlar: Değişkenler – Operatörler

Önceden tanımlı değişkenler üzerinden operatörler yardımıyla gerçekleştirilen dört işlemin (toplama, çıkarma, bölme, çarpma) sonucu kullanıcıya gösterilmektedir.

Proje 2-Basit Bir Hesap MakinesiKarar Yapıları

Kavramlar: Değişkenler – Operatörler – Tip Dönüşümü – IF Else – Switch Case

Kullanıcıdan alınan veriler üzerinden yine kullanıcının seçtiği işleme göre gerçekleştirilen dört işlemin sonucu kullanıcıya gösterilmektedir.

Proje 3-Basit Bir Hesap Makinesi – Döngüler

Kavramlar: Değişkenler – Operatörler – Tip Dönüşümü – IF Else – Switch Case – While – Do While

Bu proje ile birlikte artık tam manasıyla bir hesap makinesi ortaya çıkmaktadır. Kullanıcıdan aldığı veri doğrultusunda işlemi yaptıktan sonra tekrar kullanıcı ile itişime geçerek işleme devam edebilmektedir.

Proje 4-Basit Bir Hesap Makinesi – Diziler

Kavramlar: Değişkenler – Operatörler – Tip Dönüşümü – IF Else – Switch Case – While – Do While – Array

Dizilerinde kullanımına örnek verebilmek için dört işlemin seçeneği (toplama +, çıkarma -, çarpma *, bölme /) dizi olarak tanımlanıp kontrol ve listeleme işlemi yapılmaktadır.

Proje 5-Basit Bir Hesap Makinesi – Metotlar

Kavramlar: Değişkenler – Operatörler – Tip Dönüşümü – IF Else – Switch Case – While – Do While – Array – Methods

Yapılan tüm işlemler akışa uygun olarak yeniden yapılandırılıp parametreli/parametresiz, değer döndüren/döndürmeyen tipte metotlar kullanılarak tekrardan düzenlenmiştir.

Proje 6-Basit Bir Hesap Makinesi – Sınıflar

Kavramlar: Değişkenler – Operatörler – Tip Dönüşümü – IF Else – Switch Case – While – Do While – Array – Methods – Class (Sınıf)

Düzenlediğimiz hesap makinesi uygulaması Nesne Tabanlı Programlama (Object Oriented Programming) kavramlarına uygun sınıf yapısı kazandırılmıştır.

Proje 7-Basit Bir Hesap Makinesi – Refactoring Inheritance

Kavramlar: Değişkenler – Operatörler – Tip Dönüşümü – IF Else – Switch Case – While – Do While – Array – Methods – Class (Sınıf) – Inheritance (Miras Alma) – Refactoring (Kod iyileştirme)

Nesne Tabanlı Programlama (Object Oriented Programming) kavramlarının en önemli yapılarından olan Inheritance (miras alma) özelliğini kullanılarak uygulama yeniden düzenlenmiştir (refactoring)

Proje-1 Basit Bir Hesap Makinesi

Bu projede değişkenler üzerinden tanımladığımız sayıları operatörler yardımıyla gerçekleştirilen dört işlemin sonucu (+ – * /) kullanıcıya Console.Writlene metodu ile sunulmaktadır.

// Uygulama Adını Göster "Simple C# Calculator"
Console.WriteLine("Basit Bir C# Hesap Makinası");
// Değişkenleri Tanımla
double firstNum, secondNum, result;
// İlk Sayıyı Al (10)
firstNum = 10;
// İkinci Sayıyı Al (2)
secondNum = 2;

// Toplama İşlemi Sonucu (12)
result = firstNum + secondNum;
// Toplama İşlemi Sonucunu Göster
Console.WriteLine("Toplamı: {0} + {1} = {2}", firstNum, secondNum, result);

// Fark İşlemi Sonucu (8)
result = firstNum - secondNum;
// Fark İşlemi Sonucunu Göster
Console.WriteLine("Çıkarma: {0} - {1} = {2}", firstNum, secondNum, result);

// Çarpma İşlemi Sonucu (20)
result = firstNum * secondNum;
// Çarpma İşlemi Sonucunu Göster
Console.WriteLine("Çarpımı: {0} * {1} = {2}", firstNum, secondNum, result);

// Bölme İşlemi Sonucu (5)
result = firstNum / secondNum;
// Bölme İşlemi Sonucunu Göster
Console.WriteLine("Bölümü: {0} / {1} = {2}", firstNum, secondNum, result);

Proje 2-Basit Bir Hesap MakinesiKarar Yapıları

Burada kullanıcıdan, Console.Readline ile alınan verilere tip dönüşümü uygulanarak Convert.ToDouble() değişkenlere atanmaktadır. Atama işleminden sonra değişkenler üzerinden operatörler yardımıyla dört işlem uygulanmaktadır. Yalnız kullanıcıda alınan işlem değeri durumuna göre switch yapısı ile kullanıcının yapmak istediği işlemin sonucu yansıltılmaktadır. Ayrıca kullanıcının programdan boşluk ile çıkması için bir If yapısı bulunmaktadır.

// Uygulama Adını Göster
Console.WriteLine("Basit Bir C# Hesap Makinası");
Console.WriteLine("İşlem Seçiniz: [ + | - | * | / ] Çıkış yapmak için boş geçiniz.");

// Değişkenleri Tanımla
double firstNum, secondNum, result = 0;
string mathOp;

// Kullanıcıdan veri al ve Tip Dönüşümü
Console.Write("Sayı 1: ");
firstNum = Convert.ToDouble(Console.ReadLine());

Console.Write("Sayı 2: ");
secondNum = Convert.ToDouble(Console.ReadLine());

Console.Write("İşlem: ");
mathOp = Console.ReadLine();

//Kullanicinın çıkış yapıp yapmadığını kontrol et.
if (mathOp != string.Empty)
{
    // Kullanıcının hangi işlemi girdiğini belirleme
    switch (mathOp)
    {
        // Kullaniciya işleme göre sonucu göster.
        case "+":
            result = firstNum + secondNum;
            Console.WriteLine("Toplamı: {0}", result);
            break;
        case "-":
            result = firstNum - secondNum;
            Console.WriteLine("Çıkarma: {0}", result);
            break;
        case "*":
            result = firstNum * secondNum;
            Console.WriteLine("Çarpımı: {0}", result);
            break;
        case "/":
            result = firstNum / secondNum;
            Console.WriteLine("Bölümü: {0}", result);
            break;
        default:
            break;
    }
}
else
{
    Console.WriteLine("İşlem yapılamadı.");
}

Proje 3-Basit Bir Hesap Makinesi – Döngüler

Proje 2 de yapılan işlemlere ek olarak While döngüsü yardımıyla işlemlere süreklilik kazandırılmıştır. Bu aşamadan sonra programımız tam bir hesap makinesi işleyişine bürünmüştür. Yapılan ilk işlemin sonucu tekrardan kullanıcıya gösterilerek son işlem üzerinden yeni bir hesap yapma özelliği kazandırılmıştır.

// Uygulama Adını Göster
Console.WriteLine("Basit Bir C# Hesap Makinası");
Console.WriteLine("İşlem Seçiniz: [ + | - | * | / ]");

// Değişkenleri Tanımla
double firstNum, secondNum, result = 0;
string mathOp = "+";

// Kullanıcıdan veri al ve Tip Dönüşümü
Console.Write("Sayı 1: ");
firstNum = Convert.ToDouble(Console.ReadLine());

while (mathOp != String.Empty)
{
    try
    {
        // Kullanicidan İşlemi Al
        Console.Write("İşlem: ");
        mathOp = Console.ReadLine();

        // Sayı1 ve İşlemi Yaz
        Console.Write("{0} {1} ", firstNum, mathOp);

        // Kullanıcıdan Sayı 2 al ve Tip Dönüşümü
        secondNum = Convert.ToDouble(Console.ReadLine());
    }
    catch
    {
        Console.WriteLine("İşlem Yapılamadı!");
        mathOp = String.Empty;
        continue;
    }
    // Kullanıcının hangi işlemi girdiğini belirleme
    switch (mathOp)
    {
        case "+":
            result = firstNum + secondNum;
            Console.WriteLine("Toplamı: {0}", result);
            break;
        case "-":
            result = firstNum - secondNum;
            Console.WriteLine("Çıkarma: {0}", result);
            break;
        case "*":
            result = firstNum * secondNum;
            Console.WriteLine("Çarpımı: {0}", result);
            break;
        case "/":
            result = firstNum / secondNum;
            Console.WriteLine("Bölümü: {0}", result);
            break;
        default:
            mathOp = String.Empty;
            continue;
    }
    // Kullaniciya sonucu göster.
    Console.WriteLine(" = {0}", result);

    // İşlemin devamlı olması için tekrar döngüye girmeden önce sonucu firstNum'a atayın
    firstNum = result;
}
Console.WriteLine("Answer: {0}", result);

Proje 4-Basit Bir Hesap Makinesi – Diziler

Proje 3 ek olarak dizi kullanımı amaçlanmıştır. Dört işlem seçeneği dizi üzerinden tutularak bir kontrol mekanizması gerçekleştirilmiştir.

// Uygulama Adını Göster
Console.WriteLine("Basit Bir C# Hesap Makinası");
Console.WriteLine("İşlem Seçiniz: [ + | - | * | / ]");

// Değişkenleri Tanımla
double firstNum, secondNum, result = 0;
string mathOp = "+";
string[] ValidMathOperators = { "+", "-", "*", "/" };

// Kullanıcıdan veri al ve Tip Dönüşümü
Console.Write("Sayı 1: ");
firstNum = Convert.ToDouble(Console.ReadLine());

while (mathOp != String.Empty)
{
    try
    {
        // Kullanicidan İşlemi Al
        Console.Write("İşlem: ");
        mathOp = Console.ReadLine();

        //kullanıcı tarafından girilen matematik operatörünün geçerli olup olmadığını dizi yardımıyla kontrol edin;
        if (!Array.Exists(ValidMathOperators, e => e == mathOp))
        {
            Console.WriteLine("Invalid Math Operator");
            mathOp = String.Empty;
            continue;
        }

        // Sayı1 ve İşlemi Yaz
        Console.Write("{0} {1} ", firstNum, mathOp);

        // Kullanıcıdan Sayı 2 al ve Tip Dönüşümü
        secondNum = Convert.ToDouble(Console.ReadLine());
    }
    catch
    {
        Console.WriteLine("İşlem Yapılamadı!");
        mathOp = String.Empty;
        continue;
    }
    // Kullanıcının hangi işlemi girdiğini belirleme
    switch (mathOp)
    {
        case "+":
            result = firstNum + secondNum;
            Console.WriteLine("Toplamı: {0}", result);
            break;
        case "-":
            result = firstNum - secondNum;
            Console.WriteLine("Çıkarma: {0}", result);
            break;
        case "*":
            result = firstNum * secondNum;
            Console.WriteLine("Çarpımı: {0}", result);
            break;
        case "/":
            result = firstNum / secondNum;
            Console.WriteLine("Bölümü: {0}", result);
            break;
        default:
            mathOp = String.Empty;
            continue;
    }
    // Kullaniciya sonucu göster.
    Console.WriteLine(" = {0}", result);

    // İşlemin devamlı olması için tekrar döngüye girmeden önce sonucu firstNum'a atayın
    firstNum = result;
}
Console.WriteLine("Answer: {0}", result);

Proje 5-Basit Bir Hesap Makinesi – Metotlar

Dört İşlem için yapılan işlemler geriye değer döndüren bir metot haline dönüştürülmüş. Ana işlemi yapan kod bloklarımız ise geriye değer döndürmeyen void metot olarak tanımlanarak programın C#’ın Best Practies kavramların uygun olarak yazılması sağlanmıştır.

// Uygulama Adını Göster
Console.WriteLine("C# Hesap Makinası Programı");
Console.WriteLine("İşlem Seçiniz: [ + | - | * | / ] çıkmak için boşluk tuşuna basınız");

// İşlemi yapan metodu çağır.
Calculate();

//Void belirli bir görevi yapan metot oluştur.
static void Calculate()
{
    // Hesap Makinesi için ihtiyacımız olan değişkenleri bildirin
    double firstNum, secondNum, result = 0;
    string mathOp = "+";
    string[] ValidMathOperators = { "+", "-", "*", "/" };

    // Döngüden önceki ilk sayıyı al
    Console.Write("Sayı 1: ");
    firstNum = Convert.ToDouble(Console.ReadLine());
    while (mathOp != String.Empty)
    {
        try
        {

            // Kullancidan İşlemi Al
            Console.Write("İşlem: ");
            mathOp = Console.ReadLine();

            // kullanıcı tarafından girilen matematik operatörünün geçerli olup olmadığını kontrol edin; değilse döngüden çıkış yapın.

            if (!Array.Exists(ValidMathOperators, e => e == mathOp))
            {
                Console.WriteLine("Geçersiz İşlem");
                mathOp = String.Empty;
                continue;
            }
            // Denklemin ilk kısmını yazdırın.
            Console.Write("{0} {1} ", firstNum, mathOp);

            // Kullanicidan ikinci sayıyı alın
            secondNum = Convert.ToDouble(Console.ReadLine());
        }
        catch
        {
            Console.WriteLine("Hesaplama Gerçekleşmedi!");
            mathOp = String.Empty;
            continue;
        }

        // Hesaplama İşlemi
        switch (mathOp)
        {
            //İşlem tipine göre parametreli metot çağır.
            case "+":
                Console.WriteLine("Toplam: {0}", result = GetSum(firstNum, secondNum));
                break;
            case "-":
                Console.WriteLine("Fark: {0}", result = GetSubtract(firstNum, secondNum));
                break;
            case "*":
                Console.WriteLine("Çarpım: {0}", result = GetMultiple(firstNum, secondNum));
                break;
            case "/":
                Console.WriteLine("Bölüm: {0}", result = GetDivision(firstNum, secondNum));
                break;
            default:
                mathOp = String.Empty;
                continue;
        }
        // Kullaniciya sonucu göster
        Console.WriteLine(" = {0}", result);

        // Tekrar döngüye girmeden önce sonucu firstNum'a atayın
        firstNum = result;
    }
}
//Geri değer döndüren parametreli metot oluştur.
static double GetDivision(double firstNum, double secondNum)
{
    return firstNum / secondNum;
}
static double GetMultiple(double firstNum, double secondNum)
{
    return firstNum * secondNum;
}
static double GetSubtract(double firstNum, double secondNum)
{
    return firstNum - secondNum;
}
static double GetSum(double firstNum, double secondNum)
{
    return firstNum + secondNum;
}

Proje 6-Basit Bir Hesap Makinesi – Sınıflar

Nesne Tabanlı Programlama (OOP) kavramlarına değinmek için calculator adlı sınıf tanımlanarak işlemler sınıf üzerinden gerçekleştirilmiştir. Burada hesap makinemizin iç işleyişini kendi sınıfına soyutlayarak uygulamanın Main Metodunu önemli ölçüde temizledik.

internal class Program
{
    private static void Main(string[] args)
    {
        // Uygulama Adını Göster
        Console.WriteLine("C# Hesap Makinası Programı");
        Console.WriteLine("İşlem Seçiniz: [ + | - | * | / ] çıkmak için boşluk tuşuna basınız");

        //Oluşturduğumuz Sınıfı çağır.
        Calculator calc = new Calculator();
        // Döngüden önceki ilk sayıyı al
        Console.Write("Sayı 1: ");
        calc.SetNumber(Console.ReadLine());
        while (calc.ContinueCalculating)
        {

            // Kullanicidan işlemi alınız.
            Console.Write("[ + | - | * | /  ] : ");
            calc.MathOp = Console.ReadLine();
            // Kullanicidan ikinci sayıyı alınız
            Console.Write("{0} {1} ", calc.FirstNum, calc.MathOp);
            calc.SetNumber(Console.ReadLine());
            if (calc.ContinueCalculating)
            {
                // Sonucu hesaplayın
                calc.Calculate();
                // Sonucu Gösterin
                Console.WriteLine(" = {0}", calc.Result);
            }
        }
        Console.WriteLine("Result: {0}", calc.Result);
    }
}
class Calculator
{
    // Field tanımlayın
    private string[] validMathOperators = { "+", "-", "*", "/" };
    private string prevMathOp, mathOp;
    private bool firstNumber;

    // Properties tanımlayın
    public bool ContinueCalculating { get; private set; }
    public double FirstNum { get; private set; }
    public double SecondNum { get; private set; }
    public double Result { get; private set; }
    public string MathOp
    {
        get { return mathOp; }
        set
        {
            if (Array.Exists(validMathOperators, el => el == value))
            {
                mathOp = value;
            }
            else
            {
                mathOp = prevMathOp;
            }
        }
    }
    // Constructor (Yapıcı Metot) tanımlayın.
    public Calculator()
    {
        // Calculator Nesnesi oluşturulduğunda Propertiesleri ve Değişkenleri Başlat
        prevMathOp = validMathOperators[0];
        firstNumber = true;
        ContinueCalculating = true;
    }
    // public Method tanımlayın
    public void SetNumber(string input)
    {
        double number;
        try
        {
            number = Convert.ToDouble(input);
        }
        catch
        {
            number = 0;
            ContinueCalculating = false;
        }
        if (firstNumber)
        {
            FirstNum = number;
            firstNumber = false;
        }
        else
        {
            SecondNum = number;
        }
    }
    public void Calculate()
    {
        // İşlemleri gerçekleştirin.
        switch (MathOp)
        {
            case "+":
                Result = FirstNum + SecondNum;
                break;
            case "-":
                Result = FirstNum - SecondNum;
                break;
            case "*":
                Result = FirstNum * SecondNum;
                break;
            case "/":
                Result = FirstNum / SecondNum;
                break;
            default:
                break;
        }
        
        //Bir önceki sayıdan hesaplamaya devam ediyoruz...
        FirstNum = Result;

        //Kullanıcı boş bırakırsa, matematik operatörünün varsayılan olarak önceki değerine dönmesini istiyoruz...
        prevMathOp = MathOp;
    }
}

Proje 7-Basit Bir Hesap Makinesi – Refactoring Inheritance

Proje-6’da, Main Method hala çok fazla kod olan tüm görüntüleme ve kullanıcı etkileşimi mantığını içermektedir. Bu nedenle tam olarak C# Best Practies kavramlarına uygun bir hale getirebilmek için yeniden düzenlenerek Inheritance kavramı işlenmiştir.

Yapıtığımız uygulama ile mevcut Calculator sınıfımızla ilgili hiçbir şeyi değiştirmeden yeni bir ConsoleCalculator sınıfı oluşturabiliriz. Şuanda her ne kadar bir Console uygulaması yapsak da projemizi geliştirmek isteyebiliriz. Bu aşamadan sonra kodumuza müdahale etmeden var olan yapı üzerinden projemizi geliştirebiliriz.

Bunu, “Inheritance (miras)” olarak bilinen bir Nesne Yönelimli Programlama (OOP) kavramını kullanarak yapıyoruz.

internal class Program
{
    private static void Main(string[] args)
    {
        ConsoleCalculator calc = new ConsoleCalculator();
        calc.On();
        calc.GetFirstNumber();
        while (calc.ContinueCalculating)
        {
            calc.GetMathOperator();
            calc.GetSecondNumber();
            calc.Calculate();
        }
        calc.Off();
    }
}

//ConsoleCalculator, temel sınıfı olan Calculator'dan miras alır.
class ConsoleCalculator : Calculator
{
    public void On()
    {
        // Uygulama Adını Göster
        Console.WriteLine("C# Hesap Makinası Programı");
        Console.WriteLine("İşlem Seçiniz: [ + | - | * | / ] çıkmak için boşluk tuşuna basınız");
    }
    public void Off()
    {
        Console.WriteLine("Result: {0}", Result);
    }
    public void GetFirstNumber()
    {
        // Döngüden önceki ilk sayıyı al
        Console.Write("Sayı 1: ");
    }
    public void GetMathOperator()
    {
        // Kullanicidan işlemi alınız.
        Console.Write("[ + | - | * | /  ] : ");
        MathOp = Console.ReadLine();
    }
    public void GetSecondNumber()
    {
        // Kullanicidan ikinci sayıyı alınız
        Console.Write("{0} {1} ", FirstNum, MathOp);
        SetNumber(Console.ReadLine());
    }
    public void Calculate()
    {
        if (ContinueCalculating)
        {
            // Sonucu Hesapla
            base.Calculate();
            // Kullaniciya Sonucu Göster
            Console.WriteLine(" = {0}", Result);
        }
    }
}
// --- Calculator Class --- 
// Yeni bir değişiklik yok bir önceki konuyla aynı

class Calculator
{
    // Field tanımlayın
    private string[] validMathOperators = { "+", "-", "*", "/" };
    private string prevMathOp, mathOp;
    private bool firstNumber;

    // Properties tanımlayın
    public bool ContinueCalculating { get; private set; }
    public double FirstNum { get; private set; }
    public double SecondNum { get; private set; }
    public double Result { get; private set; }
    public string MathOp
    {
        get { return mathOp; }
        set
        {
            if (Array.Exists(validMathOperators, el => el == value))
            {
                mathOp = value;
            }
            else
            {
                mathOp = prevMathOp;
            }
        }
    }
    // Constructor (Yapıcı Metot) tanımlayın.
    public Calculator()
    {
        // Calculator Nesnesi oluşturulduğunda Propertiesleri ve Değişkenleri Başlat
        prevMathOp = validMathOperators[0];
        firstNumber = true;
        ContinueCalculating = true;
    }
    // public Method tanımlayın
    public void SetNumber(string input)
    {
        double number;
        try
        {
            number = Convert.ToDouble(input);
        }
        catch
        {
            number = 0;
            ContinueCalculating = false;
        }
        if (firstNumber)
        {
            FirstNum = number;
            firstNumber = false;
        }
        else
        {
            SecondNum = number;
        }
    }
    public void Calculate()
    {
        // İşlemleri gerçekleştirin.
        switch (MathOp)
        {
            case "+":
                Result = FirstNum + SecondNum;
                break;
            case "-":
                Result = FirstNum - SecondNum;
                break;
            case "*":
                Result = FirstNum * SecondNum;
                break;
            case "/":
                Result = FirstNum / SecondNum;
                break;
            default:
                break;
        }

        //Bir önceki sayıdan hesaplamaya devam ediyoruz...
        FirstNum = Result;

        //Kullanıcı boş bırakırsa, matematik operatörünün varsayılan olarak önceki değerine dönmesini istiyoruz...
        prevMathOp = MathOp;
    }
}

Tebrikler. Bu uygulama ile C# programlama eğitiminden bir çok şeyi ele aldık. Kullanıcı girişiyle nasıl başa çıkacağımızı, bilgisayar hesaplamalarından nasıl yararlanacağımızı, karar yapılarını, döngüleri, dizileri ve method, class, inheritance gibi nesne tabanlı programlama (oop) konularının işledik.

En önemlisi, temel bir hesap makinesi programını alıp yavaş yavaş üzerine inşa etmeyi öğrendik, ta ki uygulamamızın üzerinde çalışabileceği temiz görünümlü (Best Practies) bir kod alanı oluşturana kadar.

Amacım C# programlama dilini tüm seviyelerini tek bir örnek üzerinden gerçekleştirebilmekti umarım başarılı olmuşumdur. İyi çalışmalar…

Proje Dosyası

C# Hesap Makinası Uygulamasının proje kodlarına aşağıda githup adresi üzerinden erişebilirsiniz.

C# Hesap Makinası Konsol Uygulaması

https://github.com/alkanfatih/CalculatorAppLowerToUpper