LINUX.ORG.RU

Консольная программа завершается при вызове getchar() и нажатии Enter/стрелок

 , , ,


0

2

В общем, есть один код.
И когда я тыкаю Enter, программа завершается, вместо того, чтобы записать код клавиши в переменную int ch.
Программа запущена в эмуляторе терминала под Debian.
ЧЯДНТ?
Компьютера с этим багом под рукой нет, но если дело именно в нём - то, предположительно, с чем могут быть проблемы?

#include <termios.h>
#include <unistd.h>

int getCharacterCode() {
    struct termios  oldTerminalSettings,
                    newTerminalSettings;
    int ch;
    tcgetattr( STDIN_FILENO, &oldTerminalSettings );
    newTerminalSettings = oldTerminalSettings;
    newTerminalSettings.c_lflag &= ~( ICANON | ECHO);
    tcsetattr( STDIN_FILENO, TCSANOW, &newTerminalSettings );
    ch = getchar();
    tcsetattr( STDIN_FILENO, TCSANOW, &oldTerminalSettings );
return ch;
}



Последнее исправление: cetjs2 (всего исправлений: 1)

Завершается с сегфолтом или с каким кодом звершения? И вобще это подпрограмма, а где основная программа и как определено, что в ch ничего не заносится?

mky ★★★★★
()

setbuf(stdout,NULL);
setbuf(stdin,NULL);

int getCharacterCode(){..............,

Dron ★★★★★
()
Последнее исправление: Dron (всего исправлений: 2)
Ответ на: комментарий от mky

В основной программе происходит только вот это

    int pressed_button = 0; //нажатая клавиша
    pressed_button = getCharacterCode();
и несколько сравнений с целыми числами.
Код завершения не помню, завтра проверю. По-моему, его вообще не было. (хз, как так возможно)
Думаю, что дело в моих кривых руках и неправильном коде.

MarisaLovesUsAll
() автор топика
Ответ на: комментарий от MarisaLovesUsAll

Код завершения программы есть всегда, только он передаётся родительскому процессу, допустим bash'у. Выводится он так:

/bin/false ; echo $?

Вместо /bin/false пишете имя своей программы. Если она звершается с ошибкой (сегфолтом) то код завешения > 128.

и несколько сравнений с целыми числами.

По этим сравнениям что-то печатается?

mky ★★★★★
()

А select где?

Держи:

/**
 * Read character from console without echo
 * @return char readed
 */
int read_console(){
	int rb;
	struct timeval tv;
	int retval;
	fd_set rfds;
	FD_ZERO(&rfds);
	FD_SET(STDIN_FILENO, &rfds);
	tv.tv_sec = 0; tv.tv_usec = 10000;
	retval = select(1, &rfds, NULL, NULL, &tv);
	if(!retval) rb = 0;
	else {
		if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
		else rb = 0;
	}
	return rb;
}

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Да, вначале, ессно, настроить консоль:

// initial setup:
void setup_con(){
	tcgetattr(STDIN_FILENO, &oldt);
	newt = oldt;
	newt.c_lflag &= ~(ICANON | ECHO);
	if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0) quit(-2);
}
Eddy_Em ☆☆☆☆☆
()

В общем, так и не разобрался с терминалом.
Enter кое-как удалось укротить, но стрелки по-прежнему делают программу вылетать.
Мне нужно отловить код стрелок в терминале.
Они не отлавливаются, а просто выкидывают в командную строку (с проставленным ~( ICANON | ECHO)).
Забыл сказать спасибо за приведённые решения, однако мне нужен просто аналог getch(), он так же должен приостанавливать программу и ловить код одной клавиши.

MarisaLovesUsAll
() автор топика
Ответ на: комментарий от Extraterrestrial

ncurses заюзать религия не позволяет?

Ага. Хотел только на стандартной либе.

Впрочем, внезапно разобрался. Надо было натыкать побольше getchar'ов и поставить system(«stty raw»);. Прошу прощения за беспокойство.

MarisaLovesUsAll
() автор топика
Ответ на: комментарий от MarisaLovesUsAll

system(«stty raw»)

Я тебе выше приводил пример, как перевести в нужный режим консоль. Главное — перехватывать сигналы, чтобы даже по ctrl+C твоя программулинка успевала до смерти вернуть консоль в нормальный режим (иначе придется вслепую набирать reset).

А еще, если тебе нужно контролировать асинхронный ввод, фигачь свой велосипедный getch() на select/eselect/poll.

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.