I have read in multiple places that \n does not flush the buffer when used however in my code, which I will add at the end of this question, it seems to be doing just that or at least it seems that way from the output (maybe something else is going on in the background due to how I am executing my couts?).
Expected Output:
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
What I Get in the CLI:
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
What I want the output to do is remain in place, like those in the expected output example, and just update itself every the time loop in my code executes.
Here is my code:
#include <iostream>
#include <Windows.h>
#include <string>
#include <vector>
#include <random>
#include <thread>
#include <future>
using namespace std; //Tacky, but good enough fo a poc D:
class mLaser
{
public:
mLaser(int clen, float mamt, int time_left)
{
mlCLen = clen;
mlMAmt = mamt;
mCTime_left = time_left;
}
int getCLen()
{
return mlCLen;
}
float getMAmt()
{
return mlMAmt;
}
void setMCOld(int old)
{
mCTime_old = old;
}
void mCycle()
{
int mCTime_new = GetTickCount(); //Get current tick count for comparison to mCOld_time
if (mCTime_old != ((mCTime_new + 500) / 1000)) //Do calculations to see if time has passed since mCTime_old was set
{
//If it has then update mCTime_old and remove one second from mCTime_left.
mCTime_old = ((mCTime_new + 500) / 1000);
mCTime_left -= 1000;
}
cur_time = mCTime_left;
}
int getCTime()
{
return cur_time;
}
int getCTLeft()
{
return mCTime_left;
}
private:
int mlCLen; //Time of a complete mining cycle
float mlMAmt; //Amoung of ore produced by one mining cycle (not used yet)
int cur_time; //The current time remaining in the current mining cycle; will be removing this as it is just a copy of mCTime_left that I was going to use for another possiblity to make this code work
int mCTime_left; //The current time remaining in the current mining cycle
int mCTime_old; //The last time that mCycle was called
};
void sMCycle(mLaser& ml, int i1, thread& _thread); //Start a mining cycle thread
//Some global defines
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> laser(1, 3); //A random range for the number of mlaser entities to use
uniform_int_distribution<> cLRand(30, 90); //A random time range in seconds of mining cycle lengths
uniform_real_distribution<float> mARand(34.0f, 154.3f); //A random float range of the amount of ore produced by one mining cycle (not used yet)
int main()
{
//Init some variables for later use
vector<mLaser> mlasers; //Vector to hold mlaser objects
vector<thread> mthreads; //Vector to hold threads
vector<shared_future<int>> futr; //Vector to hold shared_futures (not used yet, might not be used if I can get the code working like this)
int lasers; //Number of lasers to create
int cycle_time; //Mining cycle time
int active_miners = 0; //Number of active mining cycle threads (one for each laser)
float mining_amount; //Amount of ore produced by one mining cycle (not used yet)
lasers = laser(gen); //Get a random number
active_miners = lasers; //Set this to that random number for the while loop later on
//Create the mlaser objects and push them into the mlasers vector
for (int i = 0; i < lasers; i++)
{
int clength = cLRand(gen);
mlasers.push_back(mLaser(clength, mARand(gen), (clength * 1000)));
//Also push thread obects into mthreads for each laser object
mthreads.push_back(thread());
}
//Setup data for mining cycles
for (int i = 0; i < mlasers.size(); i++)
{
int mCTime_start = GetTickCount(); //Get cycle start time
mlasers.at(i).setMCOld(((mCTime_start + 500) / 1000));
}
//Print initial display for mining cycles
for (int i = 0; i < mlasers.size(); i++)
{
cout << "Mining Laser " << i+1 << " cycle will complete in " << (mlasers.at(i).getCTLeft() + 500) / 1000 << " seconds...\n";
}
while (active_miners > 0)
{
for (int i = 0; i < mlasers.size(); i++)
{
//futr.push_back(async(launch::async, [mlasers, i, &mthreads]{return sMCycle(mlasers.at(i), i + 1, mthreads.at(i)); }));
async(launch::async, [&mlasers, i, &mthreads]{return sMCycle(mlasers.at(i), i + 1, mthreads.at(i)); }); //Launch a thread for the current mlaser object
//mthreads.at(i) = thread(bind(&mLaser::mCycle, ref(mlasers.at(i)), mlasers.at(i).getCLen(), mlasers.at(i).getMAmt()));
}
//Output information from loops
cout << " \r" << flush; //Return cursor to start of line and flush the buffer for the next info
for (int i = 0; i < mlasers.size(); i++)
{
if ((mlasers.at(i).getCTLeft() != 0) //If mining cycle is not completed
{
cout << "Mining Laser " << i + 1 << " cycle will complete in " << (mlasers.at(i).getCTLeft() + 500) / 1000 << " seconds...\n";
}
else //If it is completed
{
cout << "Mining Laser " << i + 1 << " has completed its mining cycle!\n";
active_miners -= 1;
}
}
}
/*for (int i = 0; i < mthreads.size(); i++)
{
mthreads.at(i).join();
}*/
//string temp = futr.get();
//float out = strtof(temp.c_str(),NULL);
//cout << out << endl;
system("Pause");
return 0;
}
void sMCycle(mLaser& ml, int i1,thread& _thread)
{
//Start thread
_thread = thread(bind(&mLaser::mCycle, ref(ml)));
//Join the thread
_thread.join();
}
Per Ben Voigt, it seems that \r cannot be used in the way I am attempting to use it. Does anyone have any other suggestions apart from Matthew's suggestion of clsing the command window each update? Maybe something in Boost or something new to c++11?
Thanks.