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

Updating data from binary file C++

本文关键字:数据 更新 C++ 二进制文件      更新时间:2023-10-16

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

不幸的是,我在修改二进制文件中的数据时陷入困境。

这是下面的更新记录函数的代码。

当我尝试指向前一个记录时,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");
}

来自 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));
^

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

我不太确定你的代码试图完成什么——那里没有评论,当试图从源代码找出你的意图时,我的大脑很痛——但是:

1)您可以将tellg()的结果转换为size_t,或将sizeof的结果转换为std::streamoff,以使错误消失(随着歧义的解决)

2)不要覆盖*this。我不太确定你打算在那里做什么,但我很确定你没有这样做(正确)。闭着一只眼睛看它,我敢说应该有另一个类,也许是一个BookCollection,它有一个std::vector< Book >,并且通过适当的std::istream & operator>>( std::istream &, Book & )std::ostream & operator<<( std::ostream &, Book const & )实现,你应该能够读取/写入单个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;

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

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