ncurses
предоставляет набор функций ввода\вывода, который идентичен функциям ввода\вывода из stdio
, но кроме этого добавляет свои функции. Рассмотрим их подробнее.
Функции вывода
Все функции вывода условно можно поделить на три группы:
- addch()-функции. Вывод одного символа с заданными атрибутами.
- printw()-функции. Форматированный вывод.
- addstr()-функции. Вывод строки.
addch()-функции
Функция addch()
выводит один символ в текущую позицию курсора с заданными атрибутами.
Атрибуты — это параметры вывода символа, такие как мерцание, подчёркнутость, выделение жирным шрифтом и т.п. В ncurses за каждый атрибут отвечает константа, объявленная в ncurses.h
. Все такие константы начинаются с приставки «A_».
Вот список некоторых атрибутов:
A_NORMAL - обычный режим
A_STANDOUT - самое яркое выделение из всех возможных
A_UNDERLINE - подчёркивание
A_BLINK - мигание
A_DIM - тусклый символ
A_BOLD - выделение жирным шрифтом
addch()
принимает ncurses
-символ, длинна которого равна 32 битам. Первые 16 бит отводятся под символ, а остальные 16 под атрибуты, поэтому чтобы составить такой символ придётся применять логическое ИЛИ(|), чтобы объединить несколько атрибутов. Например так:
addch( 'A' | A_BOLD | A_UNDERLINE );
Вызов такой функции выведет на экран подчёркнутый символ «А» жирным шрифтом.
Пример
В качестве примера сравним, как выводится обычный символ «А» и как он выводится с атрибутами A_BOLD | A_UNDERLINE
.
#include <ncurses.h>
int main()
{
initscr();
//Вывод символа "А" в обычном режиме
printw("Typical symbol \'A\': ");
addch('A');
//Вывод подчёркнутого и жирного символа "А"
printw("\nUnderline and bold symbol \'A\': ");
addch('A' | A_BOLD | A_UNDERLINE);
printw("\nPress any key...");
getch();
endwin();
return 0;
}
Вот как это выглядит:
waddch(), mvaddch() и mvwaddch()
Эти функции аналогичны addch()
за исключением того, что waddch()
выводит символ не на stdscr
а на заданное окно, mvaddch()
перед выводом символа переводит координаты курсора, примерно следующим образом:
move(y, x);
addch(ch);
Функция move()
меняет расположение корсора. Особое внимание нужно уделить тому, что в ncurses координаты принимаются в порядке (y, x), а не (x, y) как обычно. Помните об этом.
mvwaddch()
является «суммой» функции mvaddch()
и waddch()
.
printw()-функции
Эти функции практически полностью аналогичны функции printf()
. Только у printw()
, как у любой уважающей себя ncurses-функции, есть модификации для форматированного вывода на окно — wprintw()
, вывода, начиная с определённых координат — mvprintw()
, ну и вывод на окно, начиная с определённых координат — mvwprintw()
.
Пример
Эта программа выводит строку «Just a string» по центру экрана, а так же информацию о размере экрана в левом нижнем углу, вне зависимости от размеров экрана.
#include <ncurses.h>
#include <cstring>
int main()
{
const char *mesg = "Just a string";
//Количество строк и столбцов на экране терминала
int row, col;
initscr();
//Получаем максимально возможное количество строк и столбцов для окна stdscr и записываем эти данные в row и col
getmaxyx(stdscr, row, col);
//Выводим сообщение в центре окна stdscr
mvwprintw(stdscr, row / 2, (col - strlen(mesg)) / 2, "%s", mesg);
//Выводим информацию о количестве строк и столбцов в левом нижнем углу экрана
mvwprintw(stdscr, row - 1, 0, "The number of rows - %d and columns - %d\n", row, col);
getch();
endwin();
return 0;
}
Вызовем программу со стандартным размером окна:
Немного поколдуем с размерами окна (например, с помощью мыши) и снова выполним программу:
Как видно, программа получилась нечувствительной к размерам окна. Сделать её такой нам помогли функции getmaxx()
, getmaxy()
и getmaxyx()
, запомните эти функции, они часто пригождаются.
addstr()-функции
Функция addstr()
(а также mvaddstr()
, waddstr()
и mvwaddstr()
) просто выводят строку символов на экран.
Пример
Эта программа выведет на экран строку «Just a string»:
#include <ncurses.h>
int main()
{
const char *mesg = "Just a string";
initscr();
addstr(mesg);
getch();
endwin();
return 0;
}
Функции ввода
Вывод без ввода смысла не имеет, поэтому разберём функции ввода. Как и функции вывода, функции ввода условно можно поделить на три группы:
- getch()-функции. Считывание символа.
- scanw()-функции. Форматированный ввод.
- getstr()-функции. Считывание строки.
getch()-функции
Эта функция считывает только один символ с терминала. Имеет модификации wgetch()
, mvgetch()
и mvwgetch()
. Совместно с функцией keypad()
предоставляет удобное средство для управления клавиатурой.
Пример
В качестве примера напишем каркас для создания простого интерактивного меню:
#include <ncurses.h>
const char items[4][6] = {
"Item1",
"Item2",
"Item3",
"Item4"
};
int main()
{
initscr();
unsigned choice = 0; //Выбор пользователя
curs_set(0); //"Убиваем" курсор
//Включаем режим удобной работы с функциональными клавишами, другими словами KEY_UP и KEY_DOWN без этого не работали бы
keypad(stdscr, true);
while ( true )
{
clear();
for ( unsigned i = 0; i < 4; i++ ) //Проходим по всем элементам меню
{
if ( i == choice ) //Если текущий элемент совпадает с выбором пользователя
addch('>'); //Выводим указатель
else
addch(' '); //Иначе выводим " ", для равновесия
printw("%s\n", items[i]);
}
//Получаем нажатие пользователя
switch ( getch() )
{
case KEY_UP:
if ( choice ) //Если возможно, переводим указатель вверх
choice--;
break;
case KEY_DOWN:
if ( choice != 3 ) //Если возможно, переводим указатель вниз
choice++;
break;
}
}
endwin();
return 0;
}
scanw()-функции
Аналог scanf()
из stdio
, то есть форматированный ввод с клавиатуры. Как всегда, имеется wscanw()
, mvscanw()
, mvwscanw()
.
Пример
В качестве примера напишем простой калькулятор:
#include <ncurses.h>
int main()
{
initscr();
int a, b;
char c;
scanw("%d%c%d", &a, &c, &b);
printw("%d %c %d = ", a, c, b);
switch ( c )
{
case '+':
printw("%d", a + b);
break;
case '-':
printw("%d", a - b);
break;
case '*':
printw("%d", a * b);
break;
case '/':
if ( !b )
printw("ERROR");
else printw("%f", static_cast<double>(a) / b);
break;
default:
printw("ERROR");
break;
}
getch();
endwin();
return 0;
}
getstr()-функции
Как известно, scanf()
, а значит и scanw()
некорректно считывают строки — только до первого символа-разделителя. Чтобы считывать строки вместе с символом разделителем, была создана функция getstr()
(имеются, соответственно, wgetstr()
, mvgetstr()
и mvwgetstr()
).
Пример
В качестве примера напишем программу, которая считает строку, а затем будет гонять эту строку по центру экрана. Обратите внимание на использование функций getmaxy()
, getmaxx()
и refresh()
. Использование этих функций необходимо, особенно последней, поскольку без неё, программа на некоторых машинах (например, на моей) может «повиснуть» в глазах пользователя, хотя на самом деле она что-то выводит.
Так же обратите внимание на макрос задержки. До этого времени все наши программы можно было назвать, хотя и с натяжкой, кроссплатформенными, благодаря PDcurses
под windows
. Но функцию задержки нам придётся придётся прописывать для каждой платформы отдельно, потому что unistd.h
, как и windows.h
это системозависимые библиотеки.
#include <ncurses.h>
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#define msleep(msec) Sleep(msec)
#else
#include <unistd.h>
#define msleep(msec) usleep(msec*1000)
#endif
int main()
{
initscr();
char str[100];
addstr("Enter string: ");
getstr(str); //Считваем строку
curs_set(0); //"Убиваем" курсор, чтобы не мешался
while ( true )
{
//Перемещаем х-координату как можно дальше вправо, и будем уменьшать её, пока она != 0
for ( unsigned x = getmaxx(stdscr); x; x-- )
{
clear();
mvaddstr(getmaxy(stdscr) / 2, x, str);
refresh();
msleep(200);
}
}
endwin();
return 0;
}
Автор статьи: Porshe
Комментарии к статье: 15
Возможность комментировать эту статью отключена автором. Возможно, во всем виновата её провокационная тематика или большое обилие флейма от предыдущих комментаторов.
Если у вас есть вопросы по содержанию статьи, рекомендуем вам обратиться за помощью на наш форум.