【问题标题】:How to do nonblocking input from stdin in C [duplicate]如何在C中从stdin进行非阻塞输入[重复]
【发布时间】:2016-05-18 18:46:20
【问题描述】:

我有以下情况我有一个程序连续对文件进行一组操作,我希望在按下特定键时停止并执行另一组操作。

为此,我尝试使用带有

的字符的scanf

fcntl(0, F_SETFL, O_NONBLOCK);

while(feof(stdin))

但它没有按预期工作。

我搜索过,在某些地方有人说要使用select,但我找不到如何使用它。

谁能给我一些建议?

我的主要功能提供更多信息:

int main(int argc, char *argv[])
{


 if(argc>1){
  char* password;
  char* password2;

  printf("Password? ");
  password = get_password();
  printf("Repita a password? ");
  password2 = get_password();

  if(strcmp(password,password2)!=0){
   printf("Passwords diferentes!\n");
   exit(1);
  }

  FILE *fptr;
  fptr = fopen("./regist", "r");
  if(fptr == NULL) //if file does not exist, create it
  {
   fptr = fopen("./regist", "w");
  }
  fclose(fptr);

  if(find_username(argv[1])){
   printf("Utilizador ja existe\n");
   exit(1);
  }
  add_user_regist(argv[1],password);
  printf("Utilizador %s adicionado.\n",argv[1]);
  exit(0);
 }


 char readbuf[250];

 /* Create the FIFO if it does not exist */
 umask(0);
 mknod(FIFO_FILE, S_IFIFO|0666, 0);
 printf("Servidor iniciado.\nEm modo de espera de mensagens\n");

 fcntl(0, F_SETFL, O_NONBLOCK);
 while(1){


  char c = getchar();
  if(c=='q' || c=='Q')
    exit(0);//by now only goes out


  fp = fopen(FIFO_FILE, "r");
  fgets(readbuf, 250, fp);
  fclose(fp);

  if(readbuf[0]=='U')
    user_access(readbuf);
  else if(readbuf[0]=='W')
    who_online(readbuf);
  else if(readbuf[0]=='R'){
    char* tmp;
    strtok(readbuf,":");
    tmp = strtok(NULL,";");
    remove_online(tmp);
    printf("# %s fez logout\n",tmp);
  }
  else if(readbuf[0]=='F'){
    process_msg(readbuf);
  }

 }
 return(0);
}

【问题讨论】:

  • 在什么操作系统上?这改变了答案
  • 发布您的代码。为什么使用fcntl 不起作用?
  • linux ,我使用的 fcntl 但是当我按下“Q”时,我的键是什么,scanf 可能不会继续进行第一次操作
  • 如果你在 linux 上使用类似 SIGINT 的信号可能会很有趣。当您按 ctrl-c 时,您将收到此信号。
  • 您希望while(feof(stdin)) 做什么?如果您需要getch 函数,请参阅my answer here

标签: c linux ubuntu-14.04 stdin nonblocking


【解决方案1】:

查看NCurses,这是任何高级终端软件的首选库。

除其他外,它还为您提供执行“原始”终端 I/O 的工具——使用 int getch( void ),通过 int nodelay( WINDOWS * win, bool bf ) 进行非阻塞调用。

这块:

#include <ncurses.h>

int main()
{
    initscr();
    printw( "Press a key:\n" );
    int c = getch();
    endwin();
}

这不会(如果没有待处理的输入,则返回 ERR):

#include <ncurses.h>

int main()
{
    initscr();
    printw( "Press a key:\n" );
    nodelay( stdscr, TRUE );
    int c = getch();
    endwin();
}

请注意,NCurses 带有自己的一组 I/O 函数,您必须使用这些函数而不是 &lt;stdio.h&gt; 函数(查看上面的 printw())。

【讨论】:

  • 是的,这就是答案。并使用 fork 创建一个完成这项工作的子进程,同时在主进程中检查输入。如果用户按下一个键,只需杀死另一个进程。
【解决方案2】:

使用GNU Readline 替代termios/ncurses:

#include <readline/readline.h>
#include <stdio.h>

static int func(int count, int key)
{
    printf ("key pressed: %c\n", key); /* exec your function */
    return 0;
}

int main(void)
{
    char *line;

    rl_bind_key('x', func); /* 'x' is the specific key */
    line = readline ("> ");
    printf("%s\n", line);
    return 0;
}

使用-lreadline编译

【讨论】:

  • 几乎解决了我的问题,但是如果我在 func 上使用 Exit(0) ,在程序执行控制台输入被阻止后
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-10
  • 2010-10-01
  • 2015-07-24
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多