TVA van Hesteren
TVA van Hesteren

Reputation: 1221

C++ Console print on same line with carriage return

I have a console application which I want to print the progress with. However, to make this as nice as possible, I would like to print the percentage updates with a carriage return in order to keep the percentage updating instead of adding new lines with new progress status.

Printing with the carriage return works great, until I get a string that outranges the width of my console window. Obviously, the carriage return is not going to return to the start of the string which is longer than the console window.

Is there a possibility to catch this occurrence and somehow start at the beginning of the string again?

Visualized problem:

string = "This is a test string which is longer than the console";
  |<-      Console width       ->|
  |This is a test string which is|
->| longer than the console      |

The carriage return makes the string being printed starting from the -> as visualized above

Upvotes: 2

Views: 2383

Answers (3)

2785528
2785528

Reputation: 5566

until I get a string that outranges the width of my console window.

It is possible to create a small util function, in c++, to fetch the current screen dimensions as reported by ncurses.

If you run it prior to each output, you will have the dimension you need to predict 'wraparound' based on string size, and take your desired actions. The use of stringstream can be very useful.

#include <iostream>
#include <iomanip>
#include <vector>
// I prefer to not include ncurses here, see below 


// determine current console dimensions
class ConsoleDimensions
{
public:
   ConsoleDimensions()  = default;
   ~ConsoleDimensions() = default;
   //
   std::string operator()();
};


class T504_t // or any class name you want
{
public:

   T504_t() = default;
   ~T504_t() = default;

   int exec()
      {
         std::cout << "\n\n" << ConsoleDimensions()() << std::endl;
         //                    invokes operator()--^^
         return(0);
      }

}; // class T504_t



int main(int argc, char* argv[])
{
  std::cout << "\nargc: " << argc << std::endl;
  for (int i = 0; i < argc; i += 1) std::cout << argv[i] << " ";
  std::cout << std::endl;

   int retVal = -1;
   {
      T504_t   t504;
      retVal = t504.exec();
   }

   std::cout << "\n\n  <<< If your C++ 'Hello World' has no class ... "
             <<" why bother? >>> \n\n"
             << std::endl;
   return(retVal);
}



// separate this implementation file (.cc)
//     to prevent the curses macros from polluting your non-curses code
#include "cursesw.h"

std::string ConsoleDimensions::operator()()
      {
         (void)initscr(); // start curses mode
         cbreak();
         noecho();
         // erase()
         // refresh()
         raw();
         // nonl();
         // intrFlush(stdscr, FALSE)
         keypad(stdscr, true);

         // curses uses int (will there ever be a negative height or width?)
         int curses_reported_height = 0;
         int curses_reported_width  = 0;
         getmaxyx(stdscr, curses_reported_height, curses_reported_width);

         std::stringstream ss;
         ss << "  max y: " << curses_reported_height
            << "  max x: " << curses_reported_width;

         endwin();
         return(ss.str());
      }

The output when running this on a full-screen standard gnome-terminal with default font:

  max y: 70  max x: 266

You possibly just want the numbers, not the text. It is easy to change

std::string ConsoleDimensions::operator()();

I would consider,

void ConsoleDimensions::operator()(int& maxY, int& maxX);

with appropriate implementation changes.


Update 2017-07-22

Performance estimates using std::chrono::high_resolution_clock and form "void ConsoleDimensions::operator()(int& maxY, int^ maxX);"

171.2830000 k ConsoleDimension()(int&, int&) events in 4,000,006 us
42.82068577 k ConsoleDimension()(int&, int&) events per second
23.35319909 µ sec per  ConsoleDimension()(int&, int&) event 

dimensions [50,100]

Your results will vary.

Upvotes: 1

Thomas Matthews
Thomas Matthews

Reputation: 57678

The problem is that console windows differ. On the Windows platform you can adjust the width and height of the console.

You may be able to find some API that will return the height and width of the console window; but there is no requirement for a platform to support that.

There are libraries that can assist with cursor positioning. Search Software Recommendations (at StackExchange) to see what they recommend or search the internet for "c++ cursor position library".

Upvotes: 2

CaptainSegFault
CaptainSegFault

Reputation: 82

On Linux, are you looking for something like this?

#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
    struct winsize size;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);

    printf ("%d\n", size.ws_row);
    printf ("%d\n", size.ws_col);
}

Upvotes: 1

Related Questions