How do I make a function that resets a while loop? - c++

I have made a program that outputs 0 3 6 9 12. Now, I want to make a function called reset() that resets the program, so it outputs the same numbers after 12. How do I do that?
#include <iostream>
using namespace std;
void byThrees();
void reset();
int i = 0;
int main()
{
byThrees();
return 0;
}
void byThrees()
{
while(i<13) {
cout << i << ' ';
i += 3;
}
}
void reset()
{
}

Don't use global variables when you can avoid it! And right now, you can avoid it.
No one else wants to use i except byThrees(). And it sounds like you don't want the value of i to persist across runs of byThrees(). So just make it a local variable in the function:
void byThrees()
{
int i = 0;
while(i<13) {
cout << i << ' ';
i += 3;
}
}
Now whenever you want to print your 0, 3, 6, 9, ... series, just call byThrees():
int main() {
byThrees();
std::cout << std::endl; // Add a newline between runs
byThrees();
return 0;
}

Another method to do it, if you want to save memory and just keep one global variable (at least I think this saves memory) is:
#include <iostream>
using namespace std;
int i = 0;
int main()
{
run(); // this function both resets i to 0 and runs byThrees()
return 0;
}
void byThrees()
{
while(i < 13) {
cout << i << ' ';
i += 3;
}
}
void run()
{
i = 0;
byThrees();
}
Basically, whenever you run the function run(), your code will reset the global variable i to 0 and run byThrees() with i being 0 initially. This means that you can repeatedly call run() in your code and every time it will output 0 3 6 9 12.
If what you mean in your post is that you want your code to output 0 3 6 9 12 and then 15 18 21 24 27 on the next call (and so on), you could do something like this:
#include <iostream>
using namespace std;
int i = 0, nextI = 0; // nextI is a variable that stores the next starting position of i
int main()
{
run(); // will output "0 3 6 9 12"
run(); // will output "15 18 21 24 27"
run(); // will output "30 33 36 39 42"
return 0;
}
void byThrees()
{
while(i < nextI + 13) {
cout << i << ' ';
i += 3;
}
nextI += 15; // increases nextI for the next time "run()" is called
}
void run()
{
i = nextI;
byThrees();
}
This code basically keeps track of where the list of numbers left off and continues from there.

Related

default argument overwriting 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()) { ... }

Why does finite recursive behaviour cause a crash ? (free(): invalid pointer)

Below is my code just a function called kk that will be recursively called for 10 times so impossible to cause stack overflow, but it crashes with
Error in `./3': free(): invalid pointer: 0x0000000000602100
Who knows the reason??
string kk(string &s)
{
static int i=0;
s+="q";
i++;
cout<<"i="<<i<<endl;
if(i>=10) return s;
kk(s);
}
int main()
{
string s="wer";
cout<<"s="<<kk(s)<<endl;
}
I guess you forgot to put the return keyword in the last line. By putting it, the code is working without errors
string kk(string &s)
{
static int i=0;
s+="q";
i++;
cout<<"i="<<i<<endl;
if(i>=10) return s;
return kk(s);
}
int main()
{
string s="wer";
cout<<"s="<<kk(s)<<endl;
}
C26444 NO_UNNAMED_RAII_OBJECTS this was causing the problem.
On every return, the temporary object was getting created and deleted.
Modified the code like below:
#include <iostream>
#include <cstdlib>
static int i = 0;
void kk(std::string& s)
{
s += "q";
i++;
std::cout << "i=" << i << std::endl;
if (i >= 10) return ;
kk(s);
}
int main()
{
std::string s = "wer";
kk(s);
std::cout << "s=" << s << std::endl;
}
Output:
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10
s=werqqqqqqqqqq

Retrieving data from vector from a fresh instance returns 0

I am creating an instance after updating records to the vector vecData inside counter.cpp when I am trying to retrieve this data I am getting the value as 0
main.cpp
#include <iostream>
#include "counter.hpp"
#define MAX_PORTS 3
int main()
{
Counter *counter = new Counter(3);
counter->age = 1;
counter->id = 12;
counter->pincode = 123;
std::vector<Counter> counterData(MAX_PORTS);
counter->storeCounterData(counter,1);
counter->storeCounterData(counter,2);
counter->storeCounterData(counter,3);
counter->getCounterData(counterData);
// getCounterData here is not able to retrieve value updated in above vector `vecData`
Counter *count = new Counter(3);
count->getCounterData(counterData);
return 0;
}
counter.cpp
#include "counter.hpp"
#include <iostream>
#include <vector>
Counter::Counter()
{
}
Counter::Counter(int vecSize):vecData(vecSize)
{
}
void Counter::storeCounterData(Counter *counter,int user)
{
vecData[user].age = counter->age;
vecData[user].id = counter->id;
vecData[user].pincode = counter->pincode;
std::cout<<"vector size inside storeCounterData = "<<vecData.size()<<std::endl;
}
void Counter::getCounterData(std::vector<Counter> &counter)
{
counter = vecData;
std::cout<<"vector size inside getCounterData = "<<vecData.size()<<std::endl;
std::vector<Counter>::iterator it;
for( it = vecData.begin(); it != vecData.end(); ++it)
{
std::cout<<vecData[1].age<<std::endl;
std::cout<<vecData[1].id<<std::endl;
std::cout<<vecData[1].pincode<<std::endl;
}
}
counter.hpp
#include <vector>
class Counter
{
private:
std::vector<Counter> vecData; // vectors
public:
Counter();
Counter(int vecSize);
int age, id, pincode;
void storeCounterData(Counter *counter,int user);
void getCounterData(std::vector<Counter> &counter);
};
Output
./a.out vector size inside storeCounterData = 3
vector size inside storeCounterData = 3
vector size inside storeCounterData = 3
vector size inside getCounterData = 3
1 12 123
1 12 123
1 12 123
vector size inside getCounterData = 3
0 0 0
0 0 0
0 0 0
This is C++, don't use macros for constants:
#define MAX_PORTS 3
Use a const variable instead:
const int max_ports = 3;
Why are you creating this variable on the heap?
Counter *counter = new Counter(3);
counter->age = 1;
counter->id = 12;
counter->pincode = 123;
C++ is not Java or C#, don't do that. You are failing to delete those variables, so you leak memory. Don't do that. This is the correct way:
Counter counter(3);
counter.age = 1;
counter.id = 12;
counter.pincode = 123;
Then either change setCounterData to take a reference, or pass in the address of the object:
counter->storeCounterData(&counter,1);
You are indexing into the vector with the values 1, 2 and 3, but the vector only has three elements, so the correct indices are 0, 1, and 2. Doing vecData[user] when user==3 and vecData.size()==3 is a serious bug. Don't do that.
Why are you always accessing vecData[1] instead of using the iterator?
std::vector<Counter>::iterator it;
for( it = vecData.begin(); it != vecData.end(); ++it)
{
std::cout<<vecData[1].age<<std::endl;
std::cout<<vecData[1].id<<std::endl;
std::cout<<vecData[1].pincode<<std::endl;
}
You probably meant this:
std::vector<Counter>::iterator it;
for( it = vecData.begin(); it != vecData.end(); ++it)
{
std::cout<<it->age<<std::endl;
std::cout<<it->id<<std::endl;
std::cout<<it->pincode<<std::endl;
}
Or much simpler:
for (auto& c : vecData)
{
std::cout << c.age << std::endl;
std::cout << c.id << std::endl;
std::cout << c.pincode << std::endl;
}
(And notice how much easier it is to read that with spaces around the << operators).
when I am trying to retrieve this data I am getting the value as 0
The reason you always get 0 printed is because you are getting the data from an un-filled vector that just contains three new Counter objects:
Counter *count = new Counter(3);
count->getCounterData(counterData);
You haven't stored any values in count->vecData[1] so the values you print out are just the default values created by the Counter constructor, which fails to initialize its members:
Counter::Counter()
{
}
This means the member variables are just garbage. You happen to get zeros because your program has only just started so the heap happens to be full of zeros, but it's actually undefined behaviour to read those variables.
Your Counter class needs to initialize those members properly:
class Counter
{
private:
std::vector<Counter> vecData; // vectors
public:
Counter();
Counter(int vecSize);
int age = 0;
int id = 0;
int pincode = 0;
void storeCounterData(Counter *counter,int user);
void getCounterData(std::vector<Counter> &counter);
};

(C++/Qt) thread runs too much

In the example program below, my intention was to print five of same numbers per second, but in actual runtime the numbers are printed too much, sometimes around 10 or so. What is the problem in my code?
QTextStream qout(stdout);
class my_thread : public QThread
{
public:
int n;
my_thread()
{
n = 0;
}
void run()
{
while(n < 10)
{
qout << n++ << endl;
sleep(1);
}
}
};
int main()
{
enum { N_THREADS = 5 }; // N_THREADS = 2 with no problem...
std::array<my_thread, N_THREADS> thread_array;
for (std::array<my_thread, N_THREADS>::iterator it = thread_array.begin(); it != thread_array.end(); ++it)
{
it->start();
}
for (std::array<my_thread, N_THREADS>::iterator it = thread_array.begin(); it != thread_array.end(); ++it)
{
it->wait();
}
return 0;
}
EDIT
I found some interesting behaviour that my program runs just as expected when N_THREADS is 1 or 2; it starts going weird exactly from when N_THREADS equals 3 or more. Why is this so?

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