Blackened
Blackened

Reputation: 13

Is there a way to print a string-type variable in C++ via the ncurses library?

I have been constantly trying to print out a string type variable via ncurses' functions since "cout" is not working by the time I am typing in the "initscr()" command. I have created an array of string variables and I am trying to print each and every single one of the strings out on a window. The result I am getting is some nonsense words. Here's the most critical parts of my code:

string *filetypes = new string[4];
filetypes[0] = ".png";
filetypes[1] = ".jpeg";
filetypes[2] = ".jpg";
filetypes[3] = ".gif";
initscr();
WINDOW *menu = newwin(height, width, y, x);
box(menu, 0, 0);
keypad(menu, true);
selection = menuShow(filetypes, 4, menu);
endwin();

I am printing the array's values via the "menuShow" function. Here is the function's code as well:

int menuShow(string *choices, int opt, WINDOW *menu)
{

int i, highlight = 0;
system("clear");
noecho();
wchar_t buttonPress;
do
{
    refresh();
    wrefresh(menu);
    for(i = 0; i < opt; i++)
    {
        //xrwmatizei thn epilegmenh praksh sthn opoia vrisketai o cursor
        if(i == highlight)
        {
            wattron(menu, A_REVERSE);
            mvwprintw(menu, i + 1, 1, "%s", choices[i]);
            wattroff(menu, A_REVERSE);
        }
        else
        {
            mvwprintw(menu, i + 1, 1, "%s", choices[i]);
        }
            
    }
    wrefresh(menu);
    refresh();
    buttonPress = wgetch(menu);
    switch(buttonPress)
    {
        case KEY_UP:
            highlight--;
            if(highlight == -1)
                highlight++;
           break;
        case KEY_DOWN:
            highlight++;
            if(highlight > (opt - 1))
                highlight--;
            break;
        default:
            break;
    }        

}while(buttonPress != 10);

return highlight;

The output I am getting is:

~P/~[#�^? 
~P/~[#�^? 
~P/~[#�^? 
~P/~[#�^? 

Any idea?

By the way, note that after the "endwin();" line, I am printing out the array's strings using cout and they are being printed normally. I think that the reason why this happens is due to the fact that "printw()" and ncurses' functions in general do not support "string" formats. So, my question is: Is there any possible method to print out a string type variable after the "initscr();" line?

Upvotes: 0

Views: 1866

Answers (2)

Loki Astari
Loki Astari

Reputation: 264351

The menuShow uses the same type formatters as printf().

So "%s" is expecting a C-String (or char*).

You are proividing a std::string which is not the same.

int menuShow(string *choices, int opt, WINDOW *menu)

    ... STUFF

    mvwprintw(menu, i + 1, 1, "%s", choices[i]);
                                    ^^^^^^^^^^ this is a std::string

What you want to do is convert the std::string into a char* you can do this by calling c_str().

    mvwprintw(menu, i + 1, 1, "%s", choices[i].c_str());
                                           // ^^^^^^^^

You are using ncurses a (very cool but) C library. The problem here is the C language is not ss type safe as C++. In this case the C language provides variable number of arguments to mvwprintw() unfortunately the types of these arguments are not specified so the compiler does not check if you are passing a valid type (and thus no warning or error).

Note: C++ still provides this old style interface for backwards compatibility with C but in more modern C++ libraries you would use template varargs so that we can explicitly make sure the types are correct.

Upvotes: 1

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38341

The format "%s" expects char*, not std::string. Try

mvwprintw(menu, i + 1, 1, "%s", choices[i].c_str());

Why do you do so

string *filetypes = new string[4];
filetypes[0] = ".png";
filetypes[1] = ".jpeg";
filetypes[2] = ".jpg";
filetypes[3] = ".gif";

Why not

string filetypes[4] = {
  ".png",
  ".jpeg",
  ".jpg",
  ".gif",
};

Upvotes: 0

Related Questions