3

I'm learning how to use ncurses, and wanted to use RAII to automatically init and end window:

class CWindow
{
public:
   CWindow() {initscr();}
   ~CWindow() {endwin();}
};

This is basic idea of CWindow class. It works only for stdscr now, so using functions like addch(), printw(), etc. isn't a problem. However, this class will eventually be used to represent ncurses windows(WINDOW*). It would be intuitive to add member functions like print, so that instead of using

wprintw(win.getWin(), "str %i", someVar);

one could write

win.print("str %i", someVar);

I looked in web, but it seems to me that only cstdio's prinf and similar functions have been wrapped. And cstdio provides an easy way, with function that accepts va_list. However, ncurses doesn't have this set of functions.

To be honest, I'm rather using C++ then C, so my C knowledge isn't excellent. I've also not created any variable argument list functions. I tried naive approach:

void print(const char* str, ...)
{
    va_list args;
    va_start(args, str);
    printw(str, args);
    va_end(args);
}

However, it doesn't work. I also tried to incorporate variadic macros like in this thread, but it doesn't work for me. I may be doing it wrong though.

Anyway, how may I achieve this?

Community
  • 1
  • 1
MatthewRock
  • 1,071
  • 1
  • 14
  • 30
  • 1
    look for "variadic templates", or better yet, make your CWindow class a kind-of-iostream class and use inserters and extractors (`operator <<` and `operator >>`) ... – Massa Apr 05 '14 at 11:13
  • I've also seen variadic templates, but they said that variadic template will create separate function for each set of arguments(because this is how templates work). Therefore, it's uneffective regarding code size. I also thought about operator<< and >>, but I want to keep the interface consistent, and I want to use functions mvprintw(const char* str, ...), which moves cursor to (y, x), and then prints str there. – MatthewRock Apr 05 '14 at 11:32
  • With sufficient optimization, your variadic template call should be inlined to the original `mvprintw` or `printw` calls and the problem is moot. Anyway, see my answer below... – Massa Apr 05 '14 at 11:44

2 Answers2

2

The answer by @massa can be improved:

  • while ncurses accepts vwprintw, the preferred form is vw_printw.
  • it is not necessary to use the return value from initscr; the stdscr variable holds the same value.

With those fixes:

void print(const char* str, ...)
{
    va_list args;
    va_start(args, str);
    vw_printw(stdscr, str, args);
    va_end(args);
}

Further reading:

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • vw_printw returns an int with OK or ERR that could be beneficial for this print function wrapping it to return as well. – Aria Jun 15 '18 at 20:17
0

You are almost in the right path to do what you want, just change

printw(string, args);

for

WINDOW *win = initscr();
// ...
vwprintw(win, string, args);
linluk
  • 1,650
  • 16
  • 33
Massa
  • 8,647
  • 2
  • 25
  • 26