İçeriğe geç

Menü

Berk Akademi
Yorumlar Google yorumları Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

C# "Input string was not in a correct format." Hatası Nasıl Çözülür?

csharp-input-string-was-not-in-a-correct-format-hatasi
Bu yazıda neler var?
  1. Bu hata mesajı tam olarak ne söylüyor?
  2. Parse ile TryParse arasındaki fark nedir?
  3. Hatanın kaynağını nasıl ayırt edersin? Teşhis tablosu
  4. Ondalık sayıda virgül mü nokta mı: kültür ayarı hatayı nasıl etkiler?
  5. OverflowException ve ArgumentNullException: FormatException'dan farkları
  6. TryParse, try-catch ve doğrulama döngüsü: hangisini seçmeli?
  7. Hatayı çözdükten sonra seviyeni nasıl ölçersin?
  8. Sık Sorulan Sorular

C# "Input string was not in a correct format." hatası, System.FormatException istisnasından gelir. Elindeki metin, dönüştürmek istediğin veri tipinin beklediği biçime uymaz; örneğin int.Parse("abc") bu hatayı verir. Kullanıcıdan gelen girdiyi doğrudan Parse etmek yerine önce TryParse ile doğrulaman gerekir. Aşağıda hatanın nereden geldiğini bulmayı, TryParse ile try-catch arasındaki farkı ve girdiyi güvenli okumayı adım adım göreceksin.

Bu hata mesajı tam olarak ne söylüyor?

Mesaj şunu söyler: "Bu metni istediğin sayıya çeviremedim, çünkü içeriği o sayı türünün beklediği biçimde değil." Hata, int.Parse gibi bir metin dönüştürme metodunun fırlattığı System.FormatException istisnasıdır. Metodlar metni okurken rakam dışında bir karakterle, boş bir metinle ya da türün kabul etmediği bir yapıyla karşılaşınca bu istisnayı verir. Kullandığın .NET çalışma zamanına göre mesajın sözcükleri biraz değişebilir; bazı sürümler hatalı metni de mesaja ekler. İstisna türü aynı kalır.

Hatayı üreten en yalın örnek, konsoldan okunan metni doğrudan int.Parse'a vermektir:

Console.Write("Yaşını gir: ");
string metin = Console.ReadLine();
int yas = int.Parse(metin);
Console.WriteLine($"Gelecek yıl {yas + 1} yaşında olacaksın.");

Kullanıcı abc yazıp Enter'a basarsa program şuna benzer bir çıktıyla durur:

Unhandled exception. System.FormatException: Input string was not in a correct format.
   ...
   at System.Int32.Parse(String s)
   at Program.Main() in Program.cs:line 3

Yığın izindeki ara satırlar sürüme göre değişir. Senin bakacağın yer, kendi dosya adını ve satır numarasını içeren ilk satırdır. Yukarıdaki örnekte bu line 3'tür ve Parse çağrısının bulunduğu satırı gösterir. Üstündeki Parse satırları .NET'in kendi kodudur. Hatayı orada değil, senin Parse'a verdiğin metinde aramalısın.

Çözümün ilk adımı metni dönüştürmeden önce kontrol etmektir. Bunun için int.TryParse kullanılır; ayrıntısı bir sonraki bölümde.

Parse ile TryParse arasındaki fark nedir?

Parse ile TryParse arasındaki fark nedir?

Parse dönüşüm başarısız olursa istisna fırlatır. TryParse ise bool değer döner ve dönüştürülen sonucu out parametresiyle verir. Aynı iki girdiyi TryParse ile deneyelim:

foreach (string girdi in new[] { "42", "4x2" })
{
    if (int.TryParse(girdi, out int sayi))
        Console.WriteLine($"{girdi} -> başarılı: {sayi}");
    else
        Console.WriteLine($"{girdi} -> başarısız (sayi = {sayi})");
}

Beklenen çıktı:

42 -> başarılı: 42
4x2 -> başarısız (sayi = 0)

Aynı "4x2" metnini int.Parse'a verseydin program bu satırda FormatException ile dururdu. double.Parse ve double.TryParse çifti de aynı mantıkla çalışır.

Burada dikkat edilecek bir ayrıntı var: dönüşüm başarısız olduğunda out değişkenine sayısal türlerde 0 atanır. Bu yüzden sonucun 0 olup olmadığına bakarak başarıyı anlayamazsın, çünkü kullanıcı gerçekten "0" yazmış olabilir. Başarıyı yalnızca dönen bool belirler.

TryParse, dönüşüm başarısız olduğunda programın istisna ile durması yerine sonucu kontrollü biçimde değerlendirmeyi sağlar. Başarısızlığı bir else dalında ele alıp kullanıcıya "Lütfen bir sayı gir" diyebilir, soruyu yeniden sorabilirsin.

Ama Parse kötü bir seçenek değildir. Girdi senin kontrolündeki bir kaynaktan geliyorsa ve biçimi kesinse (örneğin kendi yazdığın sabit bir metin ya da biçimi garanti edilmiş bir dosya), Parse kullanabilirsin. Bu durumda hata, girdinin bozulduğuna dair bir uyarı olarak da işe yarar. Kullanıcıdan gelen serbest girdide ise TryParse daha uygun bir başlangıçtır.

Hatanın kaynağını nasıl ayırt edersin? Teşhis tablosu

Aynı hata mesajının arkasında birkaç farklı neden olabilir. Aşağıdaki tablo, sık karşılaşılan girdileri varsayılan int.Parse davranışına göre karşılaştırır:

Girdi örneğiOlası nedenÇözüm
"" (boş metin)Kullanıcı bir şey yazmadan Enter'a bastı; çevrilecek rakam yok, FormatException fırlar.TryParse ile kontrol et, kullanıcıya soruyu yeniden sor.
"abc", "12a"Rakam dışı karakter var.TryParse kullan, geçersiz girişte anlaşılır bir mesaj göster.
" 42 "Baştaki ve sondaki boşluklar int.Parse tarafından varsayılan olarak kabul edilir. Hata alıyorsan metinde görünmeyen başka bir karakter olabilir.Niyeti açık etmek için Trim() uygula, ham girdiyi köşeli parantezle yazdırıp kontrol et.
"4 2"Rakamların arasındaki boşluk kabul edilmez.Kullanıcıdan düzeltmesini iste ya da boşlukları kaldırıp yeniden dene.
"3,5" ya da "3.5" (double için)Ondalık ayırıcı, çalışan kültüre göre değişir; sonuç hata ya da beklenmedik bir değer olabilir.Kültürü açıkça belirt. Ayrıntısı bir sonraki bölümde.
"3.5" (int için)int ondalık kısım taşımaz; bu metin tam sayı biçiminde değildir.Hedef türü double ya da decimal yap, gerekirse sonra yuvarla.
"1,000"Varsayılan int.Parse binlik ayırıcıyı kabul etmez.NumberStyles.AllowThousands ile kültür belirt ya da ayırıcıyı temizle.

Tabloyu dört eksende özetleyebilirsin: değişken türü (ondalıklı metni int'e çevirmek), boş metin (kullanıcı hiçbir şey yazmadı), ondalık ayırıcı (virgül ya da nokta kültüre uymadı) ve kullanıcı girdisi (harf, ara boşluk, binlik ayırıcı). Hata aldığında bu dördünü sırayla elemek çoğu durumda nedeni bulmaya yeter.

Küçük bir kontrol listesi:

  1. Parse'a girmeden hemen önce ham girdiyi köşeli parantezle yazdır: Console.WriteLine($"[{metin}]");. Köşeli parantezler boşlukları ve boş metni görünür kılar.
  2. Metnin boş olup olmadığına bak.
  3. Hedef türün metindeki değeri taşıyıp taşıyamayacağını düşün (ondalıklı değer ve int gibi).
  4. Ondalıklı sayı varsa programın hangi kültürde çalıştığını ve girdinin hangi ayırıcıyla yazıldığını kontrol et.
  5. Düzelttikten sonra aynı girdiyi TryParse ile dene ve dönen bool değerine bak.

Ondalık sayıda virgül mü nokta mı: kültür ayarı hatayı nasıl etkiler?

int.Parse, double.Parse ve TryParse yöntemleri, kültür belirtmediğinde bilgisayarın geçerli kültürünü (CurrentCulture) kullanır. tr-TR kültüründe ondalık ayırıcı virgüldür, InvariantCulture'da ise noktadır. Bu yüzden aynı "3,5" metni bir bilgisayarda sayıya dönüşürken başka bir bilgisayarda FormatException üretebilir.

Bir de gizli tuzak var: tek parametreli double.TryParse aşırı yüklemesi binlik ayırıcıya da izin verir. Türkçe kültürde nokta binlik ayırıcı sayıldığından "3.5" hata vermeyip sessizce 35 olarak okunabilir. Ayırıcıları kendin belirlemek için NumberStyles ve IFormatProvider alan aşırı yüklemeyi kullan:

using System;
using System.Globalization;

class Program
{
    static void Main()
    {
        string[] metinler = { "3.5", "3,5" };
        double a;
        double b;

        foreach (string m in metinler)
        {
            bool invariant = double.TryParse(m, NumberStyles.Float,
                CultureInfo.InvariantCulture, out a);
            bool turkce = double.TryParse(m, NumberStyles.Float,
                new CultureInfo("tr-TR"), out b);

            Console.WriteLine(m + " -> Invariant: " + invariant + ", tr-TR: " + turkce);
        }
    }
}

Beklenen çıktı:

3.5 -> Invariant: True, tr-TR: False
3,5 -> Invariant: False, tr-TR: True

Hangi kültürü seçeceğin verinin nereden geldiğine bağlıdır:

  • Kullanıcının kendi ülkesinin biçimiyle yazdığı girdi: yerel kültürü kullan. Türkiye'deki kullanıcı virgülle yazar.
  • Dosya, API ya da sabit biçimli veri: InvariantCulture kullan. Böylece program hangi bilgisayarda çalışırsa çalışsın aynı metni aynı şekilde okur.

OverflowException ve ArgumentNullException: FormatException'dan farkları

OverflowException ve ArgumentNullException: FormatException'dan farkları

int.Parse üç ayrı durumda üç ayrı istisna fırlatır. Metnin biçimi sayıya uymuyorsa FormatException, biçim doğru ama değer int aralığına (en çok 2147483647) sığmıyorsa OverflowException, metin null ise ArgumentNullException oluşur.

using System;

class Program
{
    static void Main()
    {
        string[] girdiler = { "abc", "99999999999", null };

        foreach (string g in girdiler)
        {
            try
            {
                int.Parse(g);
            }
            catch (FormatException)
            {
                Console.WriteLine("FormatException");
            }
            catch (OverflowException)
            {
                Console.WriteLine("OverflowException");
            }
            catch (ArgumentNullException)
            {
                Console.WriteLine("ArgumentNullException");
            }
        }
    }
}

Beklenen çıktı sırasıyla FormatException, OverflowException ve ArgumentNullException olur.

Console.ReadLine, girdi akışı kapandığında null döndürebilir; örneğin girdi yönlendirilmiş bir dosyadan okunurken ya da konsolda akış sonu verildiğinde. int.Parse bu değeri alırsa istisna fırlatır. TryParse ise null için false döndürür, yani program çökmez. Başka sık karşılaşılan C# hata mesajlarının çözümlerine Berk Akademi blogundaki yazılardan bakabilirsin.

TryParse, try-catch ve doğrulama döngüsü: hangisini seçmeli?

Üç yaklaşım birbirinin rakibi değil, farklı durumlara uyan araçlardır.

  • TryParse: Hatalı girdinin sık ve beklenen olduğu yerlerde uygundur. TryParse, dönüşüm başarısız olduğunda programın istisna ile durması yerine sonucu kontrollü biçimde değerlendirmeyi sağlar. İstisna fırlatmaz, yalnızca false döndürür.
  • try-catch: Parse'ı sarmalamak, biçim hatasını taşmadan ayrı ele almak istediğinde ya da kodun başka yerlerinde zaten istisna yönetimi kurulduğunda anlamlıdır. Sık tekrarlanan hatalı girdide istisna fırlatıp yakalamak, normal bir false dönüşünden daha ağırdır.
  • Doğrulama döngüsü: Geçerli değer gelene kadar kullanıcıya yeniden sormak için kullanılır. Döngü genellikle TryParse ile birlikte çalışır; ikisi birbirinin alternatifi değildir.

Aşağıdaki program yaşı int, notu double olarak okur:

using System;
using System.Globalization;

class Program
{
    static bool YasOku(out int yas)
    {
        while (true)
        {
            Console.Write("Yaş: ");
            string girdi = Console.ReadLine();
            if (girdi == null) { yas = 0; return false; }
            if (int.TryParse(girdi, out yas) && yas >= 0) return true;
            Console.WriteLine("Geçersiz giriş, tam sayı gir.");
        }
    }

    static bool PuanOku(out double puan)
    {
        while (true)
        {
            Console.Write("Not (nokta ile): ");
            string girdi = Console.ReadLine();
            if (girdi == null) { puan = 0; return false; }
            if (double.TryParse(girdi, NumberStyles.Float,
                CultureInfo.InvariantCulture, out puan)) return true;
            Console.WriteLine("Geçersiz giriş, örnek: 3.5");
        }
    }

    static void Main()
    {
        int yas;
        double puan;
        if (!YasOku(out yas) || !PuanOku(out puan))
        {
            Console.WriteLine("Girdi akışı kapandı.");
            return;
        }
        Console.WriteLine("Yaşın: " + yas);
        Console.WriteLine("Notun: " + puan.ToString(CultureInfo.InvariantCulture));
    }
}

Girdi ve ekrandaki sonuç:

  • Yaş sorusunda 25 → kabul edilir, sonda Yaşın: 25 yazılır.
  • Yaş sorusunda abc → "Geçersiz giriş, tam sayı gir." yazılır ve soru tekrarlanır.
  • Yaş sorusunda boş Enter → ReadLine boş metin döndürür, TryParse false verir; aynı uyarı çıkar.
  • Yaş sorusunda 30 → baştaki ve sondaki boşluklar varsayılan tam sayı stilinde kabul edilir, Yaşın: 30 yazılır.
  • Yaş sorusunda 3.5 → int ondalık kabul etmez, uyarı çıkar.
  • Not sorusunda 3.5 → kabul edilir, Notun: 3.5 yazılır.
  • Not sorusunda 3,5 → InvariantCulture ve NumberStyles.Float ile virgül geçersizdir, uyarı çıkar.

Hatayı çözdükten sonra seviyeni nasıl ölçersin?

Bu hatayı çözmek, girdi doğrulama, tür dönüşümü ve istisna kavramlarını birlikte kullandığın anlamına gelir. Bir sonraki adım bu kavramları kendi küçük programlarında denemektir. Konsoldan sayı okuyan bir program yaz, sonra ona bilerek abc, boş satır, ondalıklı bir sayı ve çok büyük bir değer gir. Her seferinde istisnanın türünü ve mesajını oku. Hata mesajını okumayı alışkanlık hâline getirmek, bir sonraki hatada seni doğrudan nedene götürür.

Bilgini ölçmek istersen ücretsiz bilgi testleri merkezinde seviye testleri bulabilirsin. C# için yalnızca seviyeni ölçen ücretsiz bir bilgi testi var. Berk Akademi'de C# programı yoktur, bu test bir eğitime yönlendirme amacı taşımaz. Merkezdeki Algoritmik Düşünme Testi ise dilden bağımsızdır. Hangi dille çalışırsan çalış, problemi adımlara bölme becerini görmene yardımcı olur.

Sık Sorulan Sorular

int.Parse ile Convert.ToInt32 arasındaki fark nedir, ikisi de aynı hatayı verir mi?

Metin geçerli bir tamsayı biçiminde değilse ikisi de FormatException fırlatır. Fark, null değerde ortaya çıkar: int.Parse(null) ArgumentNullException fırlatırken Convert.ToInt32(null) string için 0 döndürür. Convert.ToInt32 ayrıca string dışındaki türler için de aşırı yüklemelere sahiptir.

int.TryParse false döndüğünde sonuç değişkeninin değeri ne olur?

Dönüşüm başarısız olduğunda out parametresi 0 değerini alır. Bu yüzden 0'ı geçerli bir girdi sayıyorsan değişkenin değerine bakmak yetmez, metodun döndürdüğü true ya da false sonucunu kontrol etmelisin.

Console.ReadLine null döndürebilir mi, bu durumda sayı dönüşümü ne olur?

Evet. Giriş akışı sona erdiğinde, örneğin girdi yönlendirilmiş bir dosyadan okunurken ya da konsolda dosya sonu işareti verildiğinde, Console.ReadLine null döndürür. Bu değeri int.Parse'a verirsen ArgumentNullException alırsın. int.TryParse ise hata fırlatmaz, false döndürür ve sonuç değişkeni 0 olur.

Bu hatayla karşılaştığında önce mesajı, sonra istisna türünü oku; çözüm çoğunlukla bu ikisinin içinde saklıdır.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara