default argument overwriting c++ - c++

i have a problem that when you make an object and enter arguments into it, for example foo f(0,5,0); the objects default arguments take over and replace the arguemnts i entered when making the object. I hope this makes sense and feel free to leave a comment if I need to change something.
code:
yo.h
class yo {
public:
yo(int Y=0, int Speed=1);
void move(); //where i use the varibles
int getx() { return x;}
private:
int x, y, speed;
};
yo.cpp
yo::yo(int Y, int Speed)
:x(1280), y(Y), speed(Speed)
{}
void yo::move() {
x -= speed;
std::cout << speed << std::endl;
}
main.cpp
std::vector<yo> yos(20);
void spawnYos() {
yo e(340, 5);
yos.push_back(e);
}
int main() {
spawnYos();
while(true) {
for (int i = 0; i != yos.size(); i++) {
yos.at(i).move();
if (yos.at(i).getx() < 0 or yos.at(i).getx() > 1290) {
yos.erase(yos.begin() + i);
}
}
}
return 0;
}
this yos.at(i).move(); prints the default argument (1) while I spesificly said yo e(340, 5); . it should be printing 5.

You start by default constructing 20 yos:
std::vector<yo> yos(20);
All 20 have x = 1280, y = 0 and speed = 1.
You then add one extra with the value you want:
yo e(340, 5);
yos.push_back(e);
You now have 20 default constructed yos + 1 with x = 1280, y = 340 and speed = 5.
From your description, I think you want 20 yo(340, 5) elements. You can create those by adding a yo to copy when constructing your vector of 20 elements:
std::vector<yo> yos(20, {340, 5});
spawnYos() can now be removed and the declaration of yos can be moved into main instead of having a global variable.
Also correct the stepping of i in your for loop. If you erase an element, you will miss the i != yos.size() condition or miss to move() the next element after the erased if you do i++ unconditionally.
Example:
int main() {
std::vector<yo> yos(20, {340, 5});
while(true) {
for (size_t i = 0; i != yos.size();) {
yos.at(i).move();
if (yos.at(i).getx() < 0 or yos.at(i).getx() > 1290) {
yos.erase(yos.begin() + i);
} else {
++i; // only step i if you don't remove an element
}
}
}
return 0;
}
Note: This program has no way of terminating normally. Such programs have undefined behavior so you need to give the program some clean way of exiting. I suggest changing
while(true) { ... }
to
while(!yos.empty()) { ... }

Related

how can i know from where double free or corruption (out) error is coming?

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
#define MAX_WEIGHT 1000000
class Set
{
public:
int * parent;
int * height;
Set(int _n)
{
parent = new int[_n+1];
height = new int[_n+1];
for(int i=0; i<_n+1; i++)
{
parent[i] = i;
height[i] = 0;
}
}
~Set()
{
delete[] parent;
delete[] height;
}
int Find_Set(int _x)
{
while(parent[_x]!=_x)
{
_x = parent[_x];
}
return _x;
}
void Union_Set(int _x, int _y)
{
_x = Find_Set(_x);
_y = Find_Set(_y);
if(_x!=_y)
{
if(height[_x]>height[_y])
parent[_y] = _x;
else if(height[_x]<height[_y])
parent[_x] = _y;
else
{
parent[_y] = _x;
height[_x]++;
}
}
}
};
template<typename WEIGHT_TYPE>
class Graph
{
public:
int vNum; // num of vertices
int eNum; // num of edges
vector<pair<int, WEIGHT_TYPE>> * edges;
Graph(const char * _fileName)
{
FILE * input = fopen(_fileName, "r");
fscanf(input, "%d %d", &vNum, &eNum);
edges = new vector<pair<int, WEIGHT_TYPE>>[vNum];
for(int i=0; i<eNum; i++)
{
int idx1, idx2;
double weight;
fscanf(input, "%d %d %lf", &idx1, &idx2, &weight);
idx1--;
idx2--;
edges[idx1].push_back(make_pair(idx2, weight));
edges[idx2].push_back(make_pair(idx1, weight));
}
}
~Graph()
{
delete[] edges;
}
};
template<typename WEIGHT_TYPE>
WEIGHT_TYPE Kruskal(Graph<WEIGHT_TYPE> &_graph)
{
vector<pair<WEIGHT_TYPE, pair<int, int>>> k;
for(int i=0; i<_graph.vNum; i++)
{
for(int j=0; j<_graph.edges[i].size(); j++)
{
if(_graph.edges[i][j].second==-1)
continue;
if(i<_graph.edges[i][j].first)
k.push_back(make_pair(_graph.edges[i][j].second, make_pair(i, _graph.edges[i][j].first)));
}
}
sort(k.begin(), k.end());
WEIGHT_TYPE cost = (WEIGHT_TYPE)0;
Set s(_graph.vNum);
for(int i=0; i<k.size(); i++)
{
int idx1 = k[i].second.first;
int idx2 = k[i].second.second;
WEIGHT_TYPE weight = k[i].first;
if(s.Find_Set(idx1) != s.Find_Set(idx2))
{
s.Union_Set(idx1, idx2);
cost += weight;
}
}
return cost;
}
template<typename WEIGHT_TYPE>
WEIGHT_TYPE Second(Graph<WEIGHT_TYPE> _graph)
{
WEIGHT_TYPE cost = (WEIGHT_TYPE)INT_MAX;
WEIGHT_TYPE cost2 = (WEIGHT_TYPE)INT_MAX;
WEIGHT_TYPE result = (WEIGHT_TYPE)INT_MAX;
for(int from=0; from<_graph.eNum; from++)
{
for(int i=0; i<_graph.edges[from].size(); i++)
{
int to = _graph.edges[from][i].first;
for(int j=0; j<_graph.edges[to].size(); j++)
{
if(_graph.edges[to][j].first==from)
{
int tmp1 = _graph.edges[from][to].second;
int tmp2 = _graph.edges[to][j].second;
_graph.edges[from][to].second = -1;
_graph.edges[to][j].second = -1;
result = Kruskal(_graph);
printf("RESULT : %d\n", result);
if(result<cost)
{
cost2 = cost;
cost = result;
}
else if(result>cost && result<cost2)
{
cost2 = result;
}
_graph.edges[from][to].second = tmp1;
_graph.edges[to][j].second = tmp2;
printf("SECOND : %d\n", cost2);
}
}
}
}
return cost2;
}
int main(int argc, char **argv)
{
Graph<int> g(argv[1]);
//int cost = Kruskal<int>(g);
int cost2 = Second<int>(g);
printf("cost2: %d\n", cost2);
FILE * output = fopen(argv[2], "w");
fprintf(output, "%d", cost2);
}
well I have this code and my input file as
7 12
1 2 8
1 3 5
2 3 10
2 4 2
2 5 18
3 4 3
3 6 16
4 5 12
4 6 30
4 7 14
5 7 4
6 7 26
I searched the web for this error and found out that it's caused when you delete a free a memory that was never allocated or already deleted or freed from memory. But I don't see any part of my code that frees or delete those kind of empty memory.. I also tried to use GDB but due to my poor knowledge, i just figured out that it was caused at Kruskal() in Second() in main().... nothing else.. So what i want to know is which in my code causes the error and how can i track it?
You are not observing the rule of 5: If you manually define any of the five special member functions (destructor, copy constructor, move constructor, copy assignment, move assignment), you should define all five explicitly because the auto-generated ones are most likely wrong.
This is exactly the case here:
Your class has an implicitly-defined copy constructor (which copies the pointer member). You invoke this copy constructor when you call WEIGHT_TYPE Second(Graph<WEIGHT_TYPE> _graph) - the argument is copied. Now you have two copies of the same Graph, both with a pointer to the same array of vector. The one that goes out of scope first (at the end of Second) will delete[] that pointer... But eventually the program ends, the Graph in main will go out of scope and will delete[] the pointer again! That's a double free.
This is why you should aim to follow the rule of zero: Never do explicit resource management. Don't use new and delete, use smart pointers or container classes. The compiler will auto-generate the correct operations (and forbid those that make no sense - if your class has explicit ownership of a pointer, i.e. std::unique_ptr, it cannot be copied).
Further reading: https://en.cppreference.com/w/cpp/language/rule_of_three
To fix memory issues there are couple tools:
Address sanitizer - best supported by clang and gcc
valgrind - good to, but slow, works on gcc and clang
electric fence
many others
As you you are writing Grpah and you have memory issues, this cppCon is a must for you.
In general
do not use raw pointers and manual memory management at all.
use std::unique_ptr and raw pointer as weak counterpart
or use std::shared_ptr and std::weak_ptr
If you use this rules that rule of zero will do the job in most cases.
Note that Herb Sutter present also a concept of container which can do a graphs. It has some sort of garbage collection, here is his repo.

How do I return value to main function without directly calling the function

I have multiple functions in my program. Each function has some conditions. If conditions are met, then it passes on the value to another function which again checks the value with some conditions, modifies it.
The first function [named 'squarefree()'] is called from main [obviously] and it further goes on to call another function which in course calls another function untill the process stops at last function named 'end()'. Like this:
#include <iostream>
using namespace std;
int squarefree(int n);
int goodnumber(int sf);
int end(int gn);
int main() {
// your code goes here
int l,r;
cin>>l;
cin>>r;
for(int p=l;p<=r;p++)
{squarefree(p);}
/*int ret=end(int gn); PROBLEM LIES HERE
cout<<ret; */
return 0;
}
int squarefree(int n){
int i;
for(int i=2;i<n;i++)
{
if((n%(i*i))==0)
{
cout<<"number not square free"<<endl;
break;
}
else{
cout<<"number square free"<<endl;
goodnumber(n);
break;
}
}
return 0;
}
int goodnumber(int sf){
cout<<"Sf is:"<<sf<<endl;
int s=0,c=0,flag=0;
for(int j=1;j<=sf;j++)
{
if(sf%j==0)
{
s+=j;
for(int k=2;k<=j/2;++k)
{
if(j%k==0)
{
c++;
}
}
}
}
cout<<"s is:"<<s<<endl;
cout<<"no.of prime numbers dividin s are:"<<c<<endl;
for(int l=2;l<=c/2;++l)
{
if(c%l==0)
{
flag=1;
break;
}
}
if (flag==0)
{cout << "C is a prime number, so this is good number and needs to be passed to next function"<<endl;
end(s);
}
else
{cout << "C is not a prime number"<<endl;
}
return 0;
}
int end(int gn)
{
int sum=0;
sum+=gn;
cout<<"SUm of factors of the good number is:"<<sum<<endl;
return sum;
}
The 'end()' function returns a value sum. Now I want this value sum to be updated everytime the for loop in main() function runs. For example: Sum in first iterations is 5, sum is 2nd iteration is 10, so total sum gets 15 and so on.
If somehow, the value returned by end function can be fetched into main function, that would be great.
Look at all those int-returning functions that are always returning 0. You might be able to take advantage of that.
A trivial example:
#include <iostream>
int step3(int val)
{
return val * val;
}
int step2(int val)
{
return step3(val + 1);
}
int step1(int val)
{
return step2(val * 2);
}
int main()
{
std::cout << step1(1);
}
But take care. You might find a case where you don't get any valid results and need to inform the caller that no result was found.
In addition to the idea of having the functions return the result of the next stage in the pipeline, which is an excellent idea, you can pass the address of the variable in which to store the result (allowing you to return more than one result, or an error code), or store the result of each stage in a temporary variable and return that (allowing you to use a result in more than one computation). I would advise against using a global variable to bypass the stack; it’s considered poor practice.
Some Examples:
// Returning the result of the next stage in the pipeline:
int g(int);
int f(int x)
{
return g(x);
}
// Passing a variable by reference:
enum errcode { success, failure };
errcode sqr( int input, int& output )
{
output = input * input; // This modifies the second variable the caller gave.
return success;
}
// Storing in a temporary variable:
int stage2(int);
int stage1(int x)
{
const int y = stage2(x); // Store the result in a temporary.
const int z = sqr(y);
return z;
}
// Passing results through a global variable is a bad idea:
int necessary_evil = 0; // Declared in global scope; should at least be
// declared static if possible to make it visible only in this source file.
// Namespaces are a fancier way to do something similar.
void kludge(int x)
{
necessary_evil = x * x; // The caller will check the global.
return;
}
There are examples of all of these in the standard library: printf() is essentially a wrapper for vfprintf(), strtol() takes a parameter by reference that the function sets to a pointer to the remainder of the string, and errno is a global variable.

How to limit a decrement?

There is a initial game difficulty which is
game_difficulty=5 //Initial
Every 3 times if you get it right, your difficulty goes up to infinity but every 3 times you get it wrong, your difficulty goes down but not below 5. So, in this code for ex:
if(user_words==words) win_count+=1;
else() incorrect_count+=1;
if(win_count%3==0) /*increase diff*/;
if(incorrect_count%3==0) /*decrease difficulty*/;
How should I go about doing this?
Simple answer:
if(incorrect_count%3==0) difficulty = max(difficulty-1, 5);
But personally I would wrap it up in a small class then you can contain all the logic and expand it as you go along, something such as:
class Difficulty
{
public:
Difficulty() {};
void AddWin()
{
m_IncorrectCount = 0; // reset because we got one right?
if (++m_WinCount % 3)
{
m_WinCount = 0;
++m_CurrentDifficulty;
}
}
void AddIncorrect()
{
m_WinCount = 0; // reset because we got one wrong?
if (++m_IncorrectCount >= 3 && m_CurrentDifficulty > 5)
{
m_IncorrectCount = 0;
--m_CurrentDifficulty;
}
}
int GetDifficulty()
{
return m_CurrentDifficulty;
}
private:
int m_CurrentDifficulty = 5;
int m_WinCount = 0;
int m_IncorrectCount = 0;
};
You could just add this as a condition:
if (user words==words) {
win_count += 1;
if (win_count %3 == 0) {
++diff;
}
} else {
incorrect_count += 1;
if (incorrect_count % 3 == 0 && diff > 5) {
--diff
}
}
For example:
if(win_count%3==0) difficulty++;
if(incorrect_count%3==0 && difficulty > 5) difficulty--;
This can be turned into a motivating example for custom data types.
Create a class which wraps the difficulty int as a private member variable, and in the public member functions make sure that the so-called contract is met. You will end up with a value which is always guaranteed to meet your specifications. Here is an example:
class Difficulty
{
public:
// initial values for a new Difficulty object:
Difficulty() :
right_answer_count(0),
wrong_answer_count(0),
value(5)
{}
// called when a right answer should be taken into account:
void GotItRight()
{
++right_answer_count;
if (right_answer_count == 3)
{
right_answer_count = 0;
++value;
}
}
// called when a wrong answer should be taken into account:
void GotItWrong()
{
++wrong_answer_count;
if (wrong_answer_count == 3)
{
wrong_answer_count = 0;
--value;
if (value < 5)
{
value = 5;
}
}
}
// returns the value itself
int Value() const
{
return value;
}
private:
int right_answer_count;
int wrong_answer_count;
int value;
};
And here is how you would use the class:
Difficulty game_difficulty;
// six right answers:
for (int count = 0; count < 6; ++count)
{
game_difficulty.GotItRight();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// three wrong answers:
for (int count = 0; count < 3; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// one hundred wrong answers:
for (int count = 0; count < 100; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
Output:
7
6
5
Once you have a firm grasp on how such types are created and used, you can start to look into operator overloading so that the type can be used more like a real int, i.e. with +, - and so on.
How should I go about doing this?
You have marked this question as C++. IMHO the c++ way is to create a class encapsulating all your issues.
Perhaps something like:
class GameDifficulty
{
public:
GameDifficulty () :
game_difficulty (5), win_count(0), incorrect_count(0)
{}
~GameDifficulty () {}
void update(const T& words)
{
if(user words==words) win_count+=1;
else incorrect_count+=1;
// modify game_difficulty as you desire
if(win_count%3 == 0)
game_difficulty += 1 ; // increase diff no upper limit
if((incorrect_count%3 == 0) && (game_difficulty > 5))
game_difficulty -= 1; //decrease diff;
}
inline int gameDifficulty() { return (game_difficulty); }
// and any other access per needs of your game
private:
int game_difficulty;
int win_count;
int incorrect_count;
}
// note - not compiled or tested
usage would be:
// instantiate
GameDiffculty gameDifficulty;
// ...
// use update()
gameDifficulty.update(word);
// ...
// use access
gameDifficulty.gameDifficulty();
Advantage: encapsulation
This code is in one place, not polluting elsewhere in your code.
You can change these policies in this one place, with no impact to the rest of your code.

How to push_back an object properly?

Hi I have an issue with pushing back object to a vector of objects.
class boxes {
protected:
int x = 0;
public:
void setx (int input) {
x = input;
}
int getx () {
return x;
}
} box;
box.setx(5);
vector <boxes> tetris;
tetris.push_back(box);
cout << box.getx();
cout << tetris.back().getx();
Why the two prints have different values? The first one is giving me x=5, the second x=0.
If you provide a copy constructor, make sure you implement it correctly. My bug was there.

Class variable resets after function completes

I'm new to C++ from a java/python/etc background, and am trying to teach myself OO programming before I have to take a class on it next semester.
I'm trying to make an animation system using SFML, but am having some trouble with one of my class variables; it keeps resetting to 0 after I increment it. I'll start with the code and follow with a log output I'm using to help figure out what's going on.
SOLUTION: Being new to C++, I was an idiot and returned a new instance of my class in my getter functions; using [class]& func()... instead of [class] func() solved this, but now I have some refactoring to do.
Code (header):
...
typedef std::vector<Frame> frameVect; // (Frame defined above)
typedef std::vector<double> dubVect;
...
class limbAnim
{
private:
int limbNum;
int numFrames;
int curFrame;
frameVect frames;
public:
limbAnim(int limb, int nFrames, frameVect F);
<getters/setters>
void incCurFrame();
dubVect incrementAnimation(dubVect curPos, double curRot);
}
Code (cpp):
... (include vector, ofstream, etc)
std::ofstream AnimLog("log.log")
typedef std::vector<Frame> frameVect; // (Frame defined above)
typedef std::vector<double> dubVect;
...
limbAnim::limbAnim(int limb, int nFrames, frameVect F)
{
limbNum = limb;
curFrame = 0;
numFrames = nFrames;
frames = F;
}
void limbAnim::incCurFrame()
{
curFrame=curFrame+1;
if (curFrame >= numFrames)
{
curFrame = 0;
AnimLog << "Greater than." << std::endl;
}
}
dubVect limbAnim::incrementAnimation(dubVect curPos, double curRot)
{
AnimLog << limbNum << ", " << numFrames << std::endl;
if (numFrames > 0)
{
AnimLog << curFrame << std::endl;
dubVect curStepP = frames[curFrame].getStepPos();
double curStepR = frames[curFrame].getStepRot();
curPos[0] = curPos[0] + curStepP[0];
curPos[1] = curPos[1] + curStepP[1];
curRot = curRot + curStepR;
incCurFrame();
AnimLog << "Incremented: " << curFrame << std::endl;
}
dubVect retV = curPos;
retV.push_back(curRot);
return retV;
}
So, my log output looks good since I'm testing with 2 frames on limbs 6 & 8, except those limbs' curFrame seems to reset to 0 after incrementing:
...
5, 0
6, 2
0
Incremented: 1
7, 0
8, 2
0
Incremented: 1
9, 0
...
5, 0
6, 2
0
Incremented: 1
7, 0
8, 2
0
Incremented: 1
9, 0
...(ad nauseam)
Edit: Code calling the increment function.
(main.cpp)
// (Outside main loop.)
Animation walk_anim(12, "assets/anim/walk.dat");
// (Inside main loop.)
for (int i=0; i<12; i++)
{
dubVect animDat = walk_anim.getLimbFrame(i).incrementAnimation(limbPos[i], curDegs[i]);
dubVect newPos = getDVect(animDat[0], animDat[1]);
double newRot = animDat[2];
curDegs[i] = newRot;
if (curDegs[i] >= 360)
curDegs[i] -=360;
limbPos[i] = newPos;
}
getLimbFrame
Animation::Animation(int lNum, string fName)
{
numLimbs = lNum;
fileName = fName;
// Fill up limbVect with correct # of empty frames.
for (int i=0; i<numLimbs; i++)
{
frameVect emptyFVect;
limbAnim LA(i, 0, emptyFVect);
limbFrames.push_back(LA);
}
// Boring .dat parsing, populates the 'frames' var of each limbAnim.
loadAnim();
}
limbAnim Animation::getLimbFrame(int index)
{
if (index < numLimbs)
{
return limbFrames[index];
}
}
Hopefully you're aware that your functions take arguments by value, so they work on a copy of something.
You carefully avoided to show the really interesting code parts where you call incrementAnimation, most likely it follows the same bad pattern as the other functions.
I suggest reading up on how to pass objects by reference and const reference -- and how function arguments work in C++.
I think you need to declare that member variable, with the static keyword, then you can say it is a class variable, where it will be the shared for every instance of your class. Like this:
static int curFrame;
Then you need to initialize it from outside de class. Have in mind that declaration, is a lot different to initialization.
You can read about it here and here