\r 和 \n 或缓冲区刷新的问题
Issues with \r and \n or Buffer Flushing
我在多个地方读到 \n 在使用时不会刷新缓冲区,但是在我的代码中,我将在这个问题的末尾添加,它似乎就是这样做的,或者至少看起来是这样从输出的方式(由于我执行 cout 的方式,可能在后台发生了其他事情?)。
预期输出:
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...
我在 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...
我希望输出保持原样,就像预期输出示例中的那样,并且在我的代码中每次执行时间循环时更新自身。
这是我的代码:
#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();
}
根据 Ben Voigt 的说法,\r 似乎不能按照我尝试使用它的方式使用。除了 Matthew 关于每次更新都关闭命令 window 的建议之外,还有其他建议吗?也许是 Boost 中的某些东西或 c++11 的新东西?
谢谢。
您可以尝试在每次执行后清空控制台
像 system("cls");
这是 link 到 post
[How can I clear console
我在多个地方读到 \n 在使用时不会刷新缓冲区,但是在我的代码中,我将在这个问题的末尾添加,它似乎就是这样做的,或者至少看起来是这样从输出的方式(由于我执行 cout 的方式,可能在后台发生了其他事情?)。
预期输出:
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...
我在 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...
我希望输出保持原样,就像预期输出示例中的那样,并且在我的代码中每次执行时间循环时更新自身。
这是我的代码:
#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();
}
根据 Ben Voigt 的说法,\r 似乎不能按照我尝试使用它的方式使用。除了 Matthew 关于每次更新都关闭命令 window 的建议之外,还有其他建议吗?也许是 Boost 中的某些东西或 c++11 的新东西?
谢谢。
您可以尝试在每次执行后清空控制台 像 system("cls"); 这是 link 到 post [How can I clear console