简体   繁体   中英

Cannot read from stdin extended ASCII character in NCURSES

I have a problem trying to read extended ASCII chars in NCURSES.

I have this program:

#include <ncurses.h>
int main () {
    initscr();
    int d = getch();
    mvprintw(0, 0, "letter: %c.", d);
    refresh();
    getch();
    endwin();
    return 0;
}

I build it with: gcc -lncursesw ac

If I type a character in the 7bit ascii, like the 'e' char, I get:

letter: e.

And then I have to type another for the program to end.

If I type a character in the extended ascii, like the 'á' char, I get:

letter:  .

and the program ends.

Its like the second byte is read as another character.

How can I get the correct char 'á' ???

Thanks!

The characters that you want to type require the program to setup the locale . As described in the manual :

Initialization

   The  library uses the locale which the calling program has
   initialized.  That is normally done with setlocale:

         setlocale(LC_ALL, "");

   If the locale is not initialized, the library assumes that
   characters  are  printable  as in ISO-8859-1, to work with
   certain legacy programs.  You should initialize the locale
   and  not  rely on specific details of the library when the
   locale has not been setup.

Past that, it is likely that your locale uses UTF-8. To work with UTF-8, you should compile and link against the ncursesw library.

Further, the getch function only returns values for single-byte encodings, such as ISO-8859-1, which some people confuse with Windows cp1252 , and thence to "Extended ASCII" (which says something about two fallacies not cancelling out). UTF-8 is a multibyte encoding. If you use getch to read that , you will get the first byte of the character.

Instead, to read UTF-8 , you should use get_wch (unless you want to decode the UTF-8 yourself). Here is a revised program which does that:

#include <ncurses.h>
#include <locale.h>
#include <wchar.h>
int
main(void)
{   
    wint_t value;
    setlocale(LC_ALL, "");
    initscr();
    get_wch(&value);
    mvprintw(0, 0, "letter: %#x.", value);
    refresh();
    getch();
    endwin();
    return 0;
}

I printed the result as a number, because printw does not know about Unicode values. printw uses the same C runtime support as printf , so you may be able to print the value directly. For instance, I see that POSIX printf has a formatting option for handling wint_t :

c
The int argument shall be converted to an unsigned char , and the resulting byte shall be written.
If an l ( ell ) qualifier is present, the wint_t argument shall be converted as if by an ls conversion specification with no precision and an argument that points to a two-element array of type wchar_t , the first element of which contains the wint_t argument to the ls conversion specification and the second element contains a null wide character.

Since ncurses works on many platforms, not all of those actually support the feature. But you can probably assume it works with the GNU C library: most distributions routinely provide workable locale configurations.

Doing that, the example is more interesting:

#include <ncurses.h>
#include <locale.h>
#include <wchar.h>
int
main(void)
{   
    wint_t value;
    setlocale(LC_ALL, "");
    initscr();
    get_wch(&value);
    mvprintw(0, 0, "letter: %#x (%lc).", value, value);
    refresh();
    getch();
    endwin();
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM