【问题标题】:How to write/read classes within classes to binary file C++如何将类中的类写入/读取到二进制文件C++
【发布时间】:2019-04-26 12:49:15
【问题描述】:

我正在做一个项目,我必须编写一个包含其他三个类作为私有成员变量的类到二进制文件,然后可以将其读回变量以在代码中使用。代码写入文件,但我不知道它是否正在写入正确的信息,因为当我尝试读取它读取的垃圾文件时。我已经包含了我当前的设置,这看起来正确吗?如果是这样,可能出了什么问题,如果不是,我该如何解决这个问题?

如果您需要我添加任何额外的代码,请询问。另一个考虑是,用作玩家对象的成员函数的两个类继承自其他类。

    if (cFile.is_open())
    {
        cFile.seekp(ios::beg);
        for (int i = 0; i < 3; i++)
        {
            cFile.write(reinterpret_cast<char *>(&players[i]), sizeof(Character));
        }

        cFile.seekg(ios::beg);
        for (int i = 0; i < 3; i++)
        {
            cFile.read(reinterpret_cast<char *>(&playersRead[i]), sizeof(Character));
            playersRead[i].display();
        }

        cFile.close();
    }
    else
    {
        cout << "Error opening file." << endl;
    }

我已经在这段代码上工作了几天,但确实遇到了麻烦。非常感谢我能得到的任何帮助,在此先感谢。

#pragma once
#include <iostream>
using std::ostream;
#include "string.h"
#include "coinPouch.h"
#include "backpack.h"

class Character
{
public:
	Character();
	Character(String name);
	Character(String name, CoinPouch wallet, Backpack storage);
	Character(const Character & copy);
	~Character();
	Character & operator =(const Character & rhs);

	friend ostream & operator << (ostream & out, const Character & c);

	void purchase(int p, int g, int s, int c);
	void income(int p, int g, int s, int c);
	void addPotion(const Potion & toAdd);
	void checkBalance();
	void checkBackpack();
	void changeName(const String & newN);
	void display();

	String getName();
	CoinPouch getWallet();
	Backpack getStorage();
	void setName(String name);
	void setWallet(CoinPouch wallet);
	void setStorage(Backpack storage);

private:
	String m_name;
	CoinPouch m_wallet;
	Backpack m_storage;

};

#include "character.h"
using std::endl;
using std::cout;

Character::Character() : m_name("Player")
{
	CoinPouch initialW;
	Backpack initialS;
	m_wallet = initialW;
	m_storage = initialS;
}

Character::Character(String name) : m_name(name)
{
	CoinPouch initialW;
	Backpack initialS;
	m_wallet = initialW;
	m_storage = initialS;
}

Character::Character(String name, CoinPouch wallet, Backpack storage) : m_name(name), m_wallet(wallet), m_storage(storage)
{

}

Character::Character(const Character & copy) : m_name(copy.m_name), m_wallet(copy.m_wallet), m_storage(copy.m_storage)
{

}

Character::~Character()
{

}

Character & Character::operator =(const Character & rhs)
{
	if (this != &rhs)
	{
		m_name = rhs.m_name;
		m_wallet = rhs.m_wallet;
		m_storage = rhs.m_storage;
	}

	return *this;
}

ostream & operator << (ostream & out, const Character & c)
{
	out << c.m_name << ": " << endl;
	out << c.m_wallet << endl;
	out << c.m_storage << endl;
	
	return out;
}

void Character::purchase(int p, int g, int s, int c)
{
	m_wallet.buy(p, g, s, c);
}

void Character::income(int p, int g, int s, int c)
{
	m_wallet.add(p, g, s, c);
}

void Character::addPotion(const Potion & toAdd)
{
	m_storage.addPotion(toAdd);
}

void Character::checkBalance()
{
	m_wallet.display();
}

void Character::checkBackpack()
{
	m_storage.displayContents();
}

void Character::changeName(const String & newN)
{
	m_name = newN;
}

void Character::display()
{
	cout << m_name << ": " << endl;
	m_wallet.display();
	m_storage.displayContents();
}

String Character::getName()
{
	return m_name;
}

CoinPouch Character::getWallet()
{
	return m_wallet;
}

Backpack Character::getStorage()
{
	return m_storage;
}

void Character::setName(String name)
{
	m_name = name;
}

void Character::setWallet(CoinPouch wallet)
{
	m_wallet = wallet;
}

void Character::setStorage(Backpack storage)
{
	m_storage = storage;
}

#pragma once
#include <iostream>
using std::ostream;
#include "string.h"

class CoinPouch
{
public:
	CoinPouch();
	CoinPouch(String init);
	CoinPouch(int p, int g, int s, int c);
	CoinPouch(const CoinPouch & copy);
	~CoinPouch();
	CoinPouch & operator = (const CoinPouch & rhs);
	friend ostream & operator << (ostream & out, const CoinPouch & c);
	
	void add(int p, int g, int s, int c);
	bool checkCost(int p, int g, int s, int c);
	void buy(int p, int g, int s, int c);
	void convertCost();
	void roundUp();
	void display();

	int getP();
	int getG();
	int getS();
	int getC();

private:
	String m_amount;

	int m_platinum;
	int m_gold;
	int m_silver;
	int m_copper;
};

#pragma once
#include "potions.h"

class DynamicArray
{
public:
	// Constructors
	DynamicArray();
	~DynamicArray();
	DynamicArray(const DynamicArray & copy);

	// Op Equals
	DynamicArray & operator =(const DynamicArray & rhs);

	// Insert, delete, and get elements functions
	int getElements();
	void Insert(const Potion & add);
	void Delete(const Potion & rmv);
	void display();

	// Overloaded operators
	Potion & operator [](int index);
	friend ostream & operator << (ostream & out, const DynamicArray & d);

private:
	// Member variables
	Potion * m_array;
	int m_elements;

	// Find function
	int Find(const Potion & target);
};

#pragma once
#include "string.h"
#include <iostream>
using std::ostream;

class Potion
{
public:
	// Constructors
	Potion();
	Potion(String name, String description, String potency, String cost);
	Potion & operator = (const Potion & rhs);
	Potion(const Potion & copy);

	// Desctructor
	~Potion();

	// Overloaded operators
	bool operator == (const Potion & rhs) const;
	friend ostream & operator << (ostream & out, const Potion & p);

	// Getter functions
	String getName();
	String getDesc();
	String getPotency();
	String getCost();
	int getP();
	int getG();
	int getS(); 
	int getC();

	// Setter functions
	void setName(String name);
	void setDesc(String desc);
	void setPotency(String potency);
	void setCost(String cost);

	// Convert and display functions
	void convertCost();
	void display();

private:
	// Strings to hold item information
	String m_name;
	String m_description;
	String m_potency;
	String m_cost;

	// Ints to hold cost information
	int m_platinum;
	int m_gold;
	int m_silver;
	int m_copper;

	// Logical test
	bool m_isnull = false;
};

#pragma once
#include <iostream>
using std::ostream;

class String
{
public:
	// Constructors
	String();
	String(char ch);
	String(const char * str);

	// Destructor
	~String();

	// Copy Constructor and Copy Assignment Constructor
	String(const String & copy);
	String & operator=(const String & rhs);
	friend ostream & operator << (ostream & out, const String & s);

	// Added Functionality
	void display();
	void upper();
	void lower();

	// Operator Conversion
	operator char *();
	operator const char *();

	// Overloaded operator
	bool operator == (const String & rhs) const;

private:
	// Member variables
	char * m_str;
	int m_ischar;

};

#pragma once
#include "dynamicarray.h"
#include "coinPouch.h"
#include "string.h"

class Backpack
{
public:
	Backpack();
	Backpack(DynamicArray potions);
	Backpack(const Backpack & copy);
	~Backpack();
	Backpack & operator = (const Backpack & rhs);
	friend ostream & operator << (ostream & out, const Backpack & c);

	void addPotion(const Potion & add);
	void usePotion(const Potion & rm);
	void displayContents();

private:
	DynamicArray m_potions;

	int m_number;
};

这是一个学校项目,我应该将 Character 类写入二进制文件以保存字符,以便在程序启动时加载它们。现在我只是想确保它们可以成功地写入和读取二进制文件,但我没有运气。

我的错,不知道要发布什么,我不想在我的文件中发布所有内容。这是字符类。如果需要,请告诉我还需要什么。

【问题讨论】:

  • 逻辑上不可能确定这是否“看起来正确”,因为显示的代码无法满足 minimal reproducible example 的所有要求,如 stackoverflow.com 的 help center 中所述。任何人都可以为您提供的最佳帮助是建议您阅读 stackoverflow.com 的 help center,将 stackoverflow.com 的 touredit 您的问题包含在 minimal reproducible example 中。
  • 请发帖Character。如果Character 是非 POD 类型,则这些“二进制文件”都不起作用。
  • 如果不清楚 POD 是什么...What Are POD Types in C++
  • 请发帖Character.h。需要查看的是Character 的成员,而不是函数实现。
  • 现在String 是什么? CoinPouch 是什么? BackPack 是什么?从它的外观来看,您的代码都不适用于“二进制读取或写入”。这是学校作业吗?如果您没有被告知执行cFile.write(reinterpret_cast&lt;char *&gt;(&amp;players[i]), sizeof(Character)) 之类的要求是什么,那么您最终会浪费您的时间。

标签: c++ file input io binary


【解决方案1】:

很明显,这段代码不可能工作。

        cFile.write(reinterpret_cast<char *>(&players[i]), sizeof(Character));

不管sizeof(Character) 有多大,我们可以有一个Character 和一个m_name,它占用的字节数比这多。所以这段代码不可能写出角色的名字,它显然需要这样做。

在向文件写入任何内容之前,请在字节级别确定(理想情况下,记录)文件格式。确保您的代码以您记录的格式编写,并且也可以以您记录的格式读取。跳过这一步会导致痛苦,而且还会使调试变得不可能,因为您无法查看文件并将其与规范进行比较,以确定是作者还是读者有问题。

如果您记录了播放器名称将在文件中占用的字节数,您会立即意识到您要么需要一个可变长度对象并以某种方式对长度进行编码,要么选择一个最大大小的名称并分配那么多字节。但是由于您跳过了这一重要步骤,因此您从未真正了解如何Character 写入文件。

【讨论】:

  • 谢谢,我现在感觉很笨。我应该知道动态字符串会导致问题。 o_o
  • @empoweredev 但这并不是真正的问题。问题是您没有决定格式。绳子只是碰巧咬你的一种方式。它也可能以其他方式咬你。
  • 那是我忘记的。我现在设置了文件格式并且文件 I/O 工作顺利,我所需要的只是记住,在写入文件时,动态内存的处理方式必须与普通内存不同。
猜你喜欢
  • 2021-10-18
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2021-08-30
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
相关资源
最近更新 更多