I have the following code:
//test.cpp
#include <Physical_file.h>
#include <boost\python.hpp>
using namespace boost::python;
using namespace FMS_Physical;
BOOST_PYTHON_MODULE(python_bridge)
{
class_<Physical_file>("pf")
.def("pcreate", &Physical_file::pcreate)
;
}
//physical_file.h
#include <fstream>
#include "tools.h"
using namespace std;
#define FMS_lvl0_DLL_API __declspec(dllexport)
namespace FMS_Physical
{
const int BLOCK_OFFSET = 20 + 4;
const string SUFFIX(".hash");
struct block
{
unsigned int BlockNr;
char filler[20];
char data[1024 - BLOCK_OFFSET];
};
class Physical_file
{
public:
fstream filefl;
string workingDir;
string fileName;
int fileSize;
block currBlock;
block FHBuffer;
bool opened;
string openMode;
/************
functions
************/
FMS_lvl0_DLL_API Physical_file(void);
FMS_lvl0_DLL_API Physical_file(string &FileName, int FileSize, string &Dir = getCurrentPath());
FMS_lvl0_DLL_API Physical_file(string &FileName, string &Type, string &Dir = getCurrentPath());
FMS_lvl0_DLL_API ~Physical_file(void);
void FMS_lvl0_DLL_API pcreate(string &Name, int Size = 1000, string &Dir = getCurrentPath());
void FMS_lvl0_DLL_API pdelete(void);
void FMS_lvl0_DLL_API popen(string &name, string &OpenMode = string("I"), string &Dir = getCurrentPath());
void FMS_lvl0_DLL_API pclose(void);
void FMS_lvl0_DLL_API seekToBlock(unsigned int BlockNr);
void FMS_lvl0_DLL_API WriteBlock(void);
void FMS_lvl0_DLL_API ReadBlock(void);
void FMS_lvl0_DLL_API WriteFH(void);
void FMS_lvl0_DLL_API ReadFH(void);
};
}
//physical_file.cpp
void Physical_file::pcreate(string &Name, int Size, string &Dir)
{
if (Dir.compare("") == 0)
Dir = getCurrentPath();
string fileFullName = Dir + '\\' + Name + SUFFIX;
this->filefl.open(fileFullName.c_str(),ios::in | ios::binary);
if (filefl.is_open())
{
throw new exception((string("in function Physical_file::pcreate, file:") + fileFullName + " exists.").c_str());
}
try{
this->filefl.open(fileFullName.c_str(),ios::binary | ios::out);
this->opened = true;
this->seekToBlock(0);
this->currBlock.BlockNr = 0;
for (int i = 0; i < Size; i++)
{
for (int j = 0; j < sizeof(currBlock.data); j++)
this->currBlock.data[j] = 0;
for (int j = 0; j < sizeof(currBlock.filler); j++)
this->currBlock.filler[j] = 0;
this->WriteBlock();
}
this->pclose();
this->fileName = Name;
this->workingDir = Dir;
this->fileSize = Size;
}
catch(exception e)
{
throw new exception("in Physical_file::pcreate \n" + *e.what());
}
}
Physical_file::Physical_file(void)
{
this->fileName = string("");
this->workingDir = string("");
this->opened = false;
}
(there is some more code, I think its irrelevant to the problem)
when trying to compile I get the following error:
error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'
can anyone explain why this problem happens and how to fix it?
(I'm compiling using vs2010, python27 and the c++ boost libs)
the files physical_file.cpp and physical_file.h are compiled to a dll used by test.cpp
By default, Boost.Python will automatically register to_python conversions for exposed types, such as Physical_file. As such, Boost.Python requires that these types be copyable. In this case, Physical_file is not copyable its filefl members is of a type that is not copyable: fstream.
To resolve this, either:
Determine copy/ownership semantics of filefl, and manage it through a holder object. For example, boost::shared_ptr.
Suppress automatic registration of python conversions by providing boost::noncopyable as a template argument when exposing the Physical_file class.
BOOST_PYTHON_MODULE(python_bridge)
{
boost::python::class_<Physical_file, boost::noncopyable>("pf")
.def("pcreate", &Physical_file::pcreate)
;
}
For more options when exposing a C++ class to Python, refer to the boost::python::class_ documentation.
Related
I'm making my OOP final project and part of it is to make a couple of databases, I'm having trouble with this one.
Every time an Alquiler x is made, it needs to go to the database's vector<Alquiler>, and then stored in a binary file. Problem is that I'm probably managing the sizes wrong because once I add a couple of Alquiler, the array gets filled up with rubbish, always outputting random characters.
Here's the code, I tried to compact it as much as possible and just leave the relevant part. If anyone wants to take a look I'd really appreciate it.
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
struct Date
{
int day, month, year;
};
struct structalquiler
{
int dni, totalq, dep;
int faday, famonth, fayear;
int fdday, fdmonth, fdyear;
vector<string> artlist;
};
class Alquiler {
private:
int a_DNI_Cliente;
int a_Total_Alquiler, a_Deposito;
Date a_Date_Alquiler, a_Date_Devolucion;
vector<string> a_Article_list;
public:
Alquiler ();
Alquiler (int dni, int totalq, int dep, Date fa, Date fd, vector<string> arts);
void save(ofstream &outfile) { // Bin file writing
structalquiler reg;
reg.dni = a_DNI_Cliente;
reg.dep = a_Deposito;
reg.totalq = a_Total_Alquiler;
reg.faday = a_Date_Alquiler.day;
reg.famonth = a_Date_Alquiler.month;
reg.fayear = a_Date_Alquiler.year;
reg.fdday = a_Date_Devolucion.day;
reg.fdmonth = a_Date_Devolucion.month;
reg.fdyear = a_Date_Devolucion.year;
reg.artlist = a_Article_list;
int wo_size = sizeof(reg) - sizeof(reg.artlist);
outfile.write((char*)®, wo_size);
int size = reg.artlist.size(); // Writing of the vector<string>
outfile.write((char*)&size, sizeof(int));
for (int i = 0; i < size; i++)
{
int letter_amount = reg.artlist[i].length();
outfile.write((char*)&letter_amount, sizeof(int));
outfile.write(reg.artlist[i].c_str(), letter_amount);
}
}
void read(ifstream &infile) { // Reading of the file
structalquiler reg;
int wo_size = sizeof(reg) - sizeof(reg.artlist);
infile.read((char*)®, wo_size);
a_DNI_Cliente = reg.dni;
a_Deposito = reg.dep;
a_Total_Alquiler = reg.totalq;
a_Date_Alquiler.day = reg.faday;
a_Date_Alquiler.month = reg.famonth;
a_Date_Alquiler.year = reg.fayear;
a_Date_Devolucion.day = reg.fdday;
a_Date_Devolucion.month = reg.fdmonth;
a_Date_Devolucion.year = reg.fdyear;
// a_Article_list = reg.artlist;
vector<string> v; // Reading of the vector<string>
int read_size;
infile.read((char*)&read_size, sizeof(int));
for (int i = 0; i < read_size; i++)
{
int letter_amount;
infile.read((char*)&letter_amount, sizeof(int));
char* buffer = new char[letter_amount + 1];
infile.read(buffer, letter_amount);
buffer[letter_amount] = '\0';
v.push_back(string(buffer));
delete [] buffer;
}
a_Article_list = v;
}
};
Alquiler::Alquiler(){}
Alquiler::Alquiler(int dni, int totalq, int dep, Date fa, Date fd, vector<string> arts)
: a_DNI_Cliente(dni), a_Total_Alquiler(totalq), a_Deposito(dep), a_Date_Alquiler(fa), a_Date_Devolucion(fd), a_Article_list(arts) {}
class Database {
private:
string m_file_name = "alquileres.dat";
vector<Alquiler> Arreglo_Alquileres;
public:
Database() { // storing in the vector<Alquiler>
ifstream infile(m_file_name.c_str(), ios::binary|ios::ate);
if (infile.is_open())
{
int size = infile.tellg();
int cant = size / sizeof(structalquiler);
Arreglo_Alquileres.resize(cant);
infile.seekg(0);
for (int i = 0; i < cant; i++)
{
Arreglo_Alquileres[i].read(infile);
}
infile.close();
}
}
void add(const Alquiler &x) {
Arreglo_Alquileres.push_back(x);
write();
}
bool write() {
ofstream outfile(m_file_name.c_str(), ios::binary|ios::trunc);
if (!outfile.is_open()) return false;
int cant = Arreglo_Alquileres.size();
for (int i = 0; i < cant; i++)
{
Arreglo_Alquileres[i].save(outfile);
}
outfile.close();
return true;
}
};
int main() {
Database base;
vector<string> v = {"panuelo", "alpargatas", "chaleco"};
Alquiler x(9,8,7,{6,5,4},{3,2,1},v);
base.add(x);
return 0;
}
Any help is appreciated.
I used a debugger to check your code as is step by step. And then I used a hex-editor to show the output.
And the result is: Your code, as shown, works fine.
But, if you use longer strings, then the std::vector in the structalquiler will have a variable length.
If you now want to read back the data, then you cannot calculate the number of elements from the filesize.
Example for Hex file after running the program as shown one time:
You can see that there is a padding of one int after the 9 data ints. But assuming that the program runs in the same environment, there should be no problem.
And this codes works fine. So, running the program 3 times it will give:
But now: What if we have longer string, then, we could get a file like this:
So, int cant = size / sizeof(structalquiler); will not work any longer.
The solution is to read the file, record for record, until all data from the file will be consumed.
I will show you a quick fix, but you should consider a redesign.
The following will work:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
struct Date
{
int day, month, year;
};
struct structalquiler
{
int dni, totalq, dep;
int faday, famonth, fayear;
int fdday, fdmonth, fdyear;
vector<string> artlist;
};
class Alquiler {
private:
int a_DNI_Cliente;
int a_Total_Alquiler, a_Deposito;
Date a_Date_Alquiler, a_Date_Devolucion;
vector<string> a_Article_list;
public:
Alquiler();
Alquiler(int dni, int totalq, int dep, Date fa, Date fd, vector<string> arts);
void save(ofstream& outfile) { // Bin file writing
structalquiler reg;
reg.dni = a_DNI_Cliente;
reg.dep = a_Deposito;
reg.totalq = a_Total_Alquiler;
reg.faday = a_Date_Alquiler.day;
reg.famonth = a_Date_Alquiler.month;
reg.fayear = a_Date_Alquiler.year;
reg.fdday = a_Date_Devolucion.day;
reg.fdmonth = a_Date_Devolucion.month;
reg.fdyear = a_Date_Devolucion.year;
reg.artlist = a_Article_list;
int sss1 = sizeof(reg);
int sss2 = sizeof(reg.artlist);
int wo_size = sizeof(reg) - sizeof(reg.artlist);
outfile.write((char*)®, wo_size);
int size = reg.artlist.size(); // Writing of the vector<string>
outfile.write((char*)&size, sizeof(int));
for (int i = 0; i < size; i++)
{
int letter_amount = reg.artlist[i].length();
outfile.write((char*)&letter_amount, sizeof(int));
outfile.write(reg.artlist[i].c_str(), letter_amount);
}
}
void read(ifstream& infile) { // Reading of the file
structalquiler reg;
int wo_size = sizeof(reg) - sizeof(reg.artlist);
if (infile.read((char*)®, wo_size)) {
a_DNI_Cliente = reg.dni;
a_Deposito = reg.dep;
a_Total_Alquiler = reg.totalq;
a_Date_Alquiler.day = reg.faday;
a_Date_Alquiler.month = reg.famonth;
a_Date_Alquiler.year = reg.fayear;
a_Date_Devolucion.day = reg.fdday;
a_Date_Devolucion.month = reg.fdmonth;
a_Date_Devolucion.year = reg.fdyear;
// a_Article_list = reg.artlist;
vector<string> v; // Reading of the vector<string>
int read_size;
infile.read((char*)&read_size, sizeof(int));
for (int i = 0; i < read_size; i++)
{
int letter_amount;
infile.read((char*)&letter_amount, sizeof(int));
char* buffer = new char[letter_amount + 1];
infile.read(buffer, letter_amount);
buffer[letter_amount] = '\0';
v.push_back(string(buffer));
delete[] buffer;
}
a_Article_list = v;
}
}
};
Alquiler::Alquiler() {}
Alquiler::Alquiler(int dni, int totalq, int dep, Date fa, Date fd, vector<string> arts)
: a_DNI_Cliente(dni), a_Total_Alquiler(totalq), a_Deposito(dep), a_Date_Alquiler(fa), a_Date_Devolucion(fd), a_Article_list(arts) {}
class Database {
private:
string m_file_name = "r:\\alquileres.dat";
vector<Alquiler> Arreglo_Alquileres;
public:
Database() { // storing in the vector<Alquiler>
ifstream infile(m_file_name.c_str(), ios::binary | ios::ate);
if (infile.is_open())
{
int size = infile.tellg();
int ss2 = sizeof(structalquiler);
int cant = size / sizeof(structalquiler);
//Arreglo_Alquileres.resize(cant);
infile.seekg(0);
while (infile) {
Arreglo_Alquileres.push_back({});
Arreglo_Alquileres.back().read(infile);
}
if (not infile) Arreglo_Alquileres.pop_back();
infile.close();
}
}
void add(const Alquiler& x) {
Arreglo_Alquileres.push_back(x);
write();
}
bool write() {
ofstream outfile(m_file_name.c_str(), ios::binary | ios::trunc);
if (!outfile.is_open()) return false;
int cant = Arreglo_Alquileres.size();
for (int i = 0; i < cant; i++)
{
Arreglo_Alquileres[i].save(outfile);
}
outfile.close();
return true;
}
};
int main() {
Database base;
vector<string> v = { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", "alpargatas", "chaleco" };
Alquiler x(9, 8, 7, { 6,5,4 }, { 3,2,1 }, v);
base.add(x);
return 0;
}
I create an object and try to pass that object through multiple function by reference
#include<iostream>
#include <string>
#include "DBMS.h"
using namespace std;
void Home(DBMS &);
int main()
{
DBMS dbms();
Home(dbms); // this is where the error is
return 0;
}
void Home(DBMS &dbms)
{
string dbName;
dbms.addDatabase(dbName);
}
and this is DBMS.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "Database.h"
using namespace std;
class DBMS
{
public:
DBMS();
void addDatabase(string);
Database& getDatabase(string);
Database& getDatabaseByIndex(int);
int getDatabaseIndex(string);
void removeDatabase(string);
int size();
~DBMS();
private:
vector <Database> dbList;
string error;
};
DBMS::DBMS()
{
}
void DBMS::addDatabase(string tbNames)
{
vector<string> TB_Names = tokenize(tbNames);
int size = TB_Names.size();
for (int i = 0; i < size; i++)
{
if (getDatabaseIndex(TB_Names[i]) == -1)
{
Database tb(TB_Names[i]);
dbList.push_back(tb);
}
else
throw "Already esited Database with given name";
}
}
Database& DBMS::getDatabase(string tbName)
{
int i;
int size = dbList.size();
for (i = 0; i < size; i++)
{
if (dbList[i].getName() == tbName)
return dbList[i];
}
throw invalid_argument("Database not found");
}
Database& DBMS::getDatabaseByIndex(int index)
{
return dbList[index];
}
void DBMS::removeDatabase(string TB_Name)
{
int i;
int size = dbList.size();
for (i = 0; i < size; i++)
{
if (dbList[i].getName() == TB_Name)
{
dbList.erase(dbList.begin() + i);
break;
}
}
if (i == size)
throw invalid_argument("Field not found");
}
int DBMS::getDatabaseIndex(string TB_Name)
{
int size = dbList.size();
for (int i = 0; i < size; i++)
{
if (dbList[i].getName() == TB_Name)
return i;
}
return -1;
}
int DBMS::size()
{
return dbList.size();
}
DBMS::~DBMS()
{
}
(Database type is just another class i create. Nothing special about it. Don't worry about it (Unless you think I have to))
The error statement is : >a reference of type "DBMS &" (a non-const-qualified) cannot be initialized with an value of "DBMS()"
I found a suggestion that i should fix void Home(DBMS &dbms) to void Home(const DBMS &dbms)
but if i do that, i can't use addDatabase() function
How can i fix this?
This declaration
DBMS dbms();
is a vexing parse. You are not declaring a variable named dbms, but instead you are actually declaring a function named dbms that takes no arguments, and returns a DBMS. Passing this object to a function expecting a DBMS object will not work.
You can fix this with:
DBMS dbms{};
I'm working to create a few classes that work together to simulate functions for a rental car agency. I have the classes working and I can create objects of each of the classes, but when I try to run the following code I get a segmentation fault and I'm not sure why. Why am I getting a segmentation fault when I declare the objects in this order?
I've tried switching the order in which I declare the objects and the error goes away. If I declare two cars with just the Car() constructor, then the problem also goes away. If I remove any of the functions in either the Car or Sensor class, the error goes away.
PS: I asked this question a few days ago, and I included way too much code because I couldn't identify the error (far from complete, minimal, and verifiable), but this time I've narrowed it down as far as I can. I apologize if it's a lot of code, but I've removed all the code I can and if I remove any more of it the problem goes away.
Here's my main file:
#include "Car.h"
int main() {
char make[] = "Subaru", model[] = "Outback", name[] = "Brandon",
type[] = "radar";
Sensor sensors[3];
Sensor sensor1 = Sensor(type), sensor2 = Sensor(), sensor3 =
Sensor();
sensors[0] = sensor1;
sensors[1] = sensor2;
sensors[2]= sensor3;
Car car1 = Car();
Car car2 = Car(make, 155.81, sensors);
return 0;
}
My Car class:
#ifndef CAR_H
#define CAR_H
#include <iostream>
#include "MyString.h"
#include "Sensor.h"
using namespace std;
#define MAX_STR_SIZE 256
#define MAX_NUM_SNSRS 3
class Car {
public:
Car();
Car(char* make, float baseprice, Sensor* sensors);
void setMake(char* make);
void setBaseprice(float baseprice);
void setAvailable(bool available);
void setOwner(char* owner);
void updatePrice();
private:
char m_make[MAX_STR_SIZE];
Sensor m_sensors[MAX_NUM_SNSRS];
int m_numsensors;
float m_baseprice;
float m_finalprice;
bool m_available;
char m_owner[MAX_STR_SIZE];
};
#endif
#include "Car.h"
Car::Car() {
char dflt[] = {'\0'};
setMake(dflt);
setAvailable(true);
setOwner(dflt);
m_numsensors = 0;
setBaseprice(0.0);
}
Car::Car(char* make, float baseprice, Sensor* sensors) {
char dflt[] = {'\0'};
setMake(make);
setAvailable(true);
setOwner(dflt);
for(int i = 0; i < MAX_NUM_SNSRS; i++) {
(*(m_sensors + i)) = Sensor(*(sensors + i));
if(myStringCompare((sensors + i)->getType(), "none") != 0) {
m_numsensors++;
}
}
setBaseprice(baseprice);
}
void Car::setMake(char* make) {
myStringCopy(m_make, make);
}
void Car::setBaseprice(float baseprice) {
m_baseprice = baseprice;
updatePrice();
}
void Car::setAvailable(bool available) {
m_available = available;
}
void Car::setOwner(char* owner) {
myStringCopy(m_owner, owner);
}
void Car::updatePrice() {
float totSnsrPrice = 0.0;
for(int i = 0; i < m_numsensors; i++) {
totSnsrPrice += (m_sensors + i)->getCost();
}
m_finalprice = m_baseprice + totSnsrPrice;
}
My Sensor class:
#ifndef SENSOR_H
#define SENSOR_H
#include "MyString.h"
#define MAX_STR_SIZE 256
#define NUM_TYPES 5
class Sensor {
public:
Sensor();
Sensor(char* type);
char* getType();
float getCost();
void setType(char* type);
void setCost(float extraCost);
private:
char m_type[MAX_STR_SIZE];
float m_extracost;
};
#endif
#include "Sensor.h"
const char* validSensors[] = {"gps", "camera", "lidar", "radar",
"none"};
const float prices[] = {5.0, 10.0, 15.0, 20.0, 0.0};
Sensor::Sensor() {
char dflt[] = "none";
setType(dflt);
setCost(0.0);
}
Sensor::Sensor(char* type) {
int index = -1;
char dflt[] = "none";
for(int i = 0; i < NUM_TYPES; i++) {
if(myStringCompare(type, *(validSensors + i)) == 0) {
index = i;
}
}
if(index < 0) {
setType(dflt);
setCost(0.0);
} else {
setType(type);
setCost(*(prices + index));
}
}
char* Sensor::getType() {
return m_type;
}
float Sensor::getCost() {
return m_extracost;
}
void Sensor::setType(char* type) {
myStringCopy(m_type, type);
}
void Sensor::setCost(float extracost) {
m_extracost = extracost;
}
myStringCopy and myStringCompare are just the typical std::string copy and compare functions, we're just not allowed to use them (they are include in MyString.h, I've been using them for a while, so I know they work as intended).
I expect the output to be nothing, but still successful, instead of a segmentation fault. I cannot find the error anywhere, any help would be appreciated. Thanks!
Edit: Here's my string class, as asked:
#ifndef MYSTRING_H
#define MYSTRING_H
int myStringCompare(const char* str1, const char* str2);
char* myStringCopy(char* destination, const char* source);
#endif
#include "MyString.h"
int myStringCompare(const char* str1, const char* str2) {
int index = 0;
while(*(str1 + index) != '\0' || *(str2 + index) != '\0') {
if(*(str1 + index) < *(str2 + index)) {
return -1;
}
if(*(str1 + index) > *(str2 + index)) {
return 1;
}
index++;
}
return 0;
}
char* myStringCopy(char* destination, const char* source) {
int index = 0;
while(*(source + index) != '\0') {
*(destination + index) = *(source + index);
index++;
}
*(destination + index) = '\0';
return destination;
}
We don't have the full details on your string class, so this is hard to reproduce.
However, when you call sensors[0] = sensor1; you are copying your Sensor, but haven't defined an assignment operator (or copy constructor for that matter).
You also do this in the Car constructor with
(*(m_sensors + i)) = Sensor(*(sensors + i));
Now without the full details of your string class, I can give suggestions that might help.
First, you are doing a lot of copying when you set up the senors.
You can collapse this
Sensor sensors[3];
Sensor sensor1 = Sensor(type), sensor2 = Sensor(), sensor3 =
Sensor();
sensors[0] = sensor1;
sensors[1] = sensor2;
sensors[2]= sensor3;
down to
Sensor sensors[3]={{type}, {}, {}};
This might not solve the problem, but is less to look at.
Next, remove the setters. You can use delegating constructors to tie the two you have together, and avoid these.
This avoids some copies.
Look very carefully at what gets deep or shallow copied.
If you have two char * types,
char * word = "Hello";
char * another_word = word;
the second is a "shallow" copy. You need an equivalent of strcpy to actually make a different ("deep") copy of the string.
i want to access the seating[row][col].getFirstName but with the following code i am getting an error and the same error in strcmp in the if condition can anyone explain what does it mean
Error C3867 'Guest::getFirstName': non-standard syntax; use '&' to
create a pointer to member
Auditorium.cpp
Auditorium::Auditorium(int rowNum, int columnNum) {
rowNum1 = rowNum;
columnNum1 = columnNum;
Guest** seating =new Guest*[rowNum];
for (int i = 0; i < rowNum; i++)
{
seating[i] = new Guest[columnNum];
Guest();
}
}
bool Auditorium::assignGuestAt(int row,int col, Guest* tempGuest){
if ((strcmp(seating[row][col].getFirstName ,"???")==0)&& (strcmp(seating[row][col].getLastName , "???")==0)) \\ error
{
for (int i = 0; i < row; i++)
{
seating[row][col].getFirstName= tempGuest->getFirstName;\\ error
seating[row][col].getLastName = tempGuest->getLastName;\\ error
return 1;
}
}
else {
return 0;
}
}
Auditorium.h
#include<iostream>
#include "guest.h"
using namespace std;
class Auditorium
{
private:
Guest **seating;
public:
Auditorium(int, int);
Guest* getGuestAt(int, int);
bool assignGuestAt(int, int, Guest *);
bool checkBoundaries(int, int);
void toString();
};
guest.cpp
#include<iostream>
#include"guest.h"
using namespace std;
Guest::Guest()
{
strcpy_s(firstName,"???");
strcpy_s(lastName, "???");
}
char* Guest::getFirstName()
{
return firstName;
}
char* Guest::getLastName()
{
return lastName;
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I am just beginning with programming in c++ (IDE is CodeBlocks).
I wrote two simple classes (Song and Metadata) and testing around with sqlite.
The Problem: My program seems to get insufficient memory: When I start the program it either crashes immediately or the sqlite3_open command returns the error "out of memory". When I test the SQLITE function without any other code, it works!
So this does not work:
#include <iostream>
#include "metadata.h"
#include "Song.h"
#include <cstdio>
#include "sqlite3.h"
using namespace std;
int main()
{
// Without this block it DOES work!
Metadata* tmpMeta = new Metadata("Eiffel 65", "Blue", "Europop");
Song* tmpSong;
tmpSong = new Song();
tmpSong->set_metadata(*tmpMeta);
// end of block
sqlite3 *db;
int rc;
rc = sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
cout << "Result: " << sqlite3_errmsg(db) << '\n';
sqlite3_close(db);
return 0;
}
Please see the Song and Metadata classes attached.
I do not know how to react to this error.
My environment:
- Windows 8, 64 bit
- Code::Blocks 10.05
- Compiler: GNU GCC Compiler
Thank you in advance!
Greetings
Sebastian
Song.h:
#include <iostream>
#include <cstring>
#include "metadata.h"
using namespace std;
class Song {
private:
Metadata metadata;
unsigned int iD;
char filename[400];
public:
//Constructors
Song( Metadata, unsigned int, const char*);
Song( );
//Methods
void set_metadata(Metadata& meta);
void set_id(unsigned int i);
void set_filename(const char* f);
Metadata get_metadata();
unsigned int get_id();
const char* get_filename();
};
Song.cpp:
#include <iostream>
#include "Song.h"
using namespace std;
Song::Song(Metadata m, unsigned int id, const char* f) {
metadata = m;
iD = id;
strncpy(filename, f, sizeof(filename)-1);
filename[sizeof(filename)] = '\0';
}
Song::Song( ) {
Metadata tmpMeta;
metadata = tmpMeta;
iD = 0;
strncpy(filename, "unknown", sizeof(filename) -1);
filename[sizeof(filename)] = '\0';
}
void Song::set_filename(const char* f) {
strncpy( filename, f, sizeof(filename)-1 );
filename[sizeof(filename)] = '\0';
}
void Song::set_id(unsigned int i) {
iD = i;
}
void Song::set_metadata(Metadata& meta) {
metadata = meta;
}
Metadata Song::get_metadata() {
return metadata;
}
const char* Song::get_filename() {
return filename;
}
unsigned int Song::get_id() {
return iD;
}
Metadata.h:
#include <iostream>
#include <cstring>
#ifndef _METADATA_H_
#define _METADATA_H_
using namespace std;
class Metadata {
private:
unsigned int trackNumber;
char artist[20];
char title[20];
unsigned int year;
char genre[20];
char album[20];
public:
Metadata(const char*, const char*, const char*);
const char* get_artist();
const char* get_title();
const char* get_album();
const char* get_genre();
unsigned int get_trackNumber();
unsigned int get_year();
void set_artist(const char*);
void set_title(const char*);
void set_album(const char*);
void set_genre(const char*);
void set_year(unsigned int);
void set_trackNumber(unsigned int);
};
#endif
Metadata.cpp:
#include <iostream>
#include "metadata.h"
Metadata::Metadata(const char* ar, const char* tit, const char* al) {
trackNumber = 0;
year = 0;
strncpy(genre, "unknown", sizeof(genre) -1);
genre[sizeof(genre)] = '\0';
strncpy(artist, ar, sizeof(artist) -1);
artist[sizeof(artist)] = '\0';
strncpy(title, tit, sizeof(title) -1);
title[sizeof(title)] = '\0';
strncpy(album, al, sizeof(album) -1);
album[sizeof(album)] = '\0';
}
const char* Metadata::get_artist() {
return artist;
}
const char* Metadata::get_title() {
return title;
}
const char* Metadata::get_album() {
return album;
}
const char* Metadata::get_genre() {
return genre;
}
void Metadata::set_artist(const char* ar) {
strncpy(artist, ar, sizeof(artist) -1);
artist[sizeof(artist)] = '\0';
}
void Metadata::set_title(const char* tit) {
strncpy(title, tit, sizeof(title) -1);
title[sizeof(title)] = '\0';
}
void Metadata::set_album(const char* al) {
strncpy(album, al, sizeof(album) -1);
album[sizeof(album)] = '\0';
}
void Metadata::set_genre(const char* g) {
strncpy(genre, g, sizeof(genre) -1);
genre[sizeof(genre)] = '\0';
}
void Metadata::set_trackNumber(unsigned int tn) {
trackNumber = tn;
}
void Metadata::set_year(unsigned int y) {
year = y;
}
For starters: All your string termination code is wrong in Metadata.cpp and Song.cpp:
Example:
strncpy(genre, "unknown", sizeof(genre) -1);
genre[sizeof(genre)] = '\0';
The call to strncpy() is correct. The hard-terminator is NOT. it should be:
strncpy(genre, "unknown", sizeof(genre) -1);
genre[sizeof(genre) -1] = '\0';
This is replicated on all your strings. recheck them all. it will surface several side-effects until you fix them. Considering these objects are all heap-allocated, you're corrupting your heap on the improper termination of Song::filename[] and MetaData::albumin[]. Don't just fix those two; fix them all.
Remember. sizeof() returns an octet-count of the field passed. which means char field[N]; will return N. if you already know C/C++ you know arrays are zero-based and therefore field[N-1] is the maximum allowable index.