首页 > 解决方案 > 文件仅读取 1 条记录,然后到达文件末尾,即使还有其他记录

问题描述

所以我被赋予了创建一个类似程序库的任务,我被指示对添加的书籍进行不同的操作(添加书籍,删除..)

addbook 函数将 book 对象写入文件,并且 book 的每条记录都有一个 endl 分隔符(这样我以后可以使用 getline 获取记录)

printbook 函数只是获取 book 对象并将其打印出来

我的问题是,当我尝试在文件中打印所有书籍记录(用 main 编写的代码)时,它只读取了第一条记录,并且显然它在没有读取其余记录之后立即到达文件末尾在文件中

我的问题是如何在不读取整个文件的情况下到达文件末尾以及如何解决此问题以便我可以读取已写入文件的所有记录

#include<iostream>
#include<fstream>
#include<strstream>
#include <cstring>
using namespace std;

struct book{
    char ISBN[6];
    char TITLE[100];
    char AUTHOR_NAME[100];
    float PRICE;
    int YEAR;
    int NUM_PAGES;

    book(char* isbn = "" , char* title = "" , char* author = "" , float price = 0 , int year = 0, int nPages = 0){
        strcpy(ISBN ,isbn);
        strcpy(TITLE , title);
        strcpy(AUTHOR_NAME ,author);
        PRICE = price;
        YEAR = year;
        NUM_PAGES = nPages;
    }

};

void printBook(book b);
void addBook(fstream& file );
//void deleteBook(fstream& file , int isbn);
//void updateBook(fstream& file , int isbn);
//void printBookByTitle(fstream& file , char* title);
//void printAll(fstream& file);

void addBook(fstream& file ){
    cout << "\nplease enter your book's \n1- ISBN\n2- title \n3- author name \n4- price \n5- year \n6- number of pages\n";
    book b;

    cin.getline(b.ISBN , 6);
    cin.getline(b.TITLE ,100);
    cin.getline(b.AUTHOR_NAME ,100);
    cin >> b.PRICE;
    cin >> b.YEAR;
    cin >> b.NUM_PAGES;

    cin.ignore();

    file.write((char*)& b ,sizeof(b));
    file<<'\n';
}
void printBook(book b){
    cout << "the book's ISPN is " << b.ISBN << endl;
    cout << "the title of this book is " << b.TITLE << endl;
    cout << "the author is " << b.AUTHOR_NAME << endl;
    cout << "the book's price is "<<b.PRICE<< endl;
    cout << "the year by which was published is "<< b.YEAR << endl;
    cout << "the number of pages on this book is " << b.NUM_PAGES << endl << endl;
}
int main()
{

    fstream file;
    file.open("farah.txt" , ios::out | ios::in );

    book b;
    addBook(file);
    addBook(file);
    addBook(file);


    file.seekg(0);

    do{
        file.getline((char*)& b , sizeof(b)+1);
        printBook(b);
    }while(!file.eof()-1);

    return 0;
}

标签: c++

解决方案


file.write((char*)& b ,sizeof(b));
file<<'\n';

因此,您写出可能包含或不包含换行符的原始记录,然后写出换行符。

    file.getline((char*)& b , sizeof(b)+1);

然后,您getline尝试将其读回。但这行不通。根据定义,一行以换行符结束。因此,如果由读取行的函数读取,记录可能会占用多行。

将一个添加到大小会导致一个巨大的问题。当您的实现看到book b时,它知道分配sizeof(book)字节来保存对象。但是随后您读取的字节数超过了该字节数——写入尚未分配的内存,可能会踩到其他对象或导致访问冲突。

你有几个选择:

您可以使用原始读取函数读取sizeof(b)字节,然后读取换行符。您可以使用原始读取功能并摆脱换行符。您可以在写出记录时将其格式化为一行,然后使用读取行的函数将其读入。

最后,你也在滥用eof. 你试图用它来预测未来,也就是说,告诉你未来的读取是否会成功。但eof它是一种状态报告功能(如selectstatfsaccess等),而不是未来预测功能。相反,看看读取是否真的成功,而不是在执行之前尝试以某种方式确保它不会失败。


推荐阅读