代码之家  ›  专栏  ›  技术社区  ›  user2891462

当更多信息被打印到屏幕上时,progress\u显示工作

  •  4
  • user2891462  · 技术社区  · 8 年前

    我有一个控制台程序,它可能需要一些时间进行计算。我正在使用 boost::progress_display 向用户提供一些反馈。

    我的问题是,如果发生某些事情,我还想打印标准输出的其他更新,这会打破进度条:

    0%   10   20   30   40   50   60   70   80   90   100%
    |----|----|----|----|----|----|----|----|----|----|
    **Found temporary candidate with score: 40
    Found temporary candidate with score: 46
    *Found temporary candidate with score: 52
    ********Found temporary candidate with score: 55
    **Found temporary candidate with score: 67
    **************************************
    

    有没有一种简单的方法可以同时拥有两个进度条(理想情况下,在代码中与 boost::progress\u显示

    编辑: 在评论中有人建议说我没有提供我想要的示例后,我想要类似的代码:

    boost::progress_display progress(10);
    for (size_t i = 0; i< 10; ++i)
    {
        std::cout << "Number is: " << i << "\n";
        ++progress;
    }
    

    但这并不会产生这种输出:

    0%   10   20   30   40   50   60   70   80   90   100%
    |----|----|----|----|----|----|----|----|----|----|
    Number is: 0
    *****Number is: 1
    *****Number is: 2
    *****Number is: 3
    *****Number is: 4
    *****Number is: 5
    *****Number is: 6
    *****Number is: 7
    *****Number is: 8
    *****Number is: 9
    ******
    

    相反,我喜欢台词 Number is: z 要在进度条之后或之前显示,请执行以下操作:

    Number is: 0
    Number is: 1
    Number is: 2
    Number is: 3
    Number is: 4
    Number is: 5
    Number is: 6
    Number is: 7
    Number is: 8
    Number is: 9
    0%   10   20   30   40   50   60   70   80   90   100%
    |----|----|----|----|----|----|----|----|----|----|
    ***************************************************
    
    1 回复  |  直到 8 年前
        1
  •  7
  •   user2891462    8 年前

    使用自制课程

    我无法使用 boost::progress_display 因此,我实现了我自己的RAII类,它在Linux下工作得很有魅力:

    进度条。h

    #ifndef PROGRESS_BAR_H
    #define PROGRESS_BAR_H
    
    #include <string>
    
    /**
     * RAII implementation of a progress bar.
     */
    class ProgressBar
    {
    public:
        /**
         * Constructor.
         * It takes two values: the expected number of iterations whose progress we
         * want to monitor and an initial message to be displayed on top of the bar
         * (which can be updated with updateLastPrintedMessage()).
         */
        ProgressBar(
                uint32_t expectedIterations, const std::string& initialMessage="");
    
        /**
         * Destructor to guarantee RAII.
         */
        ~ProgressBar();
    
        // Make the object non-copyable
        ProgressBar(const ProgressBar& o) = delete;
        ProgressBar& operator=(const ProgressBar& o) = delete;
    
        /**
         * Must be invoked when the progress bar is no longer needed to restore the
         * position of the cursor to the end of the output.
         * It is automatically invoked when the object is destroyed.
         */
        void endProgressBar();
    
        /**
         * Prints a new message under the last printed message, without overwriting
         * it. This moves the progress bar down to be placed under the newly
         * written message.
         */
        void printNewMessage(const std::string& message);
    
        /**
         * Prints a message while the progress bar is on the screen on top on the
         * last printed message. Since the cursor is right at the beginning of the
         * progress bar, it moves the cursor up by one line before printing, and
         * then returns it to its original position.
         */
        void updateLastPrintedMessage(const std::string& message);
    
        /**
         * Overloaded prefix operator, used to indicate that the has been a new
         * iteration.
         */
        void operator++();
    
    private:
        unsigned int mTotalIterations;
        unsigned int mNumberOfTicks;
        bool mEnded;
        size_t mLengthOfLastPrintedMessage;
    };
    
    #endif /* PROGRESS_BAR_H */
    

    进度条。清洁石油产品

    #include "ProgressBar.h"
    #include <iostream>
    #include <iomanip>
    #include <sstream>
    
    #define LENGTH_OF_PROGRESS_BAR 55
    #define PERCENTAGE_BIN_SIZE (100.0/LENGTH_OF_PROGRESS_BAR)
    
    namespace
    {
        std::string generateProgressBar(unsigned int percentage)
        {
            const int progress = static_cast<int>(percentage/PERCENTAGE_BIN_SIZE);
            std::ostringstream ss;
            ss << " " << std::setw(3) << std::right << percentage << "% ";
            std::string bar("[" + std::string(LENGTH_OF_PROGRESS_BAR-2, ' ') + "]");
    
            unsigned int numberOfSymbols = std::min(
                    std::max(0, progress - 1),
                    LENGTH_OF_PROGRESS_BAR - 2);
    
            bar.replace(1, numberOfSymbols, std::string(numberOfSymbols, '|'));
    
            ss << bar;
            return ss.str();
        }
    }
    
    ProgressBar::ProgressBar(
                uint32_t expectedIterations, const std::string& initialMessage)
        : mTotalIterations(expectedIterations),
          mNumberOfTicks(0),
          mEnded(false)
    {
        std::cout << initialMessage << "\n";
        mLengthOfLastPrintedMessage = initialMessage.size();
        std::cout << generateProgressBar(0) << "\r" << std::flush;
    }
    
    ProgressBar::~ProgressBar()
    {
        endProgressBar();
    }
    
    void ProgressBar::operator++()
    {
        if (mEnded)
        {
            throw std::runtime_error(
                    "Attempted to use progress bar after having terminated it");
        }
    
        mNumberOfTicks = std::min(mTotalIterations, mNumberOfTicks+1);
        const unsigned int percentage = static_cast<unsigned int>(
                mNumberOfTicks*100.0/mTotalIterations);
    
        std::cout << generateProgressBar(percentage) << "\r" << std::flush;
    }
    
    void ProgressBar::printNewMessage(const std::string& message)
    {
        if (mEnded)
        {
            throw std::runtime_error(
                    "Attempted to use progress bar after having terminated it");
        }
    
        std::cout << "\r"
            << std::left
            << std::setw(LENGTH_OF_PROGRESS_BAR + 6)
            << message << "\n";
        mLengthOfLastPrintedMessage = message.size();
        const unsigned int percentage = static_cast<unsigned int>(
                mNumberOfTicks*100.0/mTotalIterations);
    
        std::cout << generateProgressBar(percentage) << "\r" << std::flush;
    
    }
    
    void ProgressBar::updateLastPrintedMessage(const std::string& message)
    {
        if (mEnded)
        {
            throw std::runtime_error(
                    "Attempted to use progress bar after having terminated it");
        }
    
        std::cout << "\r\033[F"
            << std::left
            << std::setw(mLengthOfLastPrintedMessage)
            << message << "\n";
        mLengthOfLastPrintedMessage = message.size();
    }
    
    void ProgressBar::endProgressBar()
    {
        if (!mEnded)
        {
            std::cout << std::string(2, '\n');
        }
        mEnded = true;
    }
    

    如何使用它

    以下是两段代码,展示了如何使用它以及预期的输出:

    正在更新。清洁石油产品

    #include "ProgressBar.h"
    #include <unistd.h>
    
    #define ITERATIONS 10
    
    int main()
    {
        ProgressBar progress(ITERATIONS, "No odd number found");
        for (size_t i = 0; i < ITERATIONS; ++i)
        {
            // Sleep for 0.5s so that the gif is clear enough
            usleep(500000);
    
            if (i%2 != 0)
            {
                progress.updateLastPrintedMessage(
                        "New odd number found: " + std::to_string(i));
            }
    
            ++progress;
        }
    }
    

    enter image description here

    #include "ProgressBar.h"
    #include <unistd.h>
    
    #define ITERATIONS 10
    
    int main()
    {
        ProgressBar progress(ITERATIONS, "Looking for odd numbers...");
        for (size_t i = 0; i < ITERATIONS; ++i)
        {
            // Sleep for 0.5s so that the gif is clear enough
            usleep(500000);
    
            if (i%2 != 0)
            {
                progress.printNewMessage(
                        "New odd number found: " + std::to_string(i));
            }
    
            ++progress;
        }
    }
    

    追加的输出。清洁石油产品

    enter image description here