我做了一个书店管理系统的C++程序,目前存在以下错误:
1、在VS code中调试程序,中文部分全部为乱码,更改cpp文件编码格式(UTF-8和ANSI)都没有用
2、保存图书信息时会覆盖掉过去的记录
3、图书信息查询时,不能正常查询
(包括:不能从读取的数据中获取信息,例如:我在data.txt中录入了图书A的信息,程序成功读取该文件,但不能查找到这本书;当此录入书籍后不能正常查询)
请帮我检查一下是哪里出了问题?
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <iomanip>
#include <windows.h>
using namespace std;
class Book {
public:
string name;
string author;
string publisher;
int pages;
time_t latest_time;
int stock;
double price;
Book(string n, string a, string p, int pg, int s, double pr) {
name = n;
author = a;
publisher = p;
pages = pg;
latest_time = time(NULL);
stock = s;
price = pr;
}
friend ostream& operator<<(ostream& os, const Book& book) {
os << "图书书名:" << book.name << endl;
os << "图书作者:" << book.author << endl;
os << "图书出版社:" << book.publisher << endl;
os << "图书页数:" << book.pages << endl;
os << "最新入库时间:" << put_time(localtime(&book.latest_time), "%Y-%m-%d %H:%M:%S") << endl;
os << "图书库存量:" << book.stock << endl;
os << "图书价格:" << book.price << endl;
return os;
}
};
class PurchaseRecord {
public:
string name;
string author;
string publisher;
int pages;
time_t time1;
int quantity;
double price;
PurchaseRecord(string n, string a, string p, int pg, int q, double pr) {
name = n;
author = a;
publisher = p;
pages = pg;
time1 = time(NULL);
quantity = q;
price = pr;
}
friend ostream& operator<<(ostream& os, const PurchaseRecord& record) {
os << "图书书名:" << record.name << endl;
os << "图书作者:" << record.author << endl;
os << "图书出版社:" << record.publisher << endl;
os << "图书页数:" << record.pages << endl;
os << "图书入库时间:" << put_time(localtime(&record.time1), "%Y-%m-%d %H:%M:%S") << endl;
os << "图书进货数量:" << record.quantity << endl;
os << "图书进货价格:" << record.price << endl;
return os;
}
};
class SalesRecord {
public:
string name;
string author;
string publisher;
int pages;
time_t time2;
int quantity;
double price;
SalesRecord (string n, string a, string p, int pg, int q, double pr) {
name = n;
author = a;
publisher = p;
pages = pg;
time2 = time(NULL);
quantity = q;
price = pr;
}
friend ostream& operator<<(ostream& os, const SalesRecord& record) {
os << "图书书名:" << record.name << endl;
os << "图书作者:" << record.author << endl;
os << "图书出版社:" << record.publisher << endl;
os << "图书页数:" << record.pages << endl;
os << "图书销售时间:" << put_time(localtime(&record.time2), "%Y-%m-%d %H:%M:%S") << endl;
os << "图书销售数量:" << record.quantity << endl;
os << "图书销售价格:" << record.price << endl;
return os;
}
};
class Bookstore
{
private:
vector<Book> books;
vector<PurchaseRecord> purchase_records;
vector<SalesRecord> sales_records;
set<string> warning_books;
public:
void add_book(string n, string a, string p, int pg, int s, double pr)
{
Book book(n, a, p, pg, s, pr); books.push_back(book);
}
void purchase(string n, string a, string p, int pg, int q, double pr) {
PurchaseRecord record(n, a, p, pg, q, pr);
purchase_records.push_back(record);
for (auto& book : books) {
if (book.name == n && book.author == a && book.publisher == p && book.pages == pg) {
book.stock += q;
book.latest_time = time(NULL);
if (book.stock <= 1) {
warning_books.insert(n);
}
return;
}
}
add_book(n, a, p, pg, q, pr);
warning_books.insert(n);
}
void sell(string n, string a, string p, int pg, int q, double pr) {
SalesRecord record(n, a, p, pg, q, pr);
sales_records.push_back(record);
for (auto& book : books) {
if (book.name == n && book.author == a && book.publisher == p && book.pages == pg) {
book.stock -= q;
book.latest_time = time(NULL);
if (book.stock <= 1) {
warning_books.insert(n);
}
return;
}
}
}
void query_book(string n, string a)
{
for (auto& book : books) {
if (book.name == n && book.author == a)
{
cout << book << endl;
return;
}
}
cout << "Error Message : Warning! The book information was not found! Please enter the correct book information!" << endl;
}
void warning()
{
if (warning_books.empty())
{
cout << "Message : There are currently no books that require warning!" << endl;
return;
}
cout << "Message : The inventory of the following books is 1. Please purchase them in a timely manner:" << endl;
for (auto& book : warning_books)
{
cout << book << endl;
}
}
void save_data()
{
ofstream fout("data.txt");
if (!fout)
{
cout << "Error Message : File opening failed!"<< endl;
return;
}
fout << "图书信息:" << endl;
for (auto& book : books) {
fout << book << endl;
}
fout << "图书进货记录:" << endl;
for (auto& record : purchase_records) {
fout << record << endl;
}
fout << "图书销售记录:" << endl;
for (auto& record : sales_records) {
fout << record << endl;
}
fout.close();
cout << "Message : Data saved successfully!" << endl;
}
void load_data()
{
ifstream fin("data.txt");
if (!fin) {
cout << "Error Message : File opening failed!" << endl;
return;
}
string line;
while (getline(fin, line)) {
if (line == "图书信息:") {
while (getline(fin, line) && line != "进货记录:") {
string name, author, publisher;
int pages, stock;
double price;
time_t latest_time;
sscanf(line.c_str(), "书名:%s 作者:%s 出版社:%s 页数:%d 最新入库时间:%ld 库存量:%d 价格:%lf",
&name, &author, &publisher, &pages, &latest_time, &stock, &price);
Book book(name, author, publisher, pages, stock, price);
book.latest_time = latest_time;
books.push_back(book);
if (stock == 1) {
warning_books.insert(name);
}
}
}
else if (line == "进货记录:") {
while (getline(fin, line) && line != "销售记录:") {
string name, author, publisher;
int pages, quantity;
double price;
time_t time;
sscanf(line.c_str(), "书名:%s 作者:%s 出版社:%s 页数:%d 入库时间:%ld 进货数量:%d 进货价格:%lf",
&name, &author, &publisher, &pages, &time, &quantity, &price);
PurchaseRecord record(name, author, publisher, pages, quantity, price);
record.time1 = time;
purchase_records.push_back(record);
}
}
else if (line == "销售记录:") {
while (getline(fin, line)) {
string name, author, publisher;
int pages, quantity;
double price;
time_t time;
sscanf(line.c_str(), "书名:%s 作者:%s 出版社:%s 页数:%d 销售时间:%ld 销售数量:%d 销售价格:%lf",
&name, &author, &publisher, &pages, &time, &quantity, &price);
SalesRecord record(name, author, publisher, pages, quantity, price);
record.time2 = time;
sales_records.push_back(record);
}
}
}
fin.close();
cout << "Message : Data read successful!"<< endl;
}
void show_menu() {
cout << "欢迎使用书店管理系统!" << endl;
cout << "1. 添加图书" << endl;
cout << "2. 进货入库" << endl;
cout << "3. 销售出货" << endl;
cout << "4. 查询图书信息" << endl;
cout << "5. 自动预警提示" << endl;
cout << "6. 保存数据到文件" << endl;
cout << "7. 从文件中读取数据" << endl;
cout << "0. 退出系统" << endl;
cout << "请输入操作编号:";
}
void run() {
int choice;
while (true) {
show_menu();
cin >> choice;
switch (choice) {
case 1: {
string name, author, publisher;
int pages, stock; double price;
cout << "请输入书名:"; cin >> name;
cout << "请输入作者:"; cin >> author;
cout << "请输入出版社:"; cin >> publisher;
cout << "请输入页数:"; cin >> pages;
cout << "请输入库存量:"; cin >> stock;
cout << "请输入价格:"; cin >> price;
add_book(name, author, publisher, pages, stock, price);
cout << "Message : Book added successfully!"<< endl;
break;
}
case 2: {
string name, author, publisher;
int pages, quantity;
double price;
cout << "请输入书名:";
cin >> name;
cout << "请输入作者:";
cin >> author;
cout << "请输入出版社:";
cin >> publisher;
cout << "请输入页数:";
cin >> pages;
cout << "请输入进货数量:";
cin >> quantity;
cout << "请输入进货价格:";
cin >> price;
purchase(name, author, publisher, pages, quantity, price);
cout << "Message : Succeeded in purchasing and warehousing!" << endl;
break;
}
case 3: {
string name, author, publisher;
int pages, quantity;
double price;
cout << "请输入书名:";
cin >> name;
cout << "请输入作者:";
cin >> author;
cout << "请输入出版社:";
cin >> publisher;
cout << "请输入页数:";
cin >> pages;
cout << "请输入销售数量:";
cin >> quantity;
cout << "请输入销售价格:";
cin >> price;
sell(name, author, publisher, pages, quantity, price);
cout << "Message : Sales shipment successful!" << endl;
break;
}
case 4: {
string name, author;
cout << "请输入书名:";
cin >> name;
cout << "请输入作者:";
cin >> author;
query_book(name, author);
break;
}
case 5: {
warning();
break;
}
case 6: {
save_data();
break;
}
case 7: {
load_data();
break;
}
case 0: {
cout << "感谢使用书店管理系统,再见!" << endl;
return;
}
default: {
cout << "Error Message : Warning! No valid input information detected! Please re-enter!" << endl;
break;
}
}
}
}
};
int main()
{
Bookstore bookstore;
bookstore.run();
return 0;
}
不知道你这个问题是否已经解决, 如果还没有解决的话:可能出现了几个问题,需要逐一排查:
首先需要确保源代码文件的编码格式为UTF-8,并且在保存时选择“以UTF-8_WITH_BOM格式保存”(VS code中的设置可以通过Ctrl+Shift+P打开命令面板,搜索“文件编码”)。如果还是出现乱码,则需要在程序中添加代码以支持中文输出:
#include <iostream>
#include <locale>
using namespace std;
int main() {
// 设置标准输出流的本地化类型为中文
wcout.imbue(locale("chs"));
// 输出中文
wcout << L"你好,世界!" << endl;
return 0;
}
上述代码中,wcout
是一个输出流对象,通过调用它的imbue()
方法来设置输出流的本地化类型为中文,然后就可以通过wcout
输出支持中文的字符串了。
这个问题可能是由于每次保存时都是以覆盖写文件的方式实现的,而没有将新记录追加到文件的末尾。可以通过以下代码实现:
#include <fstream>
using namespace std;
int main() {
// 打开文件
ofstream fout("data.txt", ios::app);
// 写入数据
fout << "book_A" << ',' << "author_A" << ',' << 100 << endl;
// 关闭文件
fout.close();
return 0;
}
上述代码中,ofstream
是一个输出文件流对象,通过设置打开方式为ios::app
就可以实现追加写入文件。每次保存新记录时,就将新记录追加到文件末尾即可。
这个问题可能是由于查询条件不正确或数据格式不规范导致的。可以添加一些调试代码来查看程序的执行过程和变量值,以便快速定位问题。例如:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// 读取文件
ifstream fin("data.txt");
string line;
while (getline(fin, line)) {
// 调试代码
cout << line << endl;
// 解析数据
// ...
}
// 关闭文件
fin.close();
return 0;
}
上述代码中,ifstream
是一个输入文件流对象,通过getline()
方法每次读取一行文件,并将该行文件输出到控制台以便调试。然后就可以查看输出结果,看看数据格式是否正确。如果数据格式不规范,可以添加一些代码来对数据进行格式化处理,以方便查询。
综合GPT的回答:
文件内容你可能不是以追加的方式打开的文件
#include <iostream>
#include <fstream>
int main() {
std::ofstream file("filename.txt", std::ios::app); // 打开文件以追加方式写入
if (file) {
file << "追加的内容" << std::endl;
file.close();
std::cout << "内容已追加到文件中" << std::endl;
} else {
std::cout << "无法打开文件" << std::endl;
}
return 0;
}
确定文件的编码方式:首先要确定文件的编码方式是什么,常见的编码方式有UTF-8、GBK等。可以使用文本编辑器打开文件并查看编码方式,或者使用其他工具进行检测。
使用正确的编码方式打开文件:在C++中,使用标准库的方式打开文件可能会使用默认的编码方式,这可能导致中文乱码。为了避免这个问题,可以使用适当的编码方式打开文件。例如,使用std::wifstream
代替std::ifstream
,并使用std::locale
设置合适的编码方式,如下所示:
#include <iostream>
#include <fstream>
#include <locale>
int main() {
std::wifstream file("filename.txt");
file.imbue(std::locale("")); // 使用系统默认的编码方式
if (file) {
std::wstring line;
while (getline(file, line)) {
std::wcout << line << std::endl;
}
} else {
std::cout << "无法打开文件" << std::endl;
}
return 0;
}
iconv
库来进行编码转换。这个库提供了一种简单的方式将一个编码转换为另一个编码。你可以在代码中使用iconv
库函数将文件内容从一种编码方式转换为另一种编码方式,然后再进行处理。#include <iostream>
#include <fstream>
#include <iconv.h>
int main() {
std::ifstream file("filename.txt");
if (file) {
std::string line;
while (getline(file, line)) {
// 将line从GBK编码转换为UTF-8编码
std::string convertedLine = convertEncoding(line, "GBK", "UTF-8");
std::cout << convertedLine << std::endl;
}
} else {
std::cout << "无法打开文件" << std::endl;
}
return 0;
}
std::string convertEncoding(const std::string& str, const char* fromEncoding, const char* toEncoding) {
iconv_t converter = iconv_open(toEncoding, fromEncoding);
if (converter == (iconv_t)-1) {
std::cerr << "无法打开编码转换器" << std::endl;
return "";
}
size_t inBytes = str.length();
size_t outBytes = inBytes * 2; // 估计输出缓冲区大小为输入的两倍
char* inBuffer = const_cast<char*>(str.c_str());
char* outBuffer = new char[outBytes];
char* outBufferPtr = outBuffer;
if (iconv(converter, &inBuffer, &inBytes, &outBufferPtr, &out
Bytes) == (size_t)-1) {
std::cerr << "编码转换失败" << std::endl;
delete[] outBuffer;
iconv_close(converter);
return "";
}
std::string convertedString(outBuffer, outBufferPtr - outBuffer);
delete[] outBuffer;
iconv_close(converter);
return convertedString;
}
这些方法应该能够帮助你解决C++读取文件时的中文乱码问题。根据你的具体情况选择合适的方法进行处理。