Bütün Bir Satırı Okumak
cin >> text tek bir kelime okur: ilk boşlukta durur. Kullanıcının Enter tuşuna kadar yazdığı her şeyi, boşluklar dahil, okumak için <string> başlığındaki std::getline'ı kullan:
#include <iostream>
#include <string>
int main() {
std::string name;
std::cout << "Full name: ";
std::getline(std::cin, name);
std::cout << "Hello, " << name << "!\n";
}
Ada Lovelace yazmak Hello, Ada Lovelace! yazdırır. std::cin >> name ile Hello, Ada! yazdırır ve Lovelace girdide beklemeye devam ederdi.
İmzası şöyledir:
std::istream& std::getline(std::istream& input, std::string& text);
std::istream& std::getline(std::istream& input, std::string& text, char delim);
inputherhangi bir girdi stream'idir:std::cin,std::ifstreamile açılmış bir dosya ya da bir string'den oluşturulmuş birstd::istringstream.text, okunan karakterlerle değiştirilir (sonuna eklenmez).delim, okumayı bitiren karakterdir. Varsayılanı'\n''dir. Ayırıcı stream'den çıkarılır vetextiçinde saklanmaz.- Dönüş değeri stream'in kendisidir; onu bir koşulda test edebilmeni sağlayan da budur.
getline her girdi stream'inde aynı şekilde çalıştığı için bu sayfadaki çalıştırılabilir örnekler sabit metin tutan bir std::istringstream'den okur. Böylece hiçbir şey yazmadan çıktı tahmin edilebilir olur. Bunun yerine klavyeden okumak için stream değişkeninin yerine std::cin koy.
Çıktı:
[Ada Lovelace]
[Alan Turing]
Köşeli parantezler, satır sonunun iki string'in de parçası olmadığını gösteriyor.
cin >> Sonrasında getline Boş String Döndürür
En yaygın getline sorunu budur. >> ile bir sayı, ardından getline ile bir satır okursun ve getline atlanmış gibi görünür:
Çıktı:
age: 30
city: []
input >> age, 30 karakterlerini okur ve bir sayının parçası olamayan ilk karakterde, yani satır sonunda durur. O satır sonu stream'de kalır. Ardından getline bir sonraki satır sonuna kadar okur, hemen bir tane bulur ve boş bir string döndürür. std::cin ile bunun sonucu, programın ikinci cevap için hiç durmamasıdır.
İki standart çözüm var. İkisi de >> ile getline arasına yazılır.
Çözüm 1: satırın geri kalanını ignore ile at.
Çıktı:
age: 30
city: [Paris]
ignore(n, '\n'), bir satır sonunu çıkarana ya da n karakter atana kadar (hangisi önce gelirse) karakterleri atar. Mümkün olan en büyük std::streamsize değerini vermek "ne kadar uzakta olursa olsun, satır sonuna kadar" anlamına gelir. Kullanıcının aynı satırda sayıdan sonra yazdığı her şeyi, örneğin sondaki boşlukları da çıkarır. Klavye için satır std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); olur ve #include <limits> gerektirir.
Argümansız bir std::cin.ignore() tam olarak bir karakter atar. Satır sonu sayının hemen ardından geliyorsa çalışır, öncesinde bir boşluk olduğu anda başarısız olur.
Çözüm 2: baştaki boşlukları std::ws ile atla.
Çıktı:
age: 30
city: [Paris]
std::ws, geçerli konumdaki tüm boşluk karakterlerini (boşluklar, sekmeler, satır sonları) tüketen bir manipülatördür. input >> std::ws stream'i döndürür, bu yüzden doğrudan getline'a verilebilir. Boş satırları ve baştaki boşlukları da atlar; bu, isimler ve şehirler için kullanışlıdır ama baştaki boşluklar ya da boş bir satır anlamlı bir girdiyse yanlıştır. O durumda ignore kullan.
Girdinin Sonuna Kadar Okumak
getline stream'i döndürür ve bir okuma başarısız olduğunda stream false'a dönüşür. Okunacak satır kalmadığında getline başarısız olur; bu yüzden etrafına kurulan bir while döngüsü her satırı okur ve sonda durur:
Çıktı:
1: [apples 3]
2: [bread 1]
3: []
4: [milk 2]
read 4 lines
Bu çıktıdan iki ayrıntı:
- Boş bir satır da başarılı bir okumadır. Boş bir string verir ve döngü devam eder. Döngüyü yalnızca girdinin sonuna ulaşmak durdurur.
- Son satırın sonunda satır sonu olması gerekmez. Metin
milk 2ile bitseydi ve\nolmasaydı,getlineonu yine döndürür, bir sonraki çağrı ise başarısız olurdu.
std::cin ile aynı döngü girdi bitene kadar okur. Bu, girdi bir dosyadan yönlendirildiğinde (./program < data.txt) ya da kullanıcı macOS ve Linux'ta Ctrl+D, Windows'ta Ctrl+Z ardından Enter'a bastığında olur.
while (!input.eof()) { std::getline(input, line); ... } kalıbından kaçın. eof() ancak bir okuma sona çarptıktan sonra doğru olur, bu yüzden gövde başarısız bir okuma ve eskimiş bir line ile bir kez fazladan çalışır. Bunun yerine getline çağrısını koşulun içine koy.
Bir Dosyayı Satır Satır Okumak
Dosyalar aynı döngüyü kullanır. Dosyayı <fstream>'deki std::ifstream ile aç, açıldığını kontrol et ve oku:
Çıktı:
1. Ada 92
2. Grace 88
3. Alan 95
if (!file), eksik bir dosyayı ya da yanlış bir yolu döngüden önce yakalar. O olmadan döngü sıfır satır okur ve bu bir hata değil, boş bir dosya gibi görünür. file main'in sonunda kapsam dışına çıktığında dosya otomatik olarak kapanır.
Windows'ta kaydedilen dosyalar her satırı \r\n ile bitirir. Böyle bir dosya Linux ya da macOS'ta okunduğunda getline \n'yi çıkarır ama \r'yi bırakır; böylece her satır, line == "done" gibi karşılaştırmaları bozan görünmez bir satır başı karakteriyle biter. Okuduktan sonra onu temizle:
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
Özel Bir Ayırıcı Kullanmak
Üçüncü argüman, her okumayı bitiren karakteri değiştirir. Yaygın bir kullanım, tek bir satırı virgüllerden bölmektir. Önce satırı oku, sonra bir std::istringstream üzerinden böl:
Çıktı:
fields: 3
[Ada Lovelace]
[36]
[London]
Varsayılan biçimdeki satır sonu gibi virgül de stream'den çıkarılır ve saklanmaz. Özel bir ayırıcıyla satır sonunun sıradan bir karakter olduğuna dikkat et. std::getline(file, field, ',')'ı çok satırlı bir dosyada doğrudan çağırırsan, bir satırın son alanı ile sonraki satırın ilk alanı "London\nGrace Hopper" gibi birleşik gelir. Her seferinde bir satır okuyup her satırı ayrı ayrı bölmek bunu önler. std::istringstream'i, "36" gibi alanları sayıya dönüştürmek de dahil olmak üzere daha ayrıntılı olarak string stream'ler sayfası anlatıyor.
std::getline ve cin.getline
Benzer adlı bir üye fonksiyon da var:
char buffer[20];
std::cin.getline(buffer, 20); // üye fonksiyon, sabit boyutlu char dizisi
std::string text;
std::getline(std::cin, text); // serbest fonksiyon, std::string
cin.getline bir char dizisine yazar ve en fazla size - 1 karakter ile sonlandırıcı '\0''ı saklar. Daha uzun bir satır stream'i başarısız duruma sokar ve std::cin.clear() çağırana kadar sonraki her okuma atlanır. std::string ile std::getline'da yönetilecek bir uzunluk sınırı yoktur. char dizisi isteyen bir API ile çalışmıyorsan onu kullan.
Sık Yapılan Hatalar
- Satır sonunu temizlemeden
>>ilegetline'ı karıştırmak. Aralarınaignore(...)ekle ya dastd::wskullan. Aynı sorunustd::cinile ve sayısal bir okuma başarısız olduğunda nasıl toparlanacağını girdi ve çıktı sayfası gösteriyor. getline(std::cin, number)'ı birintile çağırmak.getlineyalnızca birstd::string'e okur. Satırı oku, sonrastd::stoiya da birstd::istringstreamile dönüştür.eof()üzerinde döngü kurmak.getlineçağrısının kendisini test et:while (std::getline(input, line)).#include <string>'i unutmak. String'ler içinstd::getline<string>içinde bildirilir. Bazı derleyiciler<iostream>üzerinden gözden kaçmasına izin verir ve kod başka bir derleyicide başarısız olur.- Bir dosyanın açıldığını kontrol etmemek. Yanlış bir yol
std::ifstream'in sessizce başarısız olmasına ve okuma döngüsünün sıfır kez çalışmasına yol açar.
Sıkça Sorulan Sorular
C++'ta getline ne yapar?
std::getline(stream, text), stream'den karakterleri bir satır sonuna ulaşana kadar text adlı std::string'e okur, ardından bu satır sonunu saklamadan stream'den çıkarır. cin >> text'in aksine boşlukları korur, bu yüzden tam bir ad ya da bir cümle gibi bütün bir satırı okur.
C++'ta cin >> sonrasında getline neden atlanıyor?
cin >> number, sayıdan sonra yazdığın satır sonunda okumayı bırakır ve o satır sonunu girdi tamponunda bırakır. Sonraki getline onu hemen bulur ve boş bir string döndürür. Önce onu std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); ile at ya da baştaki boşlukları atlamak için std::getline(std::cin >> std::ws, text) çağır.
getline'ı satır sonu dışında bir ayırıcıyla nasıl kullanırım?
Ayırıcıyı üçüncü argüman olarak ver: std::getline(stream, field, ','). Bir sonraki virgüle kadar okur, virgülden önceki metni saklar ve virgülü atar. Bu durumda satır sonları sıradan karakter sayılır, bu yüzden genellikle tek bir satırdan oluşturulan bir std::stringstream ile birlikte kullanılır.
C++'ta bir dosyayı satır satır nasıl okurum?
Dosyayı std::ifstream file("data.txt"); ile aç ve while (std::getline(file, line)) { ... } ile döngü kur. getline stream'i döndürür; okunacak satır kalmadığında stream false'a dönüşür, böylece döngü dosyanın sonunda durur.
cin.getline ile getline arasındaki fark nedir?
std::getline(std::cin, text), her uzunluktaki satıra göre büyüyen bir std::string'e okuyan serbest bir fonksiyondur. std::cin.getline(buffer, size) ise sabit boyutlu bir char dizisine okuyan bir üye fonksiyondur ve satır size - 1 karakterden uzunsa başarısız olur. Ham dizi kullanmak için bir nedenin yoksa std::string ile std::getline kullan.