C++ Konsolla Nasıl Konuşur
C++, konsol G/Ç'sini <iostream> başlığındaki stream'ler aracılığıyla yapar. Dünyaya cout (karakter çıktısı) ile yazar, kullanıcıdan cin (karakter girdisi) ile okursun. Daha önce bit kaydırma olarak gördüğün, burada yeniden amaçlandırılmış iki operatör kullanırlar:
<<ekleme operatörüdür; veriyicout'un içine gönderir.>>çıkarma operatörüdür; veriyicin'in içinden bir değişkene çeker.
Yönü hatırlamanın kolay bir yolu: oklar verinin aktığı yöne işaret eder. Artık metni string'lerde tutabildiğine göre, bu metni programının içine ve dışına taşıyalım.
cout ile Yazdırmak
cout, eklediğin her şeyi standart çıktıya gönderir. Tek bir ifadede birden fazla << zincirleyebilir; metni, sayıları ve değişkenleri serbestçe karıştırabilirsin.
Her <<, bir satır sonu ekleyene kadar aynı satıra eklenir. Bunu yapmanın iki yolu var: '\n' bir satır sonu karakteri ekler, endl ise bir satır sonu ekler ve tamponu ekrana boşaltır. Boşaltmanın gerçek bir maliyeti vardır, bu yüzden binlerce satır yazdıran bir döngünün içinde '\n''yi tercih et; stream gerektiğinde kendi kendine boşalır (ve her zaman program çıkışında).
// Tek seferlik bir mesaj için sorun yok:
cout << "Done" << endl;
// Yoğun bir döngüde bunu tercih et - her yinelemede zorla boşaltma yok:
for (int i = 0; i < 1000000; ++i)
cout << i << '\n';
cin ve >> ile Okumak
cin >> variable, boşlukla ayrılmış bir token okur ve onu değişkenin türüne dönüştürür. Baştaki boşlukları veya satır sonlarını atlar, sonra bir sonraki boşlukta durur.
>> boşlukta durduğu için tekil sayılar ve tek kelimeler için harikadır, ama tam bir cümle için işe yaramaz: hello world girdisiyle cin >> word yalnızca hello'yu okur ve world'ü bir sonraki okuma için tamponda bırakır.
getline ile Tam Satır Okumak
Bütün bir satırı —boşluklarıyla birlikte— yakalamak için, Enter tuşuna kadar olan her şeyi bir std::string'e okuyan getline(cin, line)'ı kullan.
Girdi boşluk içerebildiğinde —isimler, adresler, cümleler— doğru araç budur. Sadece, getline'ı >> ile karıştırdığın anda seni bekleyen tek bir tuzak var.
cin + getline Satır Sonu Tuzağı
Bu, C++'taki en yaygın G/Ç hatasıdır. cin >> n yaptığında, çıkarma işlemi sayıyı okur ama satır sonunu (bastığın Enter tuşunu) girdi tamponunda bırakır. Sonraki getline bu artakalan satır sonunu hemen görür, satırı zaten bitmiş sayar ve sana bir boş string verir — girdi için hiç durmadan.
int age;
string city;
cin >> age; // 30 yazıp Enter'a basarsın; '\n' tamponda kalır
getline(cin, city); // artakalan '\n'i okur -> city "" olur (boş!)
Çözüm, bu artakalan satır sonunu >>'den sonra ve getline'dan önce cin.ignore ile atmaktır:
cin.ignore(numeric_limits<streamsize>::max(), '\n') bir satır sonu yiyene (ya da girdinin sonuna gelene) kadar karakterleri atlar. Sağlam sürüm budur; daha kısa olan cin.ignore() yalnızca tek bir karakteri atar ve kullanıcı sayıdan sonra fazladan boşluk yazdıysa bozulur. Alışkanlık olarak tam biçimi kullan.
Girdi Başarısız Olduğunda
Kullanıcı sayı beklediğin yere harf yazarsa, çıkarma işlemi başarısız olur: cin bir hata durumuna geçer ve hedef değişken değişmeden kalır (C++11'den beri 0'a ayarlanır). Daha kötüsü, cin bir kez başarısız duruma düştüğünde sonraki her okuma da sessizce atlanır, böylece sonsuz bir döngüye girebilirsin.
Toparlanma her zaman iki adımdır: cin.clear() hata bayraklarını sıfırlar, böylece stream yeniden kullanılabilir hale gelir, ve cin.ignore(...) hâlâ tamponda takılı kalan sorunlu karakterleri atar. ignore'u atlarsan hatalı girdi yerinde kalır, yani sonraki >> yine başarısız olur — klasik sonsuz döngü. cin >> n'i doğrudan koşulda kontrol etmek işe yarar, çünkü stream başarısız durumdayken false'a dönüşür.
Kaçınılması Gereken Yaygın Hatalar
- Bir cümle için
cin >> skullanmak. İlk boşlukta durur. Boşluk içeren her şey içingetlinekullan. >>ilegetlinearasındacin.ignore'u unutmak. Artakalan satır sonu sana boş bir satır verir. Önce tamponu temizle.- Her yerde
endl'ye sarılmak. Her biri bir boşaltmayı zorlar. Varsayılan olarak'\n'kullan veendl'yi gerçekten çıktının şimdi görünmesi gereken durumlara sakla. - Başarısız bir
cin'i görmezden gelmek. Sayısal bir okumadaki harflercin'i bozar; yeniden okumadan önce her zamanclear()sonraignore()yap.
Sonraki: String Stream'ler
Konsol G/Ç'si ve string işleme string stream'lerde bir araya gelir. Bir stringstream sana aynı << ve >> operatörlerini verir, ama konsola değil bellekteki bir string'e yöneliktir — bir satırı sayılara ayrıştırmak, biçimlendirilmiş metin oluşturmak ve klavyeye hiç dokunmadan string'lerle diğer türler arasında dönüşüm yapmak için mükemmeldir.
Sıkça Sorulan Sorular
C++'ta cin kullandıktan hemen sonra getline neden girdiyi atlıyor?
cin >> x sayıyı okur ama bastığın satır sonunu tamponda bırakır. Sonraki getline bu artakalan satır sonuna kadar okur ve hemen boş bir string döndürür. >>'den sonra ve getline'dan önce cin.ignore(numeric_limits<streamsize>::max(), '\n'); ile önce onu temizle.
C++'ta endl ile \n arasındaki fark nedir?
İkisi de satırı bitirir, ama endl ayrıca çıktı tamponunu ekrana boşaltır (flush), '\n' ise sadece bir satır sonu ekler. Boşaltmanın bir maliyeti vardır; sıkı bir döngüde '\n''yi tercih et ve stream'in kendi kendine boşalmasına izin ver. endl'yi yalnızca çıktının gerçekten şu an görünmesi gerektiğinde kullan.
C++'ta boşluklar dahil bütün bir metin satırını nasıl okurum?
cin >> line değil, getline(cin, line) kullan. >> operatörü ilk boşlukta durur, yani sadece tek bir kelime alır. getline Enter tuşuna kadar olan her şeyi, boşluklar dahil, bir std::string'e okur.