xem xét ví dụ đơn giản sau đâyĐọc với setw: để eof hay không để eof?
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
int main() {
string str = "string";
istringstream is(str);
is >> setw(6) >> str;
return is.eof();
}
Thoạt nhìn, kể từ chiều rộng rõ ràng được xác định bởi các setw
thao túng, tôi mong đợi các nhà điều hành >>
để đọc xong chuỗi sau khi giải nén thành công số lượng yêu cầu của nhân vật từ luồng đầu vào. Tôi không thấy bất kỳ lý do ngay lập tức nào để cố gắng trích xuất ký tự thứ bảy, điều đó có nghĩa là tôi không mong đợi luồng sẽ nhập trạng thái eof
.
Khi tôi chạy ví dụ này dưới MSVC++, nó hoạt động như tôi mong đợi: luồng vẫn ở trạng thái tốt sau khi đọc. Tuy nhiên, trong GCC, hành vi khác nhau: luồng kết thúc ở trạng thái eof
.
Tiêu chuẩn ngôn ngữ, nó mang lại cho danh sách sau đây của điều kiện hoàn thành cho phiên bản này của >>
hành
- n ký tự được lưu trữ;
- kết thúc tệp xuất hiện trên chuỗi đầu vào;
- isspace (c, is.getloc()) là đúng cho ký tự đầu vào có sẵn tiếp theo c.
Do ở trên, tôi không thấy bất cứ lý do cho các nhà điều hành >>
để lái dòng vào tình trạng eof
trong đoạn code trên.
Tuy nhiên, đây là những gì >>
hành implementation in GCC library trông giống như
...
__int_type __c = __in.rdbuf()->sgetc();
while (__extracted < __n
&& !_Traits::eq_int_type(__c, __eof)
&& !__ct.is(__ctype_base::space,
_Traits::to_char_type(__c)))
{
if (__len == sizeof(__buf)/sizeof(_CharT))
{
__str.append(__buf, sizeof(__buf)/sizeof(_CharT));
__len = 0;
}
__buf[__len++] = _Traits::to_char_type(__c);
++__extracted;
__c = __in.rdbuf()->snextc();
}
__str.append(__buf, __len);
if (_Traits::eq_int_type(__c, __eof))
__err |= __ios_base::eofbit;
__in.width(0);
...
Như bạn có thể thấy, ở phần cuối của mỗi lần lặp thành công, nó cố gắng để chuẩn bị __c
ký tự tiếp theo cho phiên bản kế tiếp, mặc dù lặp lại tiếp theo có thể không bao giờ xảy ra. Và sau chu kỳ, nó phân tích giá trị cuối cùng của ký tự __c
đó và đặt eofbit
cho phù hợp.
Vì vậy, câu hỏi của tôi là: kích hoạt trạng thái luồng eof
trong tình huống trên, như GCC thực hiện - có hợp pháp không theo quan điểm chuẩn? Tôi không thấy nó được chỉ định rõ ràng trong tài liệu. Cả hành vi của MSVC và GCC có tuân thủ không? Hay chỉ một trong số họ hoạt động chính xác?
Tôi không nghĩ rằng đặc điểm kỹ thuật yêu cầu kiểm tra danh sách để đoản mạch (hoặc thậm chí theo thứ tự đó), và nếu nó không bắt buộc phải đoản mạch thì mục thứ ba (kiểm tra 'isspace' cho mục tiếp theo có sẵn ký tự đầu vào) sẽ yêu cầu nó để chuẩn bị ký tự tiếp theo. –
[libC++] (http://coliru.stacked-crooked.com/a/b0c5d41b6d1944c5) đồng ý với MSVC. –
Tôi không có văn bản tiêu chuẩn để sao lưu này, nhưng sự hiểu biết của tôi là nó là tùy chọn cho dù đọc ký tự cuối cùng đặt 'eofbit'. (Cố gắng đọc sau khi đọc nhân vật cuối cùng chắc chắn đã đặt nó). –