0

so i was given a task to create a library like program i was instructed to make different operations on the books added(adding books ,deleting ..)

addbook function writes the book objects intothe file and each record of book gets an endl delimeter (so that i can get the record later on using getline)

printbook function just takes the book object and prints it out

my problem is when i tried to print all the records of books (code written in main) in the file it only read the first record and apparently it reaches the end of file immediately after even tho it hadnt read the rest of the records that were in the file

my question is how is ir possible that it reached the end of file without to reading the whole file and how do i fix this problem so that i can read all the records that have been written into the file

#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;
}
  • Before printing the book, test for eof(). `While (file.getline((char*)& b , sizeof(b)+1) printBook(b); – Ted D. Mar 05 '19 at 20:49

2 Answers2

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

So you write out a raw record that may or may not happen to contain newline characters and then write out a newline character.

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

Then you use getline to try to read it back. But that won't work. A line, by definition, ends at a newline character. So the record may appear, if read by a function that reads lines, to occupy more than one line.

The addition of one to the size causes a huge problem. When your implementation sees book b, it knows to allocate sizeof(book) bytes to hold the object. But then you read more than that number of bytes -- writing to memory that you haven't allocated, potentially stomping on other objects or causing an access violation.

You have a few choices:

You can use a raw read function to read sizeof(b) bytes and then read the newline character. You can use the raw read function and get rid of the newline. You can format the record as a line when you write it out and then use a function that reads lines to read it in.

Lastly, you're also misusing eof. You are trying to use it to predict the future, that is, to tell you whether or not a future read will succeed. But eof is a status-reporting function (like select, statfs, access, and many more), not a future-predicting function. Instead, see if the read actually succeeded rather than trying to somehow ensure it won't fail before you perform it.

David Schwartz
  • 166,415
  • 16
  • 184
  • 259
1

while(!file.eof()-1); should be while(!file.eof()); That's probably the main problem.

char* isbn = "" , char* title = "" , char* author = "" ...

That is only allowed in C not C++, because you are trying to convert char * to const char *

HectorTav
  • 36
  • 1
  • 4