Небуферизованный ввод-вывод в ANSI C

Ради образования и практики программирования я хотел бы написать простую библиотеку, которая может обрабатывать необработанный ввод с клавиатуры и выводить на терминал в «реальном времени».

Я бы хотел как можно больше придерживаться ansi C, я просто понятия не имею, с чего начать что-то подобное. Я сделал несколько поисков в Google, и 99% результатов используют библиотеки или для C++.

Я бы очень хотел, чтобы он работал в Windows, а затем портировал его на OSX, когда у меня будет время.


person Ryan Rohrer    schedule 30.10.2009    source источник


Ответы (3)


Придерживаться стандарта C как можно дольше — это хорошая идея, но вы не продвинетесь со своей принятой задачей, используя только стандартный C. Механизмы получения символов из терминала по одному по своей сути зависят от платформы. Для систем POSIX (MacOS X) см. <termios.h> заголовок. Старые системы используют множество заголовков и системных вызовов для достижения аналогичных эффектов. Вам нужно будет решить, собираетесь ли вы выполнять какую-либо специальную обработку символов, помня, что такие вещи, как «уничтожение строки», могут появиться в конце строки и уничтожить все символы, введенные до сих пор.

Для Windows вам нужно будет вникнуть в WIN32 API — в коде между Unix и Windows практически не будет общего, по крайней мере, там, где вы переводите «терминал» в посимвольный режим. Когда у вас есть механизм для чтения отдельных символов, вы, вероятно, сможете управлять общим кодом.

Кроме того, вам нужно будет беспокоиться о различиях между символами и нажатыми клавишами. Например, чтобы ввести «ï» в MacOS X, введите option-u и i. Это три нажатия клавиш.

person Jonathan Leffler    schedule 30.10.2009
comment
Я боялся, что мне придется это сделать... Думаю, я справлюсь... есть ли win32API в windows.h? Спасибо за направление.. :) - person Ryan Rohrer; 30.10.2009

Чтобы сделать открытый поток небуферизованным с помощью ANSI C, вы можете сделать это:

#include <stdio.h>
if (setvbuf(fd, NULL, _IONBF, 0) == 0)
  printf("Set stream to unbuffered mode\n");

(Ссылка: C89 4.9.5.6)

Однако после этого вы предоставлены сами себе. :-)

person Tim    schedule 30.10.2009
comment
Первый аргумент setvbuf() — это дескриптор файла C, а не дескриптор файла. - person ruief; 18.01.2014
comment
Я использовал этот пример, и он работает, чтобы гарантировать, что библиотека C не читает из потока больше, чем необходимо, оставляя остальную часть потока нетронутой для последующих процессов в канале. - person mat_geek; 03.09.2014

Это невозможно, используя только стандартный ISO C. Однако вы можете попробовать использовать следующее:

#include <stdio.h>
void setbuf(FILE * restrict stream, char * restrict buf); 

и сопутствующие функции.

Однако лучше всего использовать библиотеку ncurses.

person dirkgently    schedule 30.10.2009
comment
Также есть достойные проклятия с открытым исходным кодом для окон; гугл курсес. Таким образом, вполне возможно кодировать против проклятий и в конечном итоге получить что-то работающее на всех платформах, о которых просит вопрошающий — я сделал это. - person asveikau; 30.10.2009