したがって、ユーザーが何かを入力するのを入力プロンプトが待機する時間を制御する方法が必要です。
たとえば、次のコードでは:
#include <stdio.h>
int main(void){
int i, value;
for (i=0;i<10;i++){
scanf(" %d", &value);
}
}
ユーザーが 5 秒後に何も入力しない場合、for ループを中断するようにプログラムを作成するにはどうすればよいですか?
の汎用バージョンは次のとおりです。魔女はscanf
、sync_scanf
選択した秒数待機するか-2
、タイムアウトとして返されます。
int sync_scanf(time_t sec, const char *format, ...);
例:
#include <stdio.h>
#include <stdarg.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int sync_scanf(time_t sec, const char *format, ...);
int main(int argc, char **argv) {
int i;
int value;
int ret;
for (i = 0 ; i < 10 ; i++ ) {
ret = sync_scanf(3, "%d", &value);
if( ret > 0 ) {
printf("OK %d\n", value);
} else if( ret == -2 ) {
printf("3 seconds passed and you typed nothing!\n");
break;
} else {
printf("No enough arguments\n");
break;
}
}
return 0;
}
int sync_scanf(time_t sec, const char *format, ...) {
int re;
va_list arg;
fd_set readfds;
struct timeval timeout = {0};
timeout.tv_sec = sec;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
re = select(1, &readfds, NULL, NULL, &timeout);
if( re == -1 ) {
perror("Error");
return -1;
}
else if( re == 0 ) {
return -2;
}
va_start(arg, format);
re = vfscanf(stdin, format, arg);
va_end(arg);
return re;
}
デモ:
$ gcc -Wall sample.c
$ ./a.out
232
OK 232
3 seconds passed and you typed nothing!
$ ./a.out
32
OK 32
fewf
No enough arguments
$
次のように機能しscanf
ますが、最初にタイムアウトを秒単位で渡します。
int sync_scanf(time_t sec, const char *format, ...);
戻り値:
-1
失敗したとき。-2
タイムアウト中。scanf
。select (入力が読み取り可能かどうかを確認するために stdin をしばらく監視する)、fgets (入力データをバッファーに安全に読み取る)、およびstrtol (可能であればバッファー文字列を long integer に変換する) を使用して、必要なものを実装できます。
サンプル コードを以下に示します (たとえば、エラー処理を拡張するには、man ページを確認してください)。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
fd_set rfds;
struct timeval tv;
int i, val, retval;
char *endptr, buff[255];
for (i=0;i<10;i++){
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1){
perror("select()");
exit(EXIT_FAILURE);
}
else if (retval){
/* FD_ISSET(0, &rfds) is true so input is available now. */
/* Read data from stdin using fgets. */
fgets(buff, sizeof(buff), stdin);
/* Convert data stored in the buffer to long int. */
errno = 0;
val = strtol(buff, &endptr, 10);
/* First, check for various possible errors. */
if (errno != 0 && val == 0) {
perror("strtol()");
exit(EXIT_FAILURE);
}
if (endptr == buff) {
fprintf(stderr, "No digits were found.\n");
exit(EXIT_FAILURE);
}
/* If we got here, strtol successfully parsed a number. */
printf("%d was read from stdin.\n", val);
}
else{
printf("No data within five seconds.\n");
break;
}
}
exit(EXIT_SUCCESS);
}