Error occurs when I pass another object to a function -> a.Concat(b);
I have just reverted to C++ from Java for a project. When I pass object by value in this code, then an error occurs. Almost every time it is displaying a different error message, sometimes bad alloc, sometimes displaying half the output. I tried passing by reference and also made a copy constructor but both attempts failed.
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class NFA
{
public:
NFA(string);
NFA(vector<vector<string> >);
NFA Concat(NFA other_nfa);
NFA Union(NFA);
NFA KleeneStar();
void display();
int GetNFASize(){ return ALPHABET_SIZE; }
int getNoOfStates(){ return NO_OF_STATES; }
vector<vector<string> > table;
int ALPHABET_SIZE;
int NO_OF_STATES;
private:
};
NFA::NFA(string input)
{
table.resize(2);
NO_OF_STATES = 2;
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
ALPHABET_SIZE = 3;
}
void NFA::display()
{
for(int i = 0; i < table.size(); i++)
{
for(int j = 0; j < ALPHABET_SIZE; j++)
{
cout << table[i][j] << "\t";
}
cout << endl;
}
}
NFA NFA::Concat(NFA other_nfa)
{
vector<vector<string> > ans_vector;
ans_vector.resize(ALPHABET_SIZE + other_nfa.ALPHABET_SIZE);
for(int i = 0; i < NO_OF_STATES; i++)
{
for(int j = 0; j < ALPHABET_SIZE; j++)
{
ans_vector[i][j] = table[i][j];
}
}
for(int i = other_nfa.NO_OF_STATES - 1; i < other_nfa.NO_OF_STATES; i++)
{
for(int j = 0; j < other_nfa.ALPHABET_SIZE; j++)
{
ans_vector[i][j] = other_nfa.table[i][j];
}
}
ans_vector[NO_OF_STATES - 1][3] = other_nfa.table[0][0];
NFA ansNFA(ans_vector);
}
NFA::NFA(vector<vector<string> >)
{
}
int main()
{
NFA a("a");
a.display();
NFA b("b");
b.display();
NFA ab = a.Concat(b);
system("pause");
return 0;
}
In
NFA::NFA(string input)
{
table.resize(2);
NO_OF_STATES = 2;
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
ALPHABET_SIZE = 3;
}
You variable initializations are out of order. When you use
table[i].resize(ALPHABET_SIZE + 1);
ALPHABET_SIZE contains garbage as you have not set a value yet. Just move ALPHABET_SIZE = 3; before the for loop and you should be okay.
I would also suggest you use a member initialization list for all variables to you can. In this case your constructor would look like
NFA::NFA(string input) : NO_OF_STATES(2), ALPHABET_SIZE(3)
{
table.resize(2);
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
}
You resize a vector<vector<string> but fail to resize any of the contained vectors:
ans_vector.resize(ALPHABET_SIZE + other_nfa.ALPHABET_SIZE);
And then later you index into the nested vectors, which goes out of bounds:
for(int i = 0; i < NO_OF_STATES; i++)
{
for(int j = 0; j < ALPHABET_SIZE; j++)
{
ans_vector[i][j] = table[i][j];
}
}
You'll need to call resize for every vector inside ans_vector, or use push_back, emplace_back etc, which would probably be safer for you.
AlPHABET_SIZE is not defined in:
table[i].resize(ALPHABET_SIZE + 1);
by default, it contains some garbage value. This might be your problem.
NFA::NFA(string input)
{
table.resize(2);
NO_OF_STATES = 2;
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
ALPHABET_SIZE = 3;
}
ALPHABET_SIZE is being used in the ctor of NFA though it was not initialized. it causes weird behaviour.
You are creating three objects a,b,ab. during construction of the object program crashes. it has nothing to do with pass by reference/value or using copy ctor.
From the first look I would say the problem lays in the vector-access of table, which would go out-of-range.
From design-point, several issues:
It seems you _other_nfa can be declared const reference:
NFA NFA::Concat(const NFA& other_nfa)
There is no return. At the end of your Concat method there should be sth. like:
return ansNFA;
It seems within Concat you don't change your member variables like table (which btw. is no good name for a member-variable). If Concat dosn't change the class members, you should declare it const:
NFA NFA::Concat(const NFA& other_nfa) const
Related
I'm just Learning about std::map and its functions . I recently got this problem. I tried making a program which prints out a grid type data where I used std::map for the keys and values . The program prints out fine but I wanted to make a program where once I erased a data in that grid, other data above that should move down one step and the topmost would have 0 in it . somehow I tried but it doesn't seem to work . I don't know where I did wrong in that . My code:
in class header:
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<map>
#define x_Pair std::pair<unsigned int,unsigned int>
class MapCheck
{
public:
std::map<x_Pair, unsigned int>m_MapData;
void SetMapData();
x_Pair GetBlockCell(int num);
void EraseCell(int cell);
};
in class cpp:
void MapCheck::SetMapData()
{
int count = 1;
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
m_MapData[{i, j}] = count;
count++;
}
}
}
x_Pair MapCheck::GetBlockCell(int num)
{
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
if (m_MapData[{i, j}] == num)
{
return x_Pair(i, j);
}
}
}
return x_Pair(-1, -1);
}
void MapCheck::EraseCell(int cell)
{
x_Pair pair = GetBlockCell(cell);
for (int i = pair.second; i < 20; i++)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
m_MapData[{pair.first, i - 1}] = 0;
}
}
-and in main:
#include"MapCheck.h"
int main()
{
MapCheck mc;
mc.SetMapData();
std::string input;
do
{
system("cls");
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
std::cout << mc.m_MapData[{i, j}] << " ";
}
std::cout << std::endl;
}
std::cout << "Enter a number to erase or E to exit";
std::cin >> input;
mc.EraseCell(std::atoi(input.c_str()));
} while (input != "E");
return 0;
}
the output without any inputs :
after entering number 191 in the input :
expected result:
All Except the printing is fine . I dont Get Where I did Wrong. Any help would be appreciated. Thanks in advance!!
The order of
for (int i = pair.second; i < 20; i++)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
m_MapData[{pair.first, i - 1}] = 0;
}
is element found to the bottom. When you want to move everything above the item removed down one slot, this isn't all that useful. So lets flip it around.
for (int i = pair.second; i > 0; i--)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
}
m_MapData[{pair.first, 0}] = 0;
This starts at the item being removed and goes up to slot 1, copying each item down one slot. To handle the top of the column, we have m_MapData[{pair.first, 0}] = 0; to set the top item to zero, something we only need to do once.
Side note: Unless we have a sparse array, this would be a lot more efficient with a 2D array in place of the map.
You have following:
x_Pair MapCheck::GetBlockCell(int num)
which is used as
x_Pair pair = GetBlockCell(cell);
This will invoke copy constructor of std::pair<>.
I think you need to return and use reference:
x_Pair& MapCheck::GetBlockCell(int num)
which is used as
x_Pair& pair = GetBlockCell(cell);
I am trying to use the suggestion from this post to free up time being spent in _platform_memmove$VARIANT$Haswell. According to a time profiler, this is occurring when I send a pointer to several class instances to a function. I have tried changing the way I declare the class instances, changing what the function takes, etc. but have not been able to resolve this.
The chunk of my code that may help:
Inputs *tables = new Inputs(OutputFolder, DataFolder);
ScreenStrat *strat_burnin = new ScreenStrat(ScreenStrat::NoScreen, ScreenStrat::NoScreen,
tables->ScreenStartAge, tables->ScreenStopAgeHIV,
tables->ScreenStopAge, ScreenStrat::NoVaccine);
calibrate *calib_output = new calibrate ();
StateMachine *Machine = new StateMachine();
for (int i = 0; i < n_sims; i++){
calib_output->saved_output[i] = RunCalibration(calib_output->calib_params[i], *strat_burnin, *tables, *Machine);
}
auto ret_val = *calib_output;
delete strat_burnin;
delete tables;
delete Machine;
delete calib_output;
return(ret_val);
and then the function declaration:
vector<double> RunCalibration(vector<double> calib_params, ScreenStrat &strat_burnin, Inputs &tables, StateMachine &Machine)
EDIT
I addressed the points #Botje suggest and it hasn't fixed the problems. Updated code:
void RunCalibration(calibrate &calib, ScreenStrat &strat_burnin, Inputs &tables, StateMachine &Machine, int i);
unique_ptr<calibrate> RunChain(string RunsFileName, string CurKey, string OutputFolder, string DataFolder);
int main(int argc, char* argv[]) {
string DataFolder;
string OutputFolder;
DataFolder = "../Data/";
OutputFolder = "../Output/";
unsigned int run;
string CurKey;
string RunsFileName(DataFolder);
if(argc == 1){
RunsFileName.append("test.ini");
}
else if(argc > 1){
RunsFileName.append(argv[1]);
}
CIniFile RunsFile(RunsFileName);
if (!RunsFile.ReadFile()) {
cout << "Could not read Runs File: " << RunsFileName << endl;
exit(1);
}
CurKey = RunsFile.GetKeyName (0);
if (RunsFile.GetValue(CurKey, "RunType") == "Calibration"){
int totaliters = RunsFile.GetValueI(CurKey, "Iterations");
int n_sims = RunsFile.GetValueI(CurKey, "Simulations");
vector<future<unique_ptr<calibrate>>> futures;
vector<unique_ptr<calibrate>> modeloutputs;
for (run = 0; run < totaliters; run++){
futures.push_back (async(launch::async, RunChain, RunsFileName, CurKey, OutputFolder, DataFolder));
}
for (int i = 0; i < futures.size(); i++){
modeloutputs.push_back (futures[i].get());
} return(0)}
unique_ptr<calibrate> RunChain(string RunsFileName, string CurKey, string OutputFolder, string DataFolder) {
Inputs *tables = new Inputs(OutputFolder, DataFolder);
tables->loadRFG (RunsFileName, CurKey);
tables->loadVariables ();
int n_sims = tables->Simulations;
int n_params = tables->Multipliers.size();
int n_targs = tables->CalibTargs.size();
ScreenStrat *strat_burnin = new ScreenStrat(ScreenStrat::NoScreen, ScreenStrat::NoScreen,
tables->ScreenStartAge, tables->ScreenStopAgeHIV,
tables->ScreenStopAge, ScreenStrat::NoVaccine);
calibrate *calib_output = new calibrate (n_sims, n_params, n_targs);
calib_output->multipliers_names = tables->MultipliersNames;
calib_output->calib_targs_names = tables->CalibTargsNames;
for (int i = 0; i < n_targs; i ++){
calib_output->calib_targs[i] = tables->CalibTargs[i][0];
calib_output->calib_targs_SD[i] = tables->CalibTargs[i][1];
}
for (int i = 0; i < n_params; i++){
for (int j = 0; j < 3; j++){
calib_output->multipliers[i][j] = tables->Multipliers[i][j];
}
}
StateMachine *Machine = new StateMachine();
for (int i = 0; i < n_sims; i++){
RunCalibration(*calib_output, *strat_burnin, *tables, *Machine, i);
}
unique_ptr<calibrate> ret_val = make_unique<calibrate>(*calib_output);
delete strat_burnin;
delete tables;
delete Machine;
delete calib_output;
return(ret_val);
}
void RunCalibration(calibrate &calib, ScreenStrat &strat_burnin, Inputs &tables, StateMachine &Machine, int i){
Adding in Calibrate definition per request from #botje
#include "calibrate.h"
using namespace std;
calibrate::calibrate(int n_sims, int n_params, int n_targs) {
calib_targs.resize (n_targs);
calib_targs_SD.resize (n_targs);
multipliers.resize(n_params);
for(int i = 0; i < n_params; i++){
multipliers[i].resize(3);
}
calib_params.resize (n_sims);
for (int i = 0; i < calib_params.size(); i++){
calib_params[i].resize (n_params);
}
saved_output.resize (n_sims);
for (int i = 0; i < saved_output.size(); i++){
saved_output[i].resize (n_targs);
}
best_params.resize (n_params);
GOF.clear();
tuned_SD.resize(n_params);
}
calibrate::~calibrate(void) {
}
void calibrate::CalculateGOF(int n_sims) {
GOF.push_back (WeightedDistance (saved_output[n_sims][0], calib_targs[0], calib_targs_SD[0]));
for (int i = 1; i < calib_targs.size(); i ++){
GOF[n_sims] += WeightedDistance (saved_output[n_sims][i], calib_targs[i], calib_targs_SD[i]);
}
if (n_sims == 0){
GOF_min = GOF[0];
best_params = calib_params[0];
} else {
auto it = std::min_element(std::begin(GOF), std::end(GOF));
int index = distance(GOF.begin(), it);
GOF_min_run = GOF[index];
if (GOF_min_run < GOF_min){
GOF_min = GOF_min_run;
best_params = calib_params[index];
}
}
}
std::vector<double> calibrate::loadCalibData(int n_params, int n_sim, int tuning_factor) {
if(n_sim == 0){
random_device rd;
mt19937 gen(rd());
for (int i = 0; i < n_params; i ++ ){
uniform_real_distribution<> dis(multipliers[i][0], multipliers[i][1]);
calib_params[n_sim][i] = dis(gen);
}
} else {
tuned_SD = tuningparam (n_sim, n_params, tuning_factor);
for (int i = 0; i < n_params; i ++ ){
calib_params[n_sim][i] = rnormal_trunc (best_params[i], tuned_SD[i], multipliers[i][1], multipliers[i][0]);
}
}
return(calib_params[n_sim]);
}
double calibrate::WeightedDistance(double data, double mean, double SD) {
double distance = pow((data - mean)/(SD * 2),2);
return distance;
}
double calibrate::rnormal_trunc(double mu, double sigma, double upper, double lower) {
std::default_random_engine generator;
std::normal_distribution<double> distribution(mu, sigma);
double prob = distribution(generator);
while (prob < lower || prob > upper){
prob = distribution(generator);
}
return(prob);
}
vector<double> calibrate::tuningparam(int n_sims, int n_param, int tuning_factor) {
vector<double> newSD;
for (int i = 0; i < n_param; i++){
newSD.push_back (multipliers[i][2]/pow(tuning_factor,n_sims));
}
return newSD;
}
I improved RunCalibration as follows. Note the comments for further improvement opportunities.
using std::make_unique;
using std::unique_ptr;
void RunCalibration(calibrate &calib, ScreenStrat &strat_burnin, Inputs &tables, StateMachine &Machine, int i);
unique_ptr<calibrate> RunChain(string RunsFileName, string CurKey, string OutputFolder, string DataFolder) {
auto tables = make_unique<Inputs>(OutputFolder, DataFolder);
tables->loadRFG (RunsFileName, CurKey);
tables->loadVariables ();
int n_sims = tables->Simulations;
int n_params = tables->Multipliers.size();
int n_targs = tables->CalibTargs.size();
auto strat_burnin = make_unique<ScreenStrat>(
ScreenStrat::NoScreen, ScreenStrat::NoScreen,
tables->ScreenStartAge, tables->ScreenStopAgeHIV,
tables->ScreenStopAge, ScreenStrat::NoVaccine);
auto calib_output = make_unique<calibrate>(n_sims, n_params, n_targs);
// I don't know the type of these fields, but IF you do not modify them in
// `RunCalibration`, consider making them `shared_ptr<vector<...>>`
// both in `calibrate` and in `Inputs` so you can simply copy
// the pointer instead of the full table.
calib_output->multipliers_names = tables->MultipliersNames;
calib_output->calib_targs_names = tables->CalibTargsNames;
// Same applies here. If you do not modify CalibTargs, make `calib_targs` a shared_ptr
// and only copy by pointer.
for (int i = 0; i < n_targs; i ++){
calib_output->calib_targs[i] = tables->CalibTargs[i][0];
calib_output->calib_targs_SD[i] = tables->CalibTargs[i][1];
}
// and again...
for (int i = 0; i < n_params; i++){
for (int j = 0; j < 3; j++){
calib_output->multipliers[i][j] = tables->Multipliers[i][j];
}
}
auto Machine = make_unique<StateMachine>();
for (int i = 0; i < n_sims; i++){
RunCalibration(*calib_output, *strat_burnin, *tables, *Machine, i);
}
// This will return the unique_ptr without copying.
return calib_output;
}
am new to c++ and am trying to create a burning forest simulator. I have been trying to call a function from the forest class but i dont know how to give it an argument, if anyone could help that would be great here is the code that i have at the moment.
using namespace std;
class ForestSetup
{
private:
const char Tree = '^';
const char Fire = '*';
const char emptySpace = '.';
const char forestBorder = '#';
const int fireX = 10;
const int fireY = 10;
char forest[21][21];
public:
void CreateForest()
{
// this function is to create the forest
for (int i = 0; i < 21; i++) // this sets the value of the rows from 0 to 20
{
for (int j = 0; j < 21; j++) // this sets the value of the columns from 0 to 20
{
if (i == 0 || i == 20)
{
forest[i][j] = forestBorder; // this creates the north and south of the forest border
}
else if (j == 0 || j == 20)
{
forest[i][j] = forestBorder; // this creates the east and the west forest border
}
else
{
forest[i][j] = Tree; // this filles the rest of the arrays with trees
}
}
}
forest[fireX][fireY] = Fire; // this sets the fire in the middle of the grid
}
void ShowForest(char grid[21][21])
{
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 21; j++)
{
cout << grid[i][j];
}
cout << endl;
}
}
};
int main(void)
{
ForestSetup myForest;
myForest.ShowForest();
system("Pause");
return 0;
}
Let's say you have a setOnFire function with the x and y co-ordinates of where you want to start the fire.
public:
setOnFire(int x, int y)
{
// Code to flag that part of the forest on fire
}
In your main, you would call it with
myForest.setOnFire(5,5);
Within the ForestSetup class you just need setOnFire(5,5);
This tutorials point article might help.
I have a class called magicSquare with a constructor and a display function called display. The constructor creates the magic square, and the display function displays the results. In my main function, I created an instance of magicSquare called ms and gave it a value 7. To display it, shouldn't it work if I just did ms.display()?
class magicSquare
{
private:
int size, square;
vector<vector <int> > finalvec;
public:
magicSquare(int a):finalvec(a, std::vector<int>(a))
{
int i = 0;
int j = a/2;
size = a;
square = a * a;
vector<int>vec(a);
vector<vector<int> > finalvec(a,vec);
for (int i = 0; i < size; i++)
{
for (int j = 0; j< size; j++)
cout << finalvec[i][j];
cout << endl;
}
for (int k=0; k < square; ++k)
{
finalvec[i][j] = k;
i--;
j++;
if (k%a == 0)
{
i = i+ 2;
--j;
}
else
{
if (j==a)
j = j- a;
else if (i<0)
i = i+ a;
}
}
}
void display()
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j< size; j++)
cout << finalvec[i][j];
cout << endl;
}
}
};
int main()
{
magicSquare ms(3);
ms.display();
return 0;
}
Your Error
As pointed by #Retired Ninja, the vector > finalvec(a,vec); hide your member variable finalvec, as you redefine it as a new vector...
What can correct it
You could construct your vector inside a Member initializer list like this
magicSquare(int a) : finalvec(a, std::vector<int>(a, 0)) {
/* your constructor */
}
And delete the two line:
vector<int>vec(a);
vector<vector<int> > finalvec(a,vec);
In your code
How to not make this error
Seeing which value are a class member, method parameter or even context variable can be sometime difficult:
What i can recommend you is to do the following:
class member -> m_NAME_OF_YOUR_CLASS_MEMBER
method parameter -> t_NAME_OF_YOUR_METHODE_PARAMETER
context variable -> c_NAME_OF_YOUR_CONTEXT_VARIABLE
by doing this error like you've done is a bit harder to do!
EDIT: After testing your code
I see there's error in it, effectively, the first time you go in that line:
finalvec[i][j] = k;
i > size, so you access further that your vector allow it, which result in a segfault! please repair your code!
hope that can help
I have this code. From main function i twice call sportPrisevinners function and if it is first call of this function it works correctly and I recive correct result, but when i call it second time I recive incorrect result even I pass this function with same arguments. Please help me to solve this problem while it doesn`t make me crasy.
const char* countries[] = {"ru", "gb", "us", "uk", "ch", "de"};
const int countriesCount = 6;
const char* sports[] = {"runing", "swiming", "baseball", "football", "jumping", "kerling"};
const int sportsCount = 6;
enum {
Empty = 0,
Bronse,
Silver,
Gold
};
struct member {
char sport[9];
char country[3];
int points;
int medal;
};
struct members {
member* list;
int count;
};
string medalToStr(int medal)
{
switch (medal) {
case Gold:
return "Gold";
case Silver:
return "Silver";
case Bronse:
return "Bronse";
default:
return "Empty";
}
}
void printMembers(members &list)
{
for (int i = 0; i < list.count ; i++)
cout << /*i << " " <<*/ medalToStr(list.list[i].medal) << " in "
<< list.list[i].sport << " with " << list.list[i].points
<< " from " << list.list[i].country << endl;
}
void generate()
{
ofstream file("members.dat", ios::binary|ios::trunc);
member temp;
for (int i = 0; i < sportsCount ; i++)
for (int j = 0; j < countriesCount ; j++)
{
int count = rand()%5+5;
for (int k = 0; k < count ; k++)
{
strcpy(&temp.sport[0], sports[i]);
strcpy(&temp.country[0], countries[j]);
temp.points = rand()%100;
temp.medal = Empty;
file.write((char*)&temp, sizeof(member));
}
}
file.close();
}
members sportPrisevinners(const char* sport)
{
//reading
ifstream file("members.dat", ios::binary);
member* loaded = new member[60];
int pos = 0;
while (!file.eof())
{
member temp;
file.read((char*)&temp, sizeof(member));
static bool reading = false;
if (strncmp(&temp.sport[0], sport, strlen(sport))==0) {
reading = true;
loaded[pos++] = temp;
} else if (reading) {
break;
}
}
file.close();
//sorting
int count = 3;
for (int i = 0; i < pos-1 ; i++)
{
for (int j = i+1; j < pos ; j++)
if (loaded[i].points<loaded[j].points)
{
member temp = loaded[i];
loaded[i] = loaded[j];
loaded[j] = temp;
}
if (i<count) {
static int last = -1;
if (loaded[i].points==last)
count++;
loaded[i].medal = count-i;
last = loaded[i].points;
} else break;
}
//returning
members result;
result.list = new member[count];
memcpy(result.list, loaded, count*sizeof(member));
/*for (int i = 0; i < count; i++)
result.list[i] = loaded[i];*/
result.count = count;
delete[] loaded;
return result;
}
int main(int /*argc*/, char */*argv*/[])
{
srand(time(0));
generate();
members r = sportPrisevinners(sports[4]);
printMembers(r);
delete[] r.list;
members l = sportPrisevinners(sports[5]);
printMembers(l);
delete[] l.list;
system("pause");
return 0;
}
I suspect it's the static local variables in your function. They won't have the same values on each call to the function, and this could affect the results. The initialization of these variables is performed just once - the first time they come into scope - so each subsequent time the function is called, you pick up the values these variables had last time the function ran.