getchar() ищется

Programs, sources, embedded, demomaking, whatsoever related to subj :)

Postby fk0 » 18 Jan 2013, 16:20

Дезсофт, ты не прав. В буханках профессионального уровня всё сложней, чем в этих ваших любительских виндах. gets() вообще рискует сразу получить строку, причём с учётом всех редактирований пользователя (трололо!) Фишка в том, что драйвер компорта (ну заодно и клавиатуры с консолью -- типичнейший же компорт) умеет работать в cooked режиме, когда сам всё делает, и на запрос read() отдаёт уже строки. При этом, при вводе юзер может редактировать. Круто? На самом деле нифига не круто, потому, что большинство программ где это действительно нужно вызывают какой-нибудь libreadline, а тот в свою очередь read(). А fread, gets, getchar и т.п. для клавиатурного ввода никто в трезвом уме не юзает (стандартная C библиотека и неблокирующее чтение -- несовместимые понятия). Хотя если блокировка некритична, то getchar таки можно. Но вторая засада. Будет EOF. Если ввод таки неблокирующий. И нужно делать fseek на конец потока для повторения (по крайней мере такие грабли в newlib). Короче на ввод библиотека C вообще ни к месту, read() сам читает, причём и с таймаутом умеет (для компортов и консолей) и редактировать (ну правда там примитивно, не libreadline) умеет.
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby deathsoft » 18 Jan 2013, 16:32

seek и fseek ни для консолей ни для ком порта не поддерживаются, это чарактер девайсы, а не блок девайсы, ровно как и для пайпов сик тоже не поддерживается. Ридлайн тупо читает сразу в буфер а дальше позволяет содержимое этого буфера редактировать.
User avatar
deathsoft
 
Posts: 4744
Joined: 07 Apr 2007, 00:58
Group: Registered users

Postby fk0 » 19 Jan 2013, 08:19

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 и многие другие кладут болт.
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby fk0 » 19 Jan 2013, 08:21

Хотя проще не использовать C библиотеку для чтения вообще, повторюсь, IMHO. От неё толку совсем мало. На вывод ещё удобно, из-за printf и буферизации.

Я не про readline, а про то, что read(STDIN_FILENO, buffer, sizeof(buffer)) в буханке выдасть строку разом. Её даже примитивно редактировать можно.
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby deathsoft » 19 Jan 2013, 09:21

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;
}
User avatar
deathsoft
 
Posts: 4744
Joined: 07 Apr 2007, 00:58
Group: Registered users

Postby fk0 » 19 Jan 2013, 09:44

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

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

А для стрелок нужно написать свой аналог readline. А без стрелок, повторюсь, это драйвер "компорта" делает. Умеет удалять символы и целые слова, умеет выводить эхо от ввода.
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby fk0 » 19 Jan 2013, 09:50

Говнокод кстати. На каждую букву перетрахивать драйвер tty? Один раз делается. Перехватываются SIGINT и т.п. и на выходе восстанавливается. Для стрелок нужно уметь понимать какой текущий терминал (getenv("TERM")) и в зависимости от серии кодов уж понимать код клавиши. Или вводимый символ, тоже от серии, ибо UTF-8. В последнем случае библиотека немного помогает (mbrtowc и т.п.) Геморой? геморой. И это причина, почему cooked режим построчного ввода предлагаемый по-умолчанию не так уж и плох. Всё за тебя сделано. Не так круто, без стрелок, но сразу работает (да, драйвер компорта в ведре умеет UTF-8).
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby fk0 » 19 Jan 2013, 09:51

Кстати если !isatty(stdin), то libreadline должна плюнуть на стрелки и читать как есть (т.е. она не нужна).
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby fk0 » 19 Jan 2013, 09:52

В той же винде микрософтовская libc читает не из клавиатуры, а из "консоли". Типа файла такого. Который у каждого процесса свой. И с физической клавиатурой никак не связан. А то нажал на кнопку: и во всех консольных программах ввод пошёл. Бред же.
* Origin: зип файл! (2:5030/1559)
User avatar
fk0
 
Posts: 1535
Joined: 07 Apr 2007, 01:08
Group: Registered users

Postby deathsoft » 19 Jan 2013, 12:03

Вопервых консоль это не файл, во вторых ввод с консоли через getch() никуда не редиректится, также как и вывод через cprintf() (в досе это был прямой ввод с клавиатуры и вывод на экран, через прерывания биоса минуя дос и его обработчики файловых дескрипторов, в винде сделано аналогично).
User avatar
deathsoft
 
Posts: 4744
Joined: 07 Apr 2007, 00:58
Group: Registered users

PreviousNext

Return to Coding

Who is online

Users browsing this forum: No registered users and 9 guests

cron