Neden kullanıyoruz:
1) cin.ignore
2) cin.clear
?
Basitçe:
1) Akışta istemediğimiz değerleri yok saymak (ayıklamak ve atmak)
2) Akışın dahili durumunu temizlemek için. Cin.clear kullanıldıktan sonra dahili durumu tekrar iyi bit'e ayarlanır, bu da 'hata' olmadığı anlamına gelir.
Uzun versiyon:
Bir şey 'akış'a (cin) konursa, o zaman oradan alınmalıdır. "Alınan" derken "kullanılmış", "kaldırılmış", "çıkarılmış" diyoruz. Akışın bir akışı var. Veriler, akıştaki su gibi cin üzerinde akıyor. Su akışını durduramazsınız;)
Örneğe bakınız:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
Kullanıcı ilk soru için "Arkadiusz Wlodarczyk" yanıtını verirse ne olur?
Kendiniz görmek için programı çalıştırın.
Konsolda "Arkadiusz" göreceksiniz, ancak program sizden "yaş" ı sormayacaktır. "Arkadiusz" yazdırıldıktan hemen sonra bitecek.
Ve "Wlodarczyk" gösterilmiyor. Sanki gitmiş gibi görünüyor (?) *
Ne oldu? ;-)
Çünkü "Arkadiusz" ile "Wlodarczyk" arasında bir boşluk var.
İsim ve soyisim arasındaki "boşluk" karakteri, "giriş" akışında çıkarılmayı bekleyen iki değişken olduğunun bilgisayar için bir işaretidir.
Bilgisayar, birden fazla değişkeni girdiye göndermeye çalıştığınızı düşünüyor. Bu "boşluk" işareti, onu bu şekilde yorumlaması için bir işarettir.
Böylece bilgisayar "Arkadiusz" u "isim" (2) 'ye atar ve akışa (giriş) birden fazla dizge koyduğunuz için, bilgisayar "Wlodarczyk" değerini "age" (!) Değişkenine atamaya çalışır. Kullanıcının 6. satırdaki 'cin'e herhangi bir şey koyma şansı olmayacak çünkü bu talimat zaten yürütülmüştür (!). Neden? Çünkü akışta hala bir şey kalmıştı. Ve daha önce de söylediğim gibi, akış bir akış içindedir, bu yüzden her şey mümkün olan en kısa sürede ondan uzaklaştırılmalıdır. Ve olasılık, bilgisayar eğitimi gördüğü zaman geldi cin >> yaş;
Bilgisayar, birinin yaşını saklayan bir değişken oluşturduğunuzu bilmiyor (4. satır). "yaş" yalnızca bir etikettir. Bilgisayar için "yaş" da "afsfasgfsagasggas" olarak adlandırılabilir ve aynı olur. Onun için bu sadece bir değişkendir ki "Wlodarczyk" atamaya çalışacak çünkü siz bilgisayarı 6. satırda bunu yapmasını emrettiniz / talimat verdiniz.
Bunu yapmak yanlış, ama hey bunu yapan sensin! Bu senin hatan! Belki kullanıcı, ama yine de ...
Tamam tamam. Ama nasıl düzeltilir ?!
Birkaç ilginç şey daha öğrenmek için düzgün bir şekilde düzeltmeden önce bu örnekle biraz oynamaya çalışalım :-)
Bir şeyleri anladığımız yerde bir yaklaşım yapmayı tercih ederim. Nasıl yaptığımızı bilmeden bir şeyi tamir etmek tatmin olmaz, sence de öyle değil mi? :)
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate();
Yukarıdaki kodu çağırdıktan sonra akışınızın (cin) durumunun 4'e (satır 7) eşit olduğunu fark edeceksiniz. Bu, iç durumunun artık iyi bitime eşit olmadığı anlamına gelir. Bir şeyler ters gitti. Oldukça açık, değil mi? Dize türü değerini ("Wlodarczyk") int türü değişken 'age'e atamayı denediniz. Türler eşleşmiyor. Bir şeylerin yanlış olduğunu bildirmenin zamanı geldi. Ve bilgisayar bunu, akışın iç durumunu değiştirerek yapar. Şöyle: "Seni sersem adamım, düzelt beni lütfen. Seni 'nazikçe' ;-)"
Artık 'cin' (akış) kullanamazsınız. Sıkışmış. Sanki su akıntısına büyük tahta kütükler koymuşsunuz gibi. Kullanmadan önce tamir etmelisiniz. Veri (su) artık o akıştan (cin) elde edilemez çünkü odun kütüğü (iç durum) bunu yapmanıza izin vermez.
Öyleyse, bir engel varsa (tahta kütükler), bunu yapmak için yapılmış araçları kullanarak onu kaldırabilir miyiz?
Evet!
Cin'in 4'e ayarlanmış dahili durumu, uluyan ve gürültü çıkaran bir alarma benzer.
cin.clear, durumu normale döndürür (iyi bit). Sanki gelip alarmı susturmuşsun gibi. Sadece erteledin. Bir şey olduğunu biliyorsunuz ve şöyle diyorsunuz: "Gürültü yapmayı bırakmak sorun değil, zaten bir şeylerin yanlış olduğunu biliyorum, kapa çeneni (net)".
Pekala, hadi yapalım! Cin.clear () kullanalım.
İlk girdi olarak "Arkadiusz Wlodarczyk" kullanarak aşağıdaki kodu çağırın:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;
cin.clear();
cout << cin.rdstate()<< endl;
Yukarıdaki kodu çalıştırdıktan sonra durumun goodbit'e eşit olduğunu kesinlikle görebiliriz.
Harika, sorun çözüldü mü?
İlk girdi olarak "Arkadiusz Wlodarczyk" kullanarak aşağıdaki kodu çağırın:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;;
cin.clear();
cout << cin.rdstate() << endl;
cin >> age;
Durum, 9. satırdan sonra iyi bit olarak ayarlanmış olsa bile, kullanıcıdan "yaş" istenmez. Program durur.
NEDEN?!
Ah adamım ... Az önce alarmı bıraktın, peki ya bir suyun içindeki odun kütüğü? * "Wlodarczyk" in sözde nasıl gittiğinden bahsettiğimiz metne geri dön.
O odun parçasını dereden "Wlodarczyk" çıkarmalısın. Alarmları kapatmak sorunu hiç çözmez. Az önce susturdunuz ve sorunun çözüldüğünü mü düşünüyorsunuz? ;)
Yani başka bir aracın zamanı geldi:
cin.ignore, akıntıya sıkışan ahşap kütükleri gelen ve kaldıran halatlı özel bir kamyona benzetilebilir. Programınızın kullanıcısının yarattığı problemi temizler.
Yani alarmı çalmadan önce kullanabilir miyiz?
Evet:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
cin >> age;
"Wlodarczyk" 7. satırda gürültü yapmadan önce kaldırılacak.
10000 ve '\ n' nedir?
10000 karakteri (her ihtimale karşı) '\ n' karşılanana kadar (ENTER) kaldırın diyor. BTW sayısal_sınırlar kullanılarak daha iyi yapılabilir, ancak bu cevabın konusu bu değildir.
Yani sorunun ana nedeni gürültü yapılmadan önce ortadan kalktı ...
O halde neden 'temizliğe' ihtiyacımız var?
Ya birisi 6. satırda 'bana yaşını ver' sorusunu sorduysa, örneğin: 20 yazmak yerine "yirmi yaşında" sorusu?
Türler yine eşleşmiyor. Bilgisayar int'e dizge atamaya çalışır. Ve alarm başlar. Böyle bir duruma tepki verme şansın bile yok. cin.ignore böyle bir durumda size yardımcı olmayacaktır.
Öyleyse böyle durumlarda net kullanmalıyız:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
cin >> age;
cin.clear();
cin.ignore(10000, '\n');
Ama durumu 'her ihtimale karşı' temizlemelisiniz?
Tabii ki değil.
Bir şeyler ters giderse (cin >> yaş;) talimatı yanlış döndürerek sizi bilgilendirecektir.
Böylece, kullanıcının akışa yanlış tür yazıp yazmadığını kontrol etmek için koşullu ifadeyi kullanabiliriz
int age;
if (cin >> age)
cout << "You put integer";
else
cout << "You bad boy! it was supposed to be int";
Pekala, ilk sorunumuzu şu şekilde çözebiliriz:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
if (cin >> age)
cout << "Your age is equal to:" << endl;
else
{
cin.clear();
cin.ignore(10000, '\n');
cout << "Give me your age name as string I dare you";
cin >> age;
}
Elbette bu, örneğin döngü while kullanarak söz konusu yaptığınız şeyi yaparak geliştirilebilir.
BONUS:
Merak ediyor olabilirsiniz. Kullanıcıdan aynı satırda ad ve soyad almak istersem ne olur? Cin, "boşluk" ile ayrılmış her değeri farklı değişken olarak yorumlarsa, cin kullanmak mümkün müdür?
Elbette, bunu iki şekilde yapabilirsiniz:
1)
string name, surname;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin >> surname;
cout << "Hello, " << name << " " << surname << endl;
2) veya getline işlevini kullanarak.
getline(cin, nameOfStringVariable);
ve bu nasıl yapılır:
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
İkinci seçenek, getline'dan önce 'cin' kullandıktan sonra kullanmanız durumunda sizi geri tepebilir.
Hadi kontrol edelim:
a)
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
Yaş olarak "20" koyarsanız adınız ve soyadınız istenmez.
Ama bu şekilde yaparsanız:
b)
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endll
herşey yolunda.
NE?!
Girişe (akışa) bir şey koyduğunuzda, sonunda beyaz karakter olan ENTER ('\ n') bırakırsınız. Konsola bir şekilde değerler girmeniz gerekir. Yani veriler kullanıcıdan geliyorsa gerçekleşmelidir.
b) cin özellikleri, boşlukları yok saymasıdır, bu nedenle cin'den bilgi okurken, satırsonu karakteri '\ n' önemli değildir. Görmezden gelinir.
a) getline işlevi, satırsonu karakterine ('\ n') kadar olan tüm satırı alır ve satırsonu karakteri ilk şey olduğunda getline işlevi '\ n' alır ve elde edilecek tek şey budur. 3. satırda akışa "20" koyan kullanıcı tarafından akışta bırakılan yeni satır karakterini çıkarırsınız.
Yani onu düzeltmek için her zaman cin.ignore () 'u çağırmaktır; programınızın içinde getline () kullanacaksanız, herhangi bir değer elde etmek için cin'i her kullandığınızda.
Dolayısıyla doğru kod şu olacaktır:
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cin.ignore();
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
Umarım akışlar sizin için daha nettir.
Hah sustur beni lütfen! :-)