Chương trình bị lặp vô hạn

#include <iostream>

using namespace std;

int main() {
	
	while(1) {
		int t;
		cout << "Nhap t: ";
		cin >> t;
		if(t==1) {
			cout << "1\n";
		} else if(t==2) {
			cout << "2\n";
		} else {
			cin.ignore();
			cout << "Nhap t: ";
			cin >> t;
		}
	}
    return 0;
}

các bác cho e hỏi e nhập t=1 hoặc 2 thì đúng nhưng e muốn dùng else để bắt các input khác và muốn nhập lại t. nhưng khi e nhập số khác 1,2 ví dụ như 3, 4, 5 thì chương trình bắt nhập lại(0k theo đúng ý muốn). nhưng ví dụ e nhập chữ hoặc kí tự thì nó lại tạo thành vòng lặp vĩnh viễn và k nhập được nữa. các bác cho e xin ý kiến với

gõ ký tự thì cin >> n nó đọc lỗi, nó set flag lỗi ở trong cin nên ko đọc tiếp được nữa. Cách chữa là gọi cin.clear() cho nó reset lại cái flag lỗi kia, và ignore hết các ký tự còn trong buffer của cin bằng cách gọi cin.ignore(numeric_limits<streamsize>::max(), '\n') :V

while (1) {
    int t;
    cout << "Nhap t: ";
    if (cin >> t) { // nếu nhập cin >> t thành công
        if (t == 1) {
            cout << "1\n";
        } else if (t == 2) {
            cout << "2\n";
        }
        // ko phải 1 2 thì bỏ qua, để vòng lặp sau lấy input lại
    } else { // nhập cin >> t thất bại, có thể là do input có ký tự khác chữ số
        cin.clear(); // xóa failbit trong cin
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); // include thêm header <limits>
    }
}

code thế này thì nhập “1”, “2” nó vào if t == 1 2 ở trên, nhập “3”, “456” gì nó bỏ qua, nhập “abc defg” nó vào cái else ở dưới, nhập vào “123abc” thì nó chạy tận 2 vòng lặp, vòng lặp thứ nhất nhập 123 vào t, rồi lần lặp thứ 2 là đọc thất bại, vào cái else cuối kia clear và ignore hết “abc”

cin >> t đọc vào thất bại thì flag failbit được set là true trong cin, nên phải gọi cin.clear() để set failbit thành false trước, rồi mới ignore hết các ký tự còn sót lại trong buffer của cin sau. cin.ignore(X, Y) thì X là số lượng ký tự tối đa cần bỏ qua, cho tới khi gặp ký tự Y thì dừng. Ví dụ cin.ignore(10, '\n') thì với buffer còn sót lại các ký tự “abcde\n” thì nó ignore hết, nhưng với “abc123456789\n” thì nó chỉ ignore 10 ký tự “abc1234567”, buffer vẫn còn sót lại “89\n”, nên cần viết numeric_limits<streamsize>::max() để bảo đảm nó ignore hết :V cái streamsize max value này là 1 số khá lớn, có thể là 2 tỷ hay 4 tỷ hay 2^63 2^64 gì đấy ko cần biết, chỉ biết là viết thế này là bảo đảm buffer của cin được ignore hết :V

3 Likes

mình nghĩ là cin.ignore() là xóa hết cơ. k cần (numeric_limits::max(), ‘\n’);
còn cái cin.clear(); mình chưa dùng bao giờ


của mình nó báo lỗi

cin.ignore(numeric_limits::max(), ‘\n’); // include thêm header <limits>

Bạn chưa đọc hết comment trong code của @tntxtnt kìa :sweat_smile:

3 Likes

mình nghĩ là cin.ignore() là xóa hết cơ

Bạn nghĩ vậy nhưng C++ nó lại nghĩ khác nhé :smile:
Bạn xem khác biệt của biến _M_gcount trong 2 hàm này là gì.

cin.ignore()
_M_gcount = 1;
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/istream.tcc#L477

cin.ignore(n)
while (_M_gcount < __n .... ) ++_M_gcount;
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/istream.tcc#L510


còn cái cin.clear();

istream operator >> (int)
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/istream.tcc#L169

Trong này bạn để ý những chổ mà C++ cast input về kiểu int không được thì nó set cái state of stream là fail bit. Lúc đó gọi hàm clear

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/basic_ios.tcc#L41

để set lại state of stream, với tham số mặc định là good bit. Như thế mới tiếp tục sử dụng stream này được.

3 Likes
basic_istream& ignore( std::streamsize count = 1, int_type delim = Traits::eof() );

https://en.cppreference.com/w/cpp/io/basic_istream/ignore

ignore() chỉ xóa có 1 ký tự à :V Mặc định count = 1, delim = eof

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?