Page 3 of 4

Re: getchar() ищется

PostPosted: 18 Jan 2013, 16:20
by fk0
Дезсофт, ты не прав. В буханках профессионального уровня всё сложней, чем в этих ваших любительских виндах. gets() вообще рискует сразу получить строку, причём с учётом всех редактирований пользователя (трололо!) Фишка в том, что драйвер компорта (ну заодно и клавиатуры с консолью -- типичнейший же компорт) умеет работать в cooked режиме, когда сам всё делает, и на запрос read() отдаёт уже строки. При этом, при вводе юзер может редактировать. Круто? На самом деле нифига не круто, потому, что большинство программ где это действительно нужно вызывают какой-нибудь libreadline, а тот в свою очередь read(). А fread, gets, getchar и т.п. для клавиатурного ввода никто в трезвом уме не юзает (стандартная C библиотека и неблокирующее чтение -- несовместимые понятия). Хотя если блокировка некритична, то getchar таки можно. Но вторая засада. Будет EOF. Если ввод таки неблокирующий. И нужно делать fseek на конец потока для повторения (по крайней мере такие грабли в newlib). Короче на ввод библиотека C вообще ни к месту, read() сам читает, причём и с таймаутом умеет (для компортов и консолей) и редактировать (ну правда там примитивно, не libreadline) умеет.

Re: getchar() ищется

PostPosted: 18 Jan 2013, 16:32
by deathsoft
seek и fseek ни для консолей ни для ком порта не поддерживаются, это чарактер девайсы, а не блок девайсы, ровно как и для пайпов сик тоже не поддерживается. Ридлайн тупо читает сразу в буфер а дальше позволяет содержимое этого буфера редактировать.

Re: getchar() ищется

PostPosted: 19 Jan 2013, 08:19
by fk0
seek не поддерживается, а fseek(SEEK_END) внутри libc сбрасывает признак EOF и можно читать дальше. для сокетов seek(2) же может работать, это у Робачевского кажись пример в книге был. Можно нарваться, man 3 fopen:

Reads and writes may be intermixed on read/write streams in any order, and do not require an intermediate seek as in previous versions of stdio....
...however ANSI C requires that a file positioning function intervene between output and input, unless an input operation encounters end-of-file...

Это кстати одна из причин, почему нет одного файла stdio, а есть stdin отдельно, и stdout отдельно, хотя у них одинаковый fileno().

newlib видимо придерживается стандарта, GNU libc и многие другие кладут болт.

Re: getchar() ищется

PostPosted: 19 Jan 2013, 08:21
by fk0
Хотя проще не использовать C библиотеку для чтения вообще, повторюсь, IMHO. От неё толку совсем мало. На вывод ещё удобно, из-за printf и буферизации.

Я не про readline, а про то, что read(STDIN_FILENO, buffer, sizeof(buffer)) в буханке выдасть строку разом. Её даже примитивно редактировать можно.

Re: getchar() ищется

PostPosted: 19 Jan 2013, 09:21
by deathsoft
fk0, к чему все это? DimkaM спрашивал как кнопки стрелок и прочего опрашивать, в досе и венде для этого есть conio.h и функция getch() http://msdn.microsoft.com/en-us/library/078sfkak(VS.80).aspx которая ни с какими файлами не связана вообще, а читает напрямую коды кнопок (в досе через int 16, в венде через функции работы с клавиатурой), для расширенных кнопок читает 0, а потом код расширенной кнопки при втором чтении. И на спектруме реализуется элементарно, прямо через порты клавиатуры, ну либо через трансляцию скан кодов от пс2/клавы. А работа с клавиатурой как с файлом на спектруме нах не всралась, лишнее абстрактное усложнение, которое тут совершенно не нужно (это не буханка).

В буханке аналога getch() нету, чтобы его написать надо ебаца с ioctl терминала, и переключать его из режима в режим.

Примерно вот таким говнокодом (более того, стрелки обрабатывать наверняка не будет) (авторство не мое):
Code: Select all
int mygetch( )
{
struct termios oldt,
newt;
int ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}

Re: getchar() ищется

PostPosted: 19 Jan 2013, 09:44
by fk0
У Димки нету доса. Он хочет сделать своё. Чтоб сделать своё неплохо бы знать, как сделано у других и почему. А он как в сюжете "старика Хоттабыча" копирует форму без того, чтобы иметь представление о содержимом (телефон из цельного куска мрамора). Димке стоило бы почитать книжку хоть какую, как там ОС устроена, как программы работают и т.п.

Усложнение не "всралось" а принципиально -- это позволяет перенаправление ввода-вывода. Даже в CP/M было. Ввод там был из файла CON:, но подсунуть можно было что-то другое. Иначе аналог more или less не сделать, как минимум. Удалённая работа невозможна. Вообще параллельная работа программ (клавиатура одна же). Управление процессами, кстати. Ctrl-C или Ctrl-| отнюдь не самой программой обрабатываются, как и Ctrl-S и Ctrl-Q. И Ctrl-Z ещё.

А для стрелок нужно написать свой аналог readline. А без стрелок, повторюсь, это драйвер "компорта" делает. Умеет удалять символы и целые слова, умеет выводить эхо от ввода.

Re: getchar() ищется

PostPosted: 19 Jan 2013, 09:50
by fk0
Говнокод кстати. На каждую букву перетрахивать драйвер tty? Один раз делается. Перехватываются SIGINT и т.п. и на выходе восстанавливается. Для стрелок нужно уметь понимать какой текущий терминал (getenv("TERM")) и в зависимости от серии кодов уж понимать код клавиши. Или вводимый символ, тоже от серии, ибо UTF-8. В последнем случае библиотека немного помогает (mbrtowc и т.п.) Геморой? геморой. И это причина, почему cooked режим построчного ввода предлагаемый по-умолчанию не так уж и плох. Всё за тебя сделано. Не так круто, без стрелок, но сразу работает (да, драйвер компорта в ведре умеет UTF-8).

Re: getchar() ищется

PostPosted: 19 Jan 2013, 09:51
by fk0
Кстати если !isatty(stdin), то libreadline должна плюнуть на стрелки и читать как есть (т.е. она не нужна).

Re: getchar() ищется

PostPosted: 19 Jan 2013, 09:52
by fk0
В той же винде микрософтовская libc читает не из клавиатуры, а из "консоли". Типа файла такого. Который у каждого процесса свой. И с физической клавиатурой никак не связан. А то нажал на кнопку: и во всех консольных программах ввод пошёл. Бред же.

Re: getchar() ищется

PostPosted: 19 Jan 2013, 12:03
by deathsoft
Вопервых консоль это не файл, во вторых ввод с консоли через getch() никуда не редиректится, также как и вывод через cprintf() (в досе это был прямой ввод с клавиатуры и вывод на экран, через прерывания биоса минуя дос и его обработчики файловых дескрипторов, в винде сделано аналогично).