Consider the following contrived data type:
Building: int
age, char*
location, float
quality
The location is in the format "XXX-XXX" (exactly 7 characters).
Goal: Serialize the object into a binary format and then deserialize the object to display (on console) the exact same building info as inputed by the user.
For example, suppose the user imputed the building object: age = 45, location = "345-789", quality = "2.3829.
Then the program should display on the console:
age = 45, location = 345-789, quality = 2.3829
Attempt: Although my application works exactly as specified by the goal, I believe there are major inefficiencies in my code. I am asking for feedback directly related to efficiency. Does there exist a more efficient method to accomplish the same goal? This project is for educational purposes and I cannot use any serialization libraries.
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
class Building
{
private:
int m_age; // the age of the building
char m_locationCode[7]; // location is the format:: example "357-278" (exactly 7 characters)
float m_buildingQuality; // the quality of the building (scale from 0 - 1000)
int m_buildingQualityDecimals; // the number of digits after the decimal for building quality
public:
Building(int age, const std::string& loc, const std::string& quality)
{
m_age = age;
for(unsigned i = 0; i < loc.size(); i++)
m_locationCode[i] = loc[i];
char qualityBuffer[10];
int count = 0;
bool hitDecimal = false;
for(int i = 0; i < quality.size(); i++)
{
qualityBuffer[i] = quality[i];
if(quality[i] == '.')
{
hitDecimal = true;
}
if(hitDecimal == true)
count++;
}
m_buildingQuality = atof(qualityBuffer);
m_buildingQualityDecimals = count;
}
int getAge() {return m_age;}
std::string getLoc()
{
std::string toReturn(m_locationCode, 7);
return toReturn;
};
int getDecimals()
{
return m_buildingQualityDecimals;
}
float getQuality()
{
return m_buildingQuality;
}
};
int main()
{
Building b(345, "123-456", "3.23654");
// Serializing
std::ofstream file;
file.open("BinaryBuilding.bin", std::ios::out | std::ios::binary | std::ios::trunc);
file.write((char*) &b, sizeof(b)); // writing file to binary by casting to a char*
file.close();
// Deserialzing
std::ifstream file2;
file2.open("BinaryBuilding.bin", std::ios::in | std::ios::binary);
Building* b2 = new Building(0, "000-000", "0.0");
file2.read((char *) b2, sizeof(*b2));
file2.close();
// Testing process
std::cout << "Age: " << b2->getAge() << "; Loc: " << b2->getLoc() <<
"; Building Quality:" << std::setprecision(b2->getDecimals()) << b2->getQuality() <<std::endl;
delete b2;
return 0;
}
Console Output:
Age: 345; Loc: 123-456; Building Quality: 3.23654
Remarks: Notice that I parse the number of characters after the decimal point as inputted by the user. I think this is inefficient since I must store another int
inside the class. This is slower and increases the size of the binary file. I want to be able to serialize and deserialize this object as fast as possible. I will eventually extend this to parse millions of objects. My professor told me that the location (i.e. XXX-XXX) should not be written as ASCII. How could the task be accomplished without writing the location to ASCII?