从二进制文件C ++更新数据

时间:2017-11-07 09:57:18

标签: c++ file

我正在编写一个简单的程序,可以对数据执行删除,修改和其他操作。

不幸的是,我在修改二进制文件中的数据时遇到困难。

以下是updateRecord函数的代码。

当我尝试指出前一个记录时,VS2017会给我下一个错误:

"more then one operator '-' matches these operands"...

请帮忙,

谢谢!!!

#include <iostream>
#include <fstream>
#include <cstring>
#include <stdio.h>

using namespace std;

class Book
{
private:
int bookid;
char title[50];
float price;
public:
Book()
{
    bookid = 0;
    strcpy(title, "no title");
    price = 0;
}

void getDate()
{
    cout << "Enter book id, title and price.";
    cin >> bookid;
    cin.ignore();
    cin.getline(title, 49);
    cin >> price;
}

void showData()
{
    cout << bookid << "  " << title << "  " << price << endl;
}

int storeDate();
void viewAllBooks();
void searchBook(char *);
void deleteBook(char *);
void updateBook(char *);

};

void Book::updateBook(char *t)
{
int pos;
fstream file;
file.open("file.dat", ios::ate | ios::in | ios::out | ios::binary);
file.seekg(0); // read data from the begining of file
file.read((char *)this, sizeof(*this));
while (!file.eof()) // it return 1 so i use not operator to break while loop
{
    if (!strcmp(title, t))
    {
        getDate();
        file.seekp(file.tellg() - sizeof(this));
        file.write((char *)this, sizeof(*this));
    }
    file.read((char *)this, sizeof(*this));
}
file.close();
}

void Book::deleteBook(char *t)
{
ifstream fin;
ofstream fout;
fin.open("file.dat", ios::in | ios::binary);
if (!fin.is_open())
{
    cout << "File not found" << endl;
}
else
{
    fout.open("temp.dat", ios::out | ios::binary);
    fin.read((char*)this, sizeof(*this)); // 
    while (!fin.eof())
    {
        if (strcmp(title, t))
        {
            fout.write((char *)this, sizeof(*this));
        }
        fin.read((char *)this, sizeof(*this));
    }

    fin.close();
    fout.close();

    remove("file.dat");
    rename("temp.dat", "file.dat");
}
}

int Book::storeDate()
{
if (bookid == 0 && price == 0)
{
    cout << "Book data in not initialized." << endl;
    return (0);
}
else
{
    // write data on file
    ofstream fout;
    fout.open("file.dat", ios::app | ios::binary);
    fout.write((char*)this, sizeof(*this));
    fout.close();
    return (1);
}

}

void Book::searchBook(char *t)
{
int count = 0;
ifstream fin;
fin.open("file.dat", ios::in | ios::binary);
if (!fin.is_open())
{
    cout << "File not found" << endl;
}
else
{
    fin.read((char*)this, sizeof(*this));
    while (!fin.eof())
    {
        if (!strcmp(t, title))
        {
            showData();
            count++;
        }

        fin.read((char*)this, sizeof(*this));
    }
    if (count == 0)
    {
        cout << "No record Found." << endl;
    }
    fin.close();
}
}

void Book::viewAllBooks()
{
ifstream fin;
fin.open("file.dat", ios::in | ios::binary);
if (!fin.is_open())
{
    cout << "File not found" << endl;
}
else
{
    // type casting is using here as char
    fin.read((char*)this, sizeof(*this));
    while (!fin.eof())
    {
        showData();
        fin.read((char*)this, sizeof(*this));
    }
    fin.close();
}
}

int main()
{
int choice;
char t[50];
Book b1;
cout << "1- Add Book" << endl;
cout << "2- View all Books" << endl;
cout << "3- Find a Book" << endl;
cout << "4- Delete a Book" << endl;
cout << "5- Update Book" << endl;
cout << "Enter choice: ";
cin >> choice;

switch (choice)
{
case 1:
    b1.getDate();
    b1.storeDate();
    break;
case 2:
    b1.viewAllBooks();
    break;
case 3:
    cout << "Enter Book title: ";
    cin.ignore();
    cin.getline(t, 49);
    b1.searchBook(t);
    break;
case 4:
    cout << "Enter Book title: ";
    cin.ignore();
    cin.getline(t, 49);
    b1.deleteBook(t);
    break;
case 5:
    cout << "Enter Book title: ";
    cin.ignore();
    cin.getline(t, 49);
    b1.updateBook(t);
    break;
default:
    cout << "You entered invalid choice." << endl;
    break;
}

system("PAUSE");
}

2 个答案:

答案 0 :(得分:2)

G ++的完整错误消息为:

foo.cpp: In member function ‘void Book::updateBook(char*)’:
foo.cpp:57:46: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
         file.seekp(file.tellg() - sizeof(this));
                                              ^
In file included from /usr/include/c++/5/iosfwd:40:0,
                 from /usr/include/c++/5/ios:38,
                 from /usr/include/c++/5/ostream:38,
                 from /usr/include/c++/5/iostream:39,
                 from foo.cpp:2:
/usr/include/c++/5/bits/postypes.h:192:7: note: candidate 1: std::fpos<_StateT> std::fpos<_StateT>::operator-(std::streamoff) const [with _StateT = __mbstate_t; std::streamoff = long int]
       operator-(streamoff __off) const
       ^
foo.cpp:57:46: note: candidate 2: operator-(std::streamoff {aka long int}, long unsigned int) <built-in>
         file.seekp(file.tellg() - sizeof(this));
                                              ^

因此,基本上,编译器无法在operator-()提供的std::fposlong int / long unsigned int提供的tellg()之间做出决定。

我不太清楚你的代码想要完成什么 - 那里没有任何评论,当我试图从源头中找出你的意图时我的大脑会受伤 - 但是:

1)您可以将size_t的结果转换为sizeof,或将std::streamoff的结果转换为*this,以使错误消失(因为模糊性得到解决)

2) 不会覆盖BookCollection 。我不太确定你打算在那里做什么,但我很确定你没有做到(正确)。通过闭着眼睛看着它,我敢说应该有另一个类,可能是std::vector< Book >,它拥有std::istream & operator>>( std::istream &, Book & ),并且有一个std::ostream & operator<<( std::ostream &, Book const & )和{{{{ 1}}实现您应该能够从/向文件读取/写入单个Book数据而不会破坏某些内容。

// Warning, untested, on-the-fly

// In the declaration of class Book
// (You need to "friend" these functions so they
// may access Book private member variables.)
friend std::ostream & operator<<( std::ostream & ostr, Book const & book );
friend std::istream & operator>>( std::istream & istr, Book & book )


// Outside the declaration -- these are NOT
// member functions of class Book!
std::ostream & operator<<( std::ostream & ostr, Book const & book )
{
    // Writing relevant data to stream -- this might
    // be a file, std::cout, or even a socket...
    ostr << book.bookid << "\n" << book.price << "\n" << book.title << "\n";
    return ostr;
}

std::istream & operator>>( std::istream & istr, Book & book )
{
    // Reading the relevant data. This needs to mirror
    // what operator<<() does, above.
    istr >> book.bookid;
    istr >> book.price;
    // Assuming you use `std::string` for book.title,
    // which would be the sensible thing to do
    std::getline( istr, book.title );
    return istr;
}

// Somewhere else (e.g. in class BookCollection)
Book book;
std::fstream file;
// open file, positioning, ...
// Note that positioning is now done line-based
// (three lines to a book -- take care that no
// newlines are entered as part of the title!),
// not via some sizeof( *this ) hackmudgery.
// Reading a book entry...
file >> book;
// ...and writing it.
file << book;

答案 1 :(得分:1)

问题是sizeof(*this)operator-重载完全不匹配,因此在选择正确的重载时存在歧义。要修复,只需自己选择一个过载:

file.seekp(file.tellg() - std::streamoff(sizeof(this)));