У меня есть следующая программа, которая в основном читает символы с клавиатуры (getch() делает это без необходимости нажимать «ENTER», функция взята отсюда: Захватывать символы из стандартного ввода, не дожидаясь нажатия клавиши ввода) , а затем, если char является одним из допустимых ходов (ВЛЕВО, ВПРАВО и т. д.), он записывает его в канал, из которого считывается draw.out.
draw.out считывает полученный ввод и выводит его на экран. (предположим, что эта программа работает нормально, я уверяю, что проблема только в следующем коде).
Проблема в том, что:
draw.out ведет себя так, будто получает мой ввод снова и снова. Это означает, что по какой-то причине, хотя я нажимаю, например, клавишу DOWN только один раз, он отправляет draw.out, как если бы я нажимал на него много раз.
После отправки одного ввода больше отправить не могу, как будто цикл останавливается.
Пытался ломать голову над этим много часов... Буду очень признателен за помощь.
int main(int argc, const char* argv[])
{
pid_t child_pid;
int fda[2];
if(pipe(fda)<0)
perror("pipe error");
if((child_pid=fork())<0)
perror("fork error");
else
{
//if we're in father
if(child_pid>0)
{
char c=' ';
//close read side
close(fda[0]);
while(c!=QUIT)
{
//get an instruction from keyboard
while(c!=ROTATE && c!=LEFT && c!=RIGHT &&
c!=DOWN && c!=QUIT)
{
c=getch();
}
//write the instruction to pipe
write(fda[1],&c,1);
//notify the child
kill(child_pid,SIGUSR2);
}
}
//if we're in child process
else
{
dup2(fda[0],0);
close(fda[0]);
close(fda[1]);
execl("./draw.out","./draw.out",NULL);
}
}
//close everything
close(fda[0]);
close(fda[1]);
return 0;
}
//this function works well in linux with tsch installed or in SSH bash shell
char getch()
{
char buf = 0;
struct termios old = {0};
if (tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
if (read(0, &buf, 1) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return (buf);
}