Lỗi EOF trong C++

Mình đang sử dụng C++, nhưng gặp một vấn đề.

Giả sử mình có một dãy số: 3, 5, 1, 8, 2 được ghi vào tệp. Và sau đó mình đọc dữ liệu vào như sau:

while (!fin.eof())
{
	fin >> a;
	cout << a <<" ";
}
fin.close();

->Thì được kết quả không mong muốn, dữ liệu được xuất ra như thế này đây: 3, 5, 1, 8, 2, 2
bị thừa một số 2.
Tại sao vậy???:Mọi người giải quyết dùm mình với. Xin cảm ơn!

while(fin >> a)
    cout << a << " ";

“Read while data exists to be read”
http://www.dreamincode.net/forums/topic/145699-eof-and-reading-text-files-c/

2 Likes

Đây chỉ một ví dụ ngắn mà mình muốn nói tới lỗi thôi bạn à.
Trong một số bài lớn, bắt buộc phải dùng tới eof()
giải thích giúp mình cách nó hoạt động như thế nào với?

Mình nghĩ là sau khi số 2 được đưa vào luồng thì hàm eof() vẫn chưa chạy hết file nên vòng lặp while lại tiếp tục nhưng k còn giá trị nào khác nên phải lấy giá trị cuối trong luồng là 2 để tiếp tục lặp.

1 Like

Bạn có thể cho ví dụ về một số bài lớn không?
Vẫn có thể sử dụng eof() được nhưng phải kiểm tra dữ liệu được đọc vào trước.
Do EOF không đọc được. Vì vậy fin >> a không thực hiện được. Vì vậy a sẽ vẫn giữ giá trị trước đó.

1 Like

Một phần bài lớn của mình đây bạn:

ĐÂY LÀ PHẦN ĐỌC:

void DocFile(vector<NhanVien*> &DanhSach)
{
	int k = 1;
	DanhSach.clear();
	ifstream fin("DanhSach.txt");
	while (!fin.eof())
	{
		bool Loai;
		string name; 
		int year; 
		float luongCB, HSLuong, NoXacDinh;
		//-------------
		
		fin >> Loai;//Toan tu nhap bo qua cac ki tu khoang trang
		fin.get();

		getline(fin, name, '#');

		fin >> year;
		fin.get();//bo #
								//0#Nguyen Dai Duong#9#9#9
		fin >> luongCB;
		fin.get();//bo #

		fin >> HSLuong;
		fin.get();//bo #

		fin >> NoXacDinh;
		
		char ch;
		
		ch = fin.get();
		if ( ch == '\n')
		{
			if (!Loai)
			{
				CongNhan *temp = new CongNhan;
				temp->NhapDL(name, year, luongCB, HSLuong, NoXacDinh);
				DanhSach.push_back(temp);
			}
			else
			{
				QuanLy *temp = new QuanLy;
				temp->NhapDL(name, year, luongCB, HSLuong, NoXacDinh);
				DanhSach.push_back(temp);
			}
			
		}
		//cout << k++ << fin.eof() << ch;//test
	}
	
}

ĐÂY LÀ PHẦN GHI:

void GhiFile(CongNhan *temp)
{
	ofstream fout("DanhSach.txt",ios::app);
	fout << temp->PhanLoai()<<"#";
	fout << temp->GetHoTen() << "#";
	fout << temp->GetNamSinh() << "#";
	fout << temp->GetLuongCoBan() << "#";
	fout << temp->GetHeSoLuong() << "#";
	fout << temp->GetSoNgayLam() << "\n";
	
}

void GhiFile(QuanLy *temp)
{
	ofstream fout("DanhSach.txt", ios::app);
	fout << temp->PhanLoai() << "#";
	fout << temp->GetHoTen() << "#";
	fout << temp->GetNamSinh() << "#";
	fout << temp->GetLuongCoBan() << "#";
	fout << temp->GetHeSoLuong() << "#";
	fout << temp->GetPhuCap() << "\n";
}

Khi đọc khó hiểu, mong bạn thông cảm

Mình phải thêm phần if(ch==’\n’)… thì mới giải quyết được vấn đề này
Nhưng khi bỏ đi thì không hiểu sao lại tạo thừa một đối tượng

Lý do vấn đề bạn đang gặp là do EOF được bật chỉ khi stream không đọc được thêm bất cứ gì (fin >> a). Theo như ví dụ của bạn, khi read tới character cuối cùng (2), fin vẫn còn đọc được, nên EOF chưa được bật, vòng lặp tiếp tục được chạy.

Ờ lần lặp tiếp theo, fin mới thật sự không đọc được data trên stream, nên EOF mới được bật. Nhưng do buffer data ở vòng lặp cũ vẫn còn đưọc giữ, kết quả là bạn in ra số 2 thêm 1 lần nữa.

Mình nghĩ bạn có thể follow theo cách bạn @Rok_Hoang, nhưng nếu bạn vẫn muốn xài eof thì có thể coi qua 2 đoạn code của mình.

while (true)
{
    fin >> a;
    if(fin.eof()) {
        break; 
    }
    cout << a <<" ";
}

hoặc sử dụng:

while (!fin.eof())
{
    fin >> a;
    if(fin.eof()) {
       break; 
    }

    cout << a <<" ";
}

Thân ái và quyết thắng.

3 Likes

Cảm ơn các bạn nhé. Xin chân thành cảm ơn. Bây giờ thì mình đã rõ rồi!

1 Like

Mình cũng đang gặp vấn đề như bạn, nếu bạn đã rõ thì giải thích giúp mình

Bạn đọc comment đầu tiên của bạn @Rok_Hoang và của bạn @chp chưa?

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