getch и putchar не работают без возврата

Я безуспешно пытался заставить getch работать в другой программе. Итак, я сделал самую простую программу, которую только мог, используя getch так, как я хочу, чтобы она работала в основной программе.

Я исследовал потребность в noecho, cbreak, initscr и nodelay, я также пытался использовать newscr(), но безуспешно.

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

abc  
   def
      ghi

Я искал ответ, но снова в тупике...

#include <stdio.h>
#include <ncurses.h>

int main()
  {
     initscr();cbreak(); noecho();nodelay(stdscr,0);
    char c ;
    while((c=getch())!=EOF){
    putchar(c);}

    return 0;
  }

person UNECS    schedule 21.04.2012    source источник
comment
Если вам интересно, почему я это делаю, я пытаюсь получить ввод со стандартного ввода и печатать только в непустые строки стандартного вывода.   -  person UNECS    schedule 21.04.2012
comment
Если вы просто хотите реализовать текстовый фильтр, очень плохой идеей будет управление терминалом через curses. Интерактивный посимвольный ввод не имеет ничего общего с проблемой фильтрации пустых строк.   -  person Kaz    schedule 21.04.2012
comment
Чтобы скопировать непустые строки из стандартного ввода в стандартный вывод, попробуйте grep '.'. Я могу заверить вас, что он не использует ncurses.   -  person Kaz    schedule 21.04.2012
comment
@Каз; Я успешно использовал посимвольную фильтрацию с перенаправленным файлом stdin, но при использовании его только с stdin терминал повторяет stdin, который мне не нужен. Итак, почему я пытаюсь управлять терминалом   -  person UNECS    schedule 21.04.2012
comment
Все стандартные инструменты обработки текста будут повторять ввод. Это полезная и хорошая вещь. sed, awk, grep, сколько угодно. Эхо не влияет на работу; это просто локальная обратная связь в драйвере TTY операционной системы, которая позволяет вам видеть, что, черт возьми, вы печатаете.   -  person Kaz    schedule 21.04.2012
comment
@Каз; Чего я не хочу в данном случае. Спасибо в любом случае.   -  person UNECS    schedule 21.04.2012
comment
Кстати, вы должны читать getch() в int, а не в char. stackoverflow .com/questions/8464030/   -  person HostileFork says dont trust SE    schedule 21.04.2012
comment
+1 за то, что сказал, что это домашнее задание. Я не могу комментировать дальше paulsm4. Ищите курсоры.   -  person Ed Heal    schedule 21.04.2012
comment
@Эд Хил; что ж, это выходит далеко за рамки обязательной домашней работы, но я ненавижу, когда что-то не работает так, как я хочу, поэтому я трачу кучу дополнительного времени на то, что я, вероятно, даже не буду отправлять ..   -  person UNECS    schedule 21.04.2012


Ответы (2)


Вы не видите вывод, потому что ваш поток stdout буферизован построчно.

Ваша программа правильно получает отдельные символы; но выходной поток буферизует их.

Попробуйте fflush(stdout); или переключите stdout в небуферизованный режим с помощью setbuf(stdout, NULL);.

Проблема с отключением буферизации заключается в том, что она неэффективна для обработки больших объемов данных, когда вывод не является терминалом.

Вы можете сделать это условным, если стандартный вывод является tty:

if (isatty(fileno(stdout)))  /* #include <unistd.h> */
  setbuf(stdout, NULL);

Чтобы вернуть курсор в начало строки, нужно поставить возврат каретки \r. Это связано с тем, что режим curses cbreak отключил режим ONLCR tty (на выходе при отправке NL добавляется CR).

Если вы безоговорочно добавите \r, то он появится в файлах при перенаправлении вашего вывода. Итак, вам снова понадобится isatty лайфхак.

Гораздо лучше было бы научиться использовать функции tcgetattr и tcsetattr для точного управления конкретными параметрами tty, если все, что вам нужно, это выполнять посимвольный ввод без эха, а не разрабатывать интерактивную программу на основе curses. .

Вы действительно хотите ввод символов за раз или просто отключите эхо? Отключить эхо легко. Вызовите tcgetattr, чтобы заполнить struct termios текущими настройками файлового дескриптора 0 (если это tty). Переверните некоторые флаги, чтобы отключить эхо, затем вызовите tcsetattr, чтобы установить обновленную структуру. Когда ваша программа завершится, будьте любезны и верните исходную. Сделанный.

person Kaz    schedule 21.04.2012
comment
Но это не решит проблему отсутствия возврата каретки. Я обновил ответ, указав больше. - person Kaz; 21.04.2012
comment
Спасибо, я посмотрю на них, это, вероятно, будет намного менее небрежно, чем то, как я это делаю. p.s. if((c == '\n'))putchar('\r');} работает, но очень дерьмовый код, который я знаю. - person UNECS; 21.04.2012
comment
;Спасибо, у меня все получилось с tcsetattr как во сне после многих гуглов о том, как установить флаги Ура. - person UNECS; 21.04.2012

Да, ncurses — хороший способ получить посимвольное управление.

И да, вы должны вызывать "initscr()" и "cbreak()".

ПРЕДЛОЖЕНИЯ:

1) Сравните свой код с этим ncurses "hello world":

#include <ncurses.h>

int main()
{   
    initscr();          /* Start curses mode          */
    printw("Hello World !!!");  /* Print Hello World          */
    refresh();          /* Print it on to the real screen */
    getch();            /* Wait for user input */
    endwin();           /* End curses mode        */

    return 0;
}

2) Посмотрите, что произойдет, если вы выполните «обновление()» и/или удалите «noecho()».

3) В этом руководстве есть много полезной информации, которая также может помочь:

http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

person paulsm4    schedule 21.04.2012
comment
Спасибо. Добавлено в закладки, и я явно не понял, что такое окно. - person UNECS; 21.04.2012
comment
Привет - Каз прав. Если вам нужен терминальный контроль для приложения в текстовом режиме, Ncurses — хороший выбор. Если вы хотите, чтобы простой фильтр удалял пустые строки (как вы объяснили позже), просто используйте sed или grep. Например: cat myfile|grep '.' - person paulsm4; 21.04.2012
comment
Я бы использовал кошку ... но это для домашнего задания, поэтому нужно сделать фильтр. - person UNECS; 21.04.2012