Parar um loop somente quando uma tecla for digitada [RESOLVIDO]

1. Parar um loop somente quando uma tecla for digitada [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 29/09/2018 - 23:31h

Olá, gostaria de saber como faço para parar um loop quando digitar uma determinada tecla e também como continuar rodando esse loop mesmo quando não pressionar nenhuma tecla. Alguém ai me dá........uma luz?




#include <ncurses.h>

//...código...e mais linhas de código...

int key;

printw("Pressione enter para sair do loop [Enter]");

while(true){

key=wgetch();

if(key==KEY_ENTER){

//...aqui acontece alguma coisa aqui e o loop é parado...
}

//...aqui acontece alguma coisa aqui...
}



O pedaço de código acima funciona, porém para continuar rodando o loop é necessário que alguma tecla diferente de enter seja digitada. Mas o que eu quero aqui é que o loop rode enquanto SOMENTE enter não for digitada.


Próximo da pilha: UNKNOWN


  


2. MELHOR RESPOSTA

Fernando
phoemur

(usa Debian)

Enviado em 30/09/2018 - 17:40h

Já experimentou trocar wgetch() por getch() ????
Já experimentou usar halfdelay(1) ou timeout (0) ou nodelay(stdscr, TRUE); nas opções de iniciar a janela???
______________________
https://github.com/phoemur

3. Re: Parar um loop somente quando uma tecla for digitada

Fernando
phoemur

(usa Debian)

Enviado em 30/09/2018 - 17:31h

Pelo que eu entendi da pergunta o problema é que

wgetch(); 


Bloqueia a execução do loop e fica esperando o usuário digitar alguma coisa.

Pra ter o efeito que ele quer só usando o Loop em uma nova Thread, assim dá pra ler sem bloquear o loop que está sendo executado.
Se não for isso me perdoe pois não entendi a pergunta.

Por exemplo algo assim em C++
Compilar com: g++ -o arquivo arquivo.cpp -lpthread

#include <atomic>
#include <chrono>
#include <future>
#include <iostream>
#include <string>

int main()
{
std::atomic<bool> flag {true};

// Loop em outra thread
auto loop = std::async(std::launch::async, [&flag](){
while (flag.load() == true)
{
std::cout << "Digite Enter para sair.\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});


std::string input;

if (std::getline(std::cin, input))
flag.store(false); //...aqui acontece alguma coisa aqui e o loop é parado...

loop.get(); // Join

return 0;
}


Agora que eu me lembre a biblioteca ncurses já tem funcionalidade pra fazer isso. Estuda lá que você acha.
Google this: "Ncurses non blocking getch"
Abraços
______________________
https://github.com/phoemur


4. Re: Parar um loop somente quando uma tecla for digitada [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 30/09/2018 - 18:22h

phoemur escreveu:

Pelo que eu entendi da pergunta o problema é que

wgetch(); 


Bloqueia a execução do loop e fica esperando o usuário digitar alguma coisa.

Pra ter o efeito que ele quer só usando o Loop em uma nova Thread, assim dá pra ler sem bloquear o loop que está sendo executado.
Se não for isso me perdoe pois não entendi a pergunta.


É exatamente isso que eu quero phoemur!

Desculpe por não ser mais explicativo em minha pergunta.



5. Re: Parar um loop somente quando uma tecla for digitada

Perfil removido
removido

(usa Nenhuma)

Enviado em 30/09/2018 - 18:24h

phoemur escreveu:

Agora que eu me lembre a biblioteca ncurses já tem funcionalidade pra fazer isso. Estuda lá que você acha.
Google this: "Ncurses non blocking getch"
Abraços
______________________
https://github.com/phoemur


Desculpe pela minha preguiça...é que as vezes fico desesperado por não achar o que eu quero e acabo apelando por fazer perguntas em forúns.
Assim que tiver tempo eu dou uma olhada melhor no tio google.

Obrigado!



6. Re: Parar um loop somente quando uma tecla for digitada

Perfil removido
removido

(usa Nenhuma)

Enviado em 30/09/2018 - 22:44h

Consegui fazer com nodelay!

Eis um código de exemplo:


#include <ncurses.h>

int main(void){

WINDOW *win=initscr();

start_color();

curs_set(0);
keypad(win, true);
nodelay(win, true);

init_pair(1, COLOR_WHITE, COLOR_BLACK);

mvwprintw(win, 1, 1, "Pressione enter para sair do loop [Enter]");

unsigned char key;

while(true){

key=wgetch(win);

if(key==10){

break;
}
}

delwin(win);
endwin();

return 0;
}


Agora eu não conseguir o mesmo efeito que está acima no código abaixo:


for(long int i=0; i<max; i+=cond){

key=wgetch(win);

if(key==10){ //Mesmo quando esse if é satisfeito o loop não para

break;
}

csockfd=accept(sockfd, (struct sockaddr*)&aux, &socklen);

if(csockfd!=-1){

count++;
info=realloc(info, count*hostInfoLen);
remoteAddr=realloc(remoteAddr, count*socklen);

remoteAddr[count-1]=aux;

if(info==NULL || remoteAddr==NULL){

free(info);
free(remoteAddr);

destroy(win, true);
exit(1);

}else{

add_host_info(&info[count-1], remoteAddr[count-1]);

list_ganados(win, info, count);
}
}

close(csockfd);
}


No código acima, para que o for seja parado é necessário que enter seja pressionado, porém, por algum motivo, a função accept parece continuar aguardando uma nova conexão vinda de um cliente mesmo que uma chamada para break tenha sido realizada.

Bem...alguém poderia me explicar como driblar esse "fenômeno"?


7. Re: Parar um loop somente quando uma tecla for digitada

Paulo
paulo1205

(usa Ubuntu)

Enviado em 01/10/2018 - 05:11h

timeout() e nodelay() afetam apenas outras funções da [n]curses, que não é o caso de accept().

A função accept() é blocante em sockets que não tenham sido marcados como não-blocantes. Se não quiser que ela fique parada esperando, você pode usar fcntl() para marcar o socket com O_NONBLOCK (e, nesse caso, accept() vai retornar -1 e ajustar errno com EAGAIN se não houver atividade no socket), ou você usa select(), poll() ou epoll() para testar se há atividade no socket ANTES de chamar accept().

Outras possibilidades são você usar múltiplas threads de execução (mas eu acho que isso pode dificultar seu programa, na medida em que você vai acabar tendo de inventar outro mecanismo de sincronização entre as duas linhas de execução) ou você pode envelopar a chamada a accept() com chamadas a alarm() (depois de ter definido um tratador para o sinal SIGALRM), de modo a aplicar um timeout para a chegada de nova conexão.

Num programa meu, eu iria de select() ou poll(). epoll() seria outra opção, mas como ela é exclusiva do Linux, eu prefiro ficar com coisas que sejam mais portáveis, especialmente num caso como o que você mostrou, em que desempenho de comunicação por rede não parece ser uma preocupação primordial.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts