从二进制文件C++更新数据
Updating data from binary file C++
我正在编写一个简单的程序,它可以对数据进行删除,修改和其他操作。
不幸的是,我在修改二进制文件中的数据时陷入困境。
这是下面的更新记录函数的代码。
当我尝试指向前一个记录时,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)));
相关文章:
- 如何在ECS框架中更新组件数据和通知系统
- 在 1 个服务器 n 客户端套接字 C++ MFC 应用程序中更新数据的客户端
- LLVM:在运行时更新数据结构
- 类的成员数据未更新
- 使用二进制数据更新 PostgreSQL 表
- QTableView 不会更新数据
- 有没有办法有效地更新QML中的CAN数据?
- 如何使用C++删除/更新txt文件中的特定数据
- 如何使用C++删除/更新txt文件中的特定数据?
- 比较 JSON::Value 变量中的数据,然后更新到文件
- 如何自动更新表格数据或数据库
- 如何在线程中更新qcustomplot数据
- 从高度动态的C 数据模型中更新QML:计时器与属性绑定
- 随着C 的数据更改,更新本地Qlabel的文本
- 用于在具有更新查询的二维矩阵中查找最大值的最佳数据结构
- MySQL 使用一组列中的数据更新列,以非零值为准
- 使用来自不同线程的实时数据更新QTableView的最佳策略
- 从网站将数据更新到QTableView(间歇性)
- 如何使用 ODBC API 将数据更新插入到 NVARCHAR 列中
- OpenGL + 无法使用缓冲区子数据更新缓冲区数据