Пишем первую программу на Ncurses

12 комментариев

Ncurses — это библиотека, предназначенная для управления вводом-выводом на терминал. Позволяет задавать экранные координаты и цвет выводимых символов. Это статья является переводом данного материала. Пишите в комментариях, если нашли ошибку или неточность в переводе.

Материал рассчитан в первую очередь, на пользователей Unix-подобных ОС. Тем не менее, для пользователей Windows есть клон библиотеки ncursesPDcurses.

История

В стародавние времена все немногочисленные возможности терминалов (телетайп-терминалов) поддерживались с помощью последовательностей байт. Эти управляющие последовательности, обычно называемые escape-последовательностями, начинались со специального символа 0x1B. Отголоски того времени дошли и до нас. Сегодня мы можем сделать то же самое со своим терминалом (на самом деле с эмулятором терминала, но для краткости, здесь и далее, называемым терминалом), используя точно такую же технологию.

Рассмотрим пример. Допустим, вам захотелось написать строку «In color» красным цветом. Для этого напишем в терминале (работает только для UNIX-подобных систем!):

echo "^[[0;31;40mIn color"

Первый символ является escape-символом («^[», догадайтесь сами какой HEX-код у этого символа). Чтобы набрать его в терминале нужно нажать CTRL+V, а затем ESC. Дальше набираете так, как есть.

Результат выполнения команды: Вывод цветного текста в терминале

Тот же трюк можно провернуть и программно:

#include <iostream>

int main()
{
    std::cout << "\x1B[0;31;40mIn color" << std::endl;
    return 0;
}

В С\C++ escape-символы задаются символом \ (к примеру, \n — переход на новую строку, \r — возврат каретки). Соответственно, чтобы загнать escape-символ 0×1B в поток, нужно вписать \x1B.

Представим, что вам захотелось в своей программе использовать различные цвета, чтобы программа выглядела красивее чем обычно. Не правда ли будет сложно запоминать значения каждых управляющих символов?

И к тому же, эти символы, скорее всего, различны для каждого типа терминала. Именно для того, чтобы избежать заучивания значения каждого символа, а также для написания кода, не зависящего от типа терминала, была придумана библиотека ncurses.

Что такое ncurses и с чем его едят?

Изначально была библиотека под названием curses (название произошло от сокращения «cursor optimization»). Эта библиотека работала напрямую с терминалом, используя API системы, и при этом позволяла разработчикам не заботиться о различных типах терминалов. Библиотека давала возможность приложению перемещать курсор, создавать окна (не GUI), управлять цветом, управлять мышью и т.д. без использования зависящих от системы управляющих символов.

ncurses — это клон оригинальной curses из System V Release 4.0 (SVr4), которая в свою очередь была улучшением классического curses из BSD (название произошло от  «new curses»)

Но ncurses это не только обёртка над зависимыми от системы управляющими символами, это так же и хороший фреймворк для создания красивого пользовательского интерфейса в текстовом режиме. Библиотека содержит функции управления окнами и меню, а так же «библиотеку-сестру» panel, управляющую панелями.

Вот пример приложения, основанного на ncurses: Пример программы на Ncurses

Разумеется, это не все возможности, предоставляемые этой библиотекой. По мере продвижения вперёд, мы увидим гораздо больше, не сомневайтесь :)

Установка ncurses

Установить ncurses очень просто. Для этого откроем терминал и напишем:

sudo apt-get install libncursesw5-dev

Всё. Библиотека установлена и теперь мы готовы писать код.

Привет, мир! (Hello world!)

Итак, добро пожаловать в мир ncurses. Перед погружением в библиотеку, напишем простую программу, которая скажет «Hello!» всему миру.

Чуть не забыл, чтобы компилировать программы, использующие библиотеку ncurses, нужно устанавливать флаг -lncurses:

gcc <программа> -lncurses

Код программы:

#include <ncurses.h>

int main()
{
    initscr();                   // Переход в curses-режим
    printw("Hello world!\n");  // Отображение приветствия в буфер
    refresh();                   // Вывод приветствия на настоящий экран
    getch();                     // Ожидание нажатия какой-либо клавиши пользователем
    endwin();                    // Выход из curses-режима. Обязательная команда.
    return 0;
}

Описание кода

ncurses.h

ncurses.h — заголовочный файл ncurses. В нём объявлены все функции и константы библиотек. Обязателен к подключению.

initscr()

Функция initscr() переводит терминал в curses-режим. Она чистит экран, выделяет память под необходимые данные для работы библиотеки, и инициализирует окно stdscr (об этом не сегодня, к сожалению). Вызов initscr() обязателен перед любым использованием ncurses. В некоторых случаях функция может завершиться неудачно, если не хватило памяти. Впрочем, такие ситуации маловероятны, учитывая ресурсы, предоставленные современным компьютерам и ресурсы, требуемые для нормальной работы библиотеки.

printw()

Функция printw() выполняет ту же роль что и printf(), и имеет точно такой же синтаксис. Почему используется именно printw()? Потому что std::cout и printf() на работают в curses-режиме. В остальном эта функция полностью аналогична printf(). Для справки: ввод осуществляется при помощи функции scanw() (аналогично scanf()).

refresh()

Функция printw() отправляет данные не напрямую на экран, а в так называемый буфер. Функция refresh() проверяет буфер и, если он не пуст, отправляет информацию на экран (обновляет только изменившиеся зоны экрана), она чем то схожа с flush() из stdio. Зачастую, её вызов не обязателен, но иногда без вызова этой функции можно получить странные ошибки.

getch()

Функция getch(), наверное, знакома всем по библиотеке conio.h. Так вот, это её полный аналог (даже чуть лучше, как мы увидим далее). Функция ожидает нажатие любой клавиши на клавиатуре и возвращает код этой самой клавиши.

endwin()

В конце не забывайте выйти из curses-режима, иначе, после завершения программы ваш терминал будет «странно» себя вести. Выходом из curses-режима занимается функция endwin(). Она очищает экран, освобождает память, которую выделяла initscr() и переводит терминал в нормальный режим (в тот, в котором он был до выполнения программы).

Автор статьи: Porshe

Продолжение: →.

Комментарии к статье: 12

Подождите, загружаются комментарии...

Возможность комментировать эту статью отключена автором. Возможно, во всем виновата её провокационная тематика или большое обилие флейма от предыдущих комментаторов.

Если у вас есть вопросы по содержанию статьи, рекомендуем вам обратиться за помощью на наш форум.