我遇到了两件事情,首先在我的if语句中选择C它应该从文件中获取所选记录并更改其内容,但由于某些原因文件内容不会改变,它不起作用。同样在选择D我需要它能够从文件中读取并添加所有数量和销售成本并将它们一起添加然后显示它们。我甚至不知道从哪一个开始。我知道我需要从文件中访问信息,但只需要包含这些数据的行,然后将它们一起添加并保存在要显示的变量中,但是如何只访问文件中包含该数据的行?
#include <iostream>
#include <fstream>
#include <string>
#include "stdafx.h"
using namespace std;
struct Info
{
// create inventory items info
string ItemDescription;
int Quantity;
double WholesaleCost;
double RetailCost;
string Date;
};
int main()
{
//make instance of info and a variable for user selection
Info Item;
char choice;
// set up functions
long byteNum(int);
void showRec(Info);
void changeRec(Info);
//open file
fstream inventory("inventory.dat", ios::out | ios::in | ios::binary);
// loop for user selection
do
{
cout << "press 'A' to add files\n";
cout << "press 'D' to display files\n";
cout << "press 'C' to Change files\n";
cout << "press 'G' to Generate a record\n";
cout << "or press 'Q' to quit\n";
cin >> choice;
//if add files get record info put it into struct and save it tofile
if (choice == 'A' || choice == 'a')
{
cout << "enter Item description\n";
cin >> Item.ItemDescription;
cout << "enter quantity on hand\n";
cin >> Item.Quantity;
cout << "enter whole sale cost\n";
cin >> Item.WholesaleCost;
cout << "enter Item retail cost\n";
cin >> Item.RetailCost;
cout << "enter date added to inventory\n";
cin >> Item.Date;
cout << "data added\n";
inventory.write(reinterpret_cast<char *>(&Item), sizeof(Item));
}
//display record
else if (choice == 'D' || choice == 'd')
{
int recordChoice;
// get which record user wants
cout << "enter which record number you want?";
cin >> recordChoice;
// display record info
cout << " here is record " << recordChoice << endl;
inventory.seekg(byteNum(recordChoice), ios::beg);
inventory.read(reinterpret_cast<char *>(&Item), sizeof(Item));
showRec(Item);
}
// change record info
else if (choice == 'C' || choice == 'c')
{
int recordChoice;
//get which record user wants to change
cout << "enter which record number you want to change?";
cin >> recordChoice;
// change struct info and save it over old record in the file
changeRec(Item);
inventory.seekp(byteNum(recordChoice), ios::beg);
inventory.write(reinterpret_cast<char *>(&Item), sizeof(Item));
}
else if (choice == 'G' || choice == 'g')
{
cout << "D";
}
} while (choice != 'Q' || choice != 'q');
inventory.close();
return 0;
}
long byteNum(int recNum)
{
// get record selection number
return sizeof(Info) * recNum;
}
void showRec(Info record)
{
// display record info
cout << record.ItemDescription << endl;
cout << record.Quantity << endl;
cout << record.WholesaleCost << endl;
cout << record.RetailCost << endl;
cout << record.Date << endl;
}
void changeRec(Info record)
{
// change record info in struct
cout << "enter new Item description\n";
cin >> record.ItemDescription;
cout << "enter new quantity on hand\n";
cin >> record.Quantity;
cout << "enter new whole sale cost\n";
cin >> record.WholesaleCost;
cout << "enter new Item retail cost\n";
cin >> record.RetailCost;
cout << "enter new date added to inventory\n";
cin >> record.Date;
cout << "data added\n";
}
答案 0 :(得分:2)
你的班级由一群std::string
(以及其他一些东西组成,但这并不重要)。
std::string
是一个实现类似文本字符串的接口的类。它本身不是一个字符串。通常,std::string
由指向堆分配缓冲区的指针,字符串的大小以及可能的其他元数据组成。
你不必担心这些。您所要做的就是访问std::string
方法,例如substr()
和其他方法,您就可以得到结果。类本身管理其内部元数据,并对其负责。你调用substr()
,该类使用其内部指针来查找字符串的请求部分,并返回它,依此类推。
inventory.write(reinterpret_cast<char *>(&Item), sizeof(Item));
因此,您最终将Item
结构的二进制内容写入文件。其中包括一堆std::string
个。太棒了。您的文件现在包含一些二进制数据,其中包含一堆包含文本字符串的堆分配缓冲区的原始内存地址。它不包含文本字符串本身。
当您稍后阅读它们时,您获得的所有内容都将是相同的原始内存地址。这很好,除了现在,它是一个完全不同的过程,并且一段时间前终止的某些进程使用的原始内存地址......不是很有用。当你试图访问它们时,你的代码就会爆炸,因为所有这些指针现在都是毫无意义的废话。
问自己以下这个简单的问题:你知道你在sizeof(Item)
()调用中写了write
个字节,对吗?而且你知道sizeof(Item)
是一个常量表达式(或者,至少,你的C ++课程中的教师应该首先告诉你的是sizeof
始终是一个常量表达式) 。所以,你需要问自己的问题是,如果Item
结构中的一个字符串是否包含10个字符,或者是1万个字符,那么总是可以写出一些常量字节数是否可能?
不幸的是,这不仅仅是一个write
()和read
()调用。您需要提供一种表示Item
类内容的文件格式,并实现不同的方法将所有字段的内容逐个写入文件,并将其读回。
您对问题的评论已经为您提供了一些谷歌食品。使用它。