2012-04-27 48 views
14

Trong C++, bạn xử lý các đầu vào sai như thế nào? Giống như, nếu chương trình yêu cầu một số nguyên, khi bạn nhập một ký tự, nó sẽ có thể làm điều gì đó và sau đó lặp lại để lặp lại đầu vào nhưng vòng lặp đi vô hạn khi bạn nhập một ký tự khi số nguyên cần và ngược lại.Cách xử lý nhập dữ liệu sai

Trả lời

32

Lý do chương trình đi vào vòng lặp vô hạn là do cờ đầu vào xấu của std::cin được đặt do lỗi nhập. Điều cần làm là xóa cờ đó và loại bỏ đầu vào xấu khỏi bộ đệm đầu vào.

//executes loop if the input fails (e.g., no characters were read) 
while (std::cout << "Enter a number" && !(std::cin >> num)) { 
    std::cin.clear(); //clear bad input flag 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard input 
    std::cout << "Invalid input; please re-enter.\n"; 
} 

Xem the C++ FAQ cho điều này và các ví dụ khác, bao gồm thêm tối thiểu và/hoặc tối đa điều kiện.

Một cách khác là lấy đầu vào dưới dạng chuỗi và chuyển đổi nó thành số nguyên với std::stoi hoặc một số phương pháp khác cho phép kiểm tra chuyển đổi.

+1

tôi đã thực hiện một số nghiên cứu trước khi yêu cầu tại đây. Tôi thấy rằng họ đặt cin.ignore (1000, '\ n'); điều này làm gì? (Cin >> num) trả về một boolean? tôi không biết rằng – Zik

+0

nhờ trang web – Zik

+1

@Marvin, 'cin.ignore (1000, '\ n')' bỏ qua/loại bỏ các ký tự trong bộ đệm đầu vào cho đến khi 1000 bị loại bỏ hoặc một dòng mới đã gặp phải, bất cứ thứ gì đến trước. Đó là một cách hay để loại bỏ một dòng. Bạn sẽ thấy trong ví dụ parashift, họ sử dụng kích thước tối đa của luồng thay vì 1000 để tính cho một dòng có độ dài tối đa. Tôi sử dụng 'cin.sync()' bởi vì khi làm điều này, tôi muốn được đứng ngang hàng với người dùng (chưa đọc dòng tiếp theo), vì vậy tôi loại bỏ mọi thứ. Cuối cùng, 'cin' có một' toán tử void * ', vì vậy nó không thể chuyển đổi thành bool. – chris

0

Kiểm tra đầu vào để xem liệu chương trình của bạn có dự kiến ​​hay không. Nếu không, hãy thông báo cho người dùng rằng thông tin họ cung cấp không được chấp nhận.

0

Bạn có thể kiểm tra thông qua giá trị ASCII nếu giá trị ascii nằm trong khoảng từ 65 t0 90 hoặc 97 đến 122, nó sẽ là ký tự.

3

Câu trả lời bình chọn hàng đầu đề cập đến giải pháp thực sự tốt.

Ngoài câu trả lời rằng, điều này có thể giúp hình dung những gì đang xảy ra tốt hơn một chút:

int main() 

    int input = 1;//set to 1 for illustrative purposes 
    bool cinState = false; 
    string test = "\0"; 
    while(input != -1){//enter -1 to exit 
     cout << "Please input (a) character(s): ";//input a character here as a test 
     cin >> input; //attempting to input a character to an int variable will cause cin to fail 
     cout << "input: " << input << endl;//input has changed from 1 to 0 
     cinState = cin;//cin is in bad state, returns false 
     cout << "cinState: " << cinState << endl; 
     cin.clear();//bad state flag cleared 
     cinState = cin;//cin now returns true and will input to a variable 
     cout << "cinState: " << cinState << endl; 
     cout << "Please enter character(s): "; 
     cin >> test;//remaining text in buffer is dumped here. cin will not pause if there is any text left in the buffer. 
     cout << "test: " << test << endl; 
    } 
    return 0;  
} 

bán phá giá các văn bản trong bộ đệm cho một biến không phải là đặc biệt hữu ích, tuy nhiên nó giúp hình dung tại sao cin.ignore() là cần thiết.

Tôi cũng lưu ý thay đổi đối với biến đầu vào vì nếu bạn đang sử dụng biến đầu vào trong điều kiện của mình cho vòng lặp while hoặc câu lệnh chuyển có thể bị bế tắc hoặc có thể đáp ứng điều kiện bạn đã ' t mong đợi, có thể khó hiểu hơn để gỡ lỗi.

Các vấn đề liên quan