2008-11-05 42 views
6

Tôi đang học C++ và viết các chương trình nhỏ khi tôi đi cùng. Sau đây là một trong các chương trình như vậy:vòng lặp vô hạn trong c + +

// This program is intended to take any integer and convert to the 
// corresponding signed char. 

#include <iostream> 

int main() 
{ 
    signed char sch = 0; 
    int n = 0; 
    while(true){ 
    std::cin >> n; 
    sch = n; 
    std::cout << n << " --> " << sch << std::endl; 
    } 
} 

Khi tôi chạy chương trình này và giữ nguyên giá trị tuyệt đối nhỏ, nó hoạt động như mong đợi. Nhưng khi tôi nhập các đầu vào lớn hơn, ví dụ: 10000000000, chương trình lặp đi lặp lại phát ra cùng một đầu ra. Một số kết hợp đầu vào gây ra hành vi thất thường. Ví dụ:

#: ./int2ch 
10 
10 --> 

10000000000 
10 --> 

10 --> 

10 --> 

10 --> 

Chương trình phun ra "10 ->" cho đến khi nó bị giết. Tôi cũng nhận thấy rằng đầu ra của các giá trị lớn được xác định bởi đầu vào pháp lý trước đó cũng như giá trị của đầu vào bất hợp pháp hiện tại.

gì đang xảy ra? (Tôi không quan tâm đến việc sửa chương trình, thật dễ dàng. Tôi muốn hiểu nó.)

Trả lời

13

Về cơ bản, luồng cin của bạn đang ở trạng thái không thành công và do đó sẽ trả về ngay lập tức khi bạn cố gắng đọc. Viết lại ví dụ của bạn như thế này:

#include <iostream> 

int main() 
{ 
    signed char sch = 0; 
    int n = 0; 
    while(std::cin >> n){ 
    sch = n; 
    std::cout << n << " --> " << sch << std::endl; 
    } 
} 

cin >> n sẽ trả về một tham chiếu đến cin, mà bạn có thể kiểm tra cho "tốt-Ness" trong một điều kiện. Vì vậy, về cơ bản, "while(std::cin >> n)" đang nói "trong khi tôi vẫn có thể đọc từ đầu vào chuẩn thành công, hãy làm như sau"

EDIT: lý do nó liên tục xuất ra giá trị tốt nhất đã nhập là vì đó là giá trị cuối cùng đọc thành công n, các thất bại lần đọc sẽ không thay đổi giá trị của n

EDIT: như đã nêu trong một chú thích, bạn có thể xóa tình trạng lỗi và thử lại một cái gì đó như thế này có lẽ sẽ làm việc và chỉ cần bỏ qua số xấu:

#include <iostream> 
#include <climits> 

int main() { 
    signed char sch = 0; 
    int n = 0; 
    while(true) { 
     if(std::cin >> n) { 
      sch = n; 
      std::cout << n << " --> " << sch << std::endl; 
     } else { 
      std::cin.clear(); // clear error state 
      std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it 
     } 
    } 
} 
+0

Cách khác, hãy thực hiện cuộc gọi đến std :: cin.clear() để xóa trạng thái lỗi trước khi vượt qua vòng lặp tiếp theo của vòng lặp. – hark

3

Cho rằng bạn đang sử dụng máy 32 bit, 10000000000 là một số quá lớn để được đại diện bởi một int. Cũng chuyển đổi một int thành char sẽ chỉ cung cấp cho bạn từ 0..255 hoặc -128..127 tùy thuộc vào trình biên dịch.

+0

Đó là 0..255 hoặc -128..127, thực sự. :) – unwind

0

Một vấn đề ở đây là char có kích thước một byte và do đó có thể chỉ giữ một số nằm trong khoảng -127 và 128. Mặt khác, int thường là 4 byte và có thể có nhiều giá trị lớn hơn. Vấn đề thứ hai là bạn đang nhập một giá trị quá lớn ngay cả đối với một số int.

+0

đầu tiên của tất cả các in ấn của "một số ký tự lạ" không phải là nguyên nhân, thứ hai là char là không ký theo mặc định, đây là trình biên dịch phụ thuộc. Nó được * thường * ký, nhưng không cần phải. –

5

Có, Evan Teran đã chỉ ra hầu hết mọi thứ. Một điều tôi muốn thêm (kể từ khi tôi không thể bình luận bình luận của mình chưa :)) là bạn phải đặt cuộc gọi đến istream :: rõ ràng trước khi cuộc gọi đến istream :: bỏ qua. Lý do là istream :: bỏ qua tương tự như vậy sẽ chỉ từ chối làm bất cứ điều gì nếu dòng vẫn còn trong trạng thái thất bại.

+0

Cảm ơn, đã sửa. Bạn nhận được một upvote cho điều đó;) –

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