Trong trường hợp này, bạn bơm thêm một lần nữa sau khi người dùng nhấn '0'. Giả sử rằng điều này là không mong muốn, bạn có những gì được gọi là một "off-by-một lỗi." Bạn có thể khắc phục điều này (và loại bỏ các biến tạm thời) bằng cách sắp xếp lại chức năng của bạn như sau:
void GasPump::dispense()
{
while (true) {
cout << "Press any key, or enter to dispense.\n"
<< "Or press 0 to stop: \n";
if (cin.get() == '0')
break;
gasDispensed = gasDispensed + gasDispensedPerCycle;
charges = costPerGallon*gasDispensed;
displayGasNCharges();
}
}
Để tránh sử dụng một câu lệnh break, bạn có thể sử dụng xây dựng sau đây:
bool GasPump::shouldDispenseGas()
{
cout << "Press any key, or enter to dispense.\n"
<< "Or press 0 to stop: \n";
return (cin.get() != '0');
}
void GasPump::dispense()
{
while (shouldDispenseGas()) {
gasDispensed = gasDispensed + gasDispensedPerCycle;
charges = costPerGallon*gasDispensed;
displayGasNCharges();
}
}
EDIT (2011 Tháng Chín 27): @TonyK Chỉ vì một ngôn ngữ cung cấp một tính năng không có nghĩa là một ngôn ngữ nên sử dụng nó. Tuyên bố goto
là một ví dụ điển hình về điều này.
Được cấp, với vòng lặp đơn giản như vậy, thực sự không có sự khác biệt giữa việc sử dụng hàm và ngắt. Cả hai đều rõ ràng. Tuy nhiên, khi các tính năng bổ sung được thêm vào một tháng (hoặc nhiều năm), cùng với các điều kiện bổ sung để thoát khỏi vòng lặp, rất dễ dàng để tìm các câu lệnh if
nhân với logic phức tạp bên trong một vòng lặp quá lớn. thời gian tìm thấy sự khởi đầu của nó, ít hơn nhiều điểm thoát. Một trong những cách để chống lại loại bloat mã này là viết các hàm ngắn, đơn giản và tập trung được đặt tên tốt. Nếu bạn làm điều này, mã tài liệu chính nó. Hãy so sánh
while (true)
so
while (shouldDispenseGas())
Tương tự, so sánh này cho STL thuật toán for_each
. Chắc chắn, std::for_each(v.begin(), v.end(), &foo);
ngắn hơn một chút so với for (int i = 0; i < v.size(); ++i) { ...body of foo()... }
. Nhưng lợi thế thực sự là dễ dàng hơn để xem mục đích là gì. Trong số for_each
bạn ngay lập tức thấy rằng bạn sẽ làm điều gì đó một lần và chỉ một lần cho từng phần tử. Trong vòng lặp for, bạn không có ý tưởng. Bộ đếm vòng lặp i
có thể được thay đổi trong vòng lặp. Một break
cũng có thể được ẩn bên trong. Bằng cách bỏ qua tuyên bố break
này và nhúng logic vào shouldDispenseGas
, bạn ngay lập tức hiểu các điều kiện theo đó vòng lặp sẽ tiếp tục và kết thúc.
Ooh! Tôi đã không nhận ra khi sử dụng một số thập phân như một char bạn đã phải đặt dấu ngoặc kép xung quanh nó, tốt để biết, cảm ơn rất nhiều nụ! –
@ blakejc70 Vì stop là một char và với phương thức C++, quá tải cuộc gọi của bạn tới cin.get được chuyển đến một logic xử lý đầu vào sẽ trả về một mã ký tự. Vì vậy, dừng == '0' == 48 (đi theo giả định của bộ ký tự ASCII). – David