我已经在学校CS项目上工作了几周,并且编写了一个基于文本的程序来用C ++管理一家超市。尝试存储数据库并从文件存储中读取数据库时遇到了麻烦。
完整源here
我知道TurboC ++是一个非常过时的编译器,但这是我规定的课程提纲的一部分,因此没有办法。 (非常感谢,下一批将学习python)
我的主要概念是使用自我参照结构作为由类及其功能处理的单链接列表的节点。
struct product //Self referencial structure to store the product details
{
unsigned int code;
char name[100];
char category[40];
unsigned int quantity;
double price;
product *next;
};
class list //Class to handle the linked list of products
{
private:
product *head, *tail;
public:
list()
{
head = NULL; //By default the list will be empty
tail = NULL;
}
void DelList();
void AppProduct(product *, unsigned int);
void AddProduct(unsigned int);
product* FindProduct(unsigned int);
double CalcTotal();
void ListProducts();
void ModProduct(product *);
void SaveToFile();
void LoadFromFile();
product* PointToNewProduct(product);
product* GetProductFromFile(ifstream &);
product* GetHead()
{
return head;
}
void Clear();
};
[store
和cart
是list
类的全局声明对象,存储了单独的链表。
我主要为程序选择了链表格式,并决定仅在以后发现文件处理是项目的必修部分时才添加文件保存和从文件加载。这是我为相同代码编写的代码-
void list::SaveToFile() //self explanatory
{
ofstream fout("DATABASE.DAT", ios::trunc);
product * cur = head;
product temp;
while( cur != NULL )
{
temp = *cur;
fout.write( (char *)&temp, sizeof(product) );
cur = cur->next;
}
fout.close();
}
product * list::PointToNewProduct(product temp) //copy the temp product details into a new pointer and return the pointer
{
product * cur = new product;
cur->code = temp.code;
strcpy(cur->name, temp.name);
strcpy(cur->category, temp.category);
cur->price = temp.price;
cur->quantity = temp.quantity;
cur->next = NULL;
return cur;
}
product * list::GetProductFromFile(ifstream& fin) //retrieve a single product from the given file
{
if( fin.eof() )
return NULL;
product temp;
fin.read( (char *)&temp, sizeof(product) );
cout<<temp.name;
return PointToNewProduct(temp);
}
void list::LoadFromFile() //Function to load struct from file and rebuild the linked list (only returning one item right now)
This is the code I wrote for the same - //Update: I thought I fixed it, but its up to two items now, still not all
{
ifstream fin("DATABASE.DAT", ios::in); //Initialize the stream
head = GetProductFromFile(fin); //initialize head pointer
product * cur = head;
product * nextptr;
do {
nextptr = GetProductFromFile(fin); //get the next product in file
cur = cur->next = nextptr; //link product with the previous product
tail = cur; //make the current pointer the last one
} while( !fin.eof() );
tail->next = NULL;
fin.close();
}
现在我的问题是,尽管我能够正确地将链接列表项写入文件,但是尝试读取它会导致它仅检索2个节点,而不管我已写入文件的节点数如何。
与我的老师进行的一次调试会议使我相信,这是因为从文件加载一个链接列表时,我并没有删除它,并且在写入文件时仍存在未释放内存的问题。我编写的释放内存的析构函数从未被调用过,因为我的对象是全局声明的,这导致我编写了DelList();
函数并在从文件读取之前对其进行了调用。不幸的是,这并没有解决问题。
void list::DelList()
{
product * cur = head, * temp;
while(cur != NULL)
{
temp = cur;
cur = cur->next;
delete temp;
}
delete cur;
delete head;
delete tail;
head = NULL;
tail = NULL;
}
这是我为同一代码编写的代码-我还添加了一些测试代码作为切换案例的选择,在这里我只是从文件中读取而不进行链接,而且它也不显示所需的输出。
case 7:
clrscr();
ifstream fin("DATABASE.DAT", ios::in);
product temp;
fin.seekg(0, ios::beg);
while( fin.read( (char *)&temp, sizeof(product) ) )
{
//fin.read( (char *)&temp, sizeof(product) );
cout<<temp.name<<'\t'<<temp.category<<'\n';
}
getch();
break;
我的代码有什么问题,如何解决?
我设法通过一种解决方法解决了我的问题,尽管我仍然不知道为什么我的原始代码不起作用,尽管看似问题在于读写文件的指针。
我为解决此问题所做的工作是将product
更改为一个从基类prod
继承的类,其中prod
包含与指针所使用的结构相同的内容下一个。然后,我编写了一个函数Delink()
,将链接列表中的每个product
转换为prod
并将其写入文件。然后,在读取文件时,我将读取的每个prod
转换为product
,然后将其链接回以再次构造链接列表。这似乎已经解决了我的问题。