challenge 出力の一時停止と再開

起動すると、標準出力に1秒毎に'a'の1文字を出力し続けるプログラムで、 以下の条件を満たすものを「どう書く?」

  • 'q'キーが押されるとプログラムは終了する
  • 出力中に'p'キーが押されると一時停止する
  • 一時停止中に'p'キーが押されると出力を再開する

Posted feedbacks - C

適当に拡張性を考えて書いてみた。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <conio.h>
#include <time.h>

#define STATE_RUN  0
#define STATE_WAIT 1
#define STATE_QUIT 2


int main(){
    time_t now,last;
    int c;
    int state=STATE_RUN;
    
    last=time(NULL);
    do{
        if(kbhit()){
            c=getch();
            switch(c){
            case 'q':
                state=STATE_QUIT;
                break;
            case 'p':
                if(state==STATE_RUN){
                    state=STATE_WAIT;
                }else{
                    state=STATE_RUN;
                }
            }
        }
        
        switch(state){
        case STATE_RUN:
            now=time(NULL);
            if(last-now!=0){
                last=now;
                printf("a");
                fflush(stdout);
            }
        }
    }while(state!=STATE_QUIT);
    
    return 0;
}

ども、raynstardです。
入力がブロッキングされてしまうのは
入力モードを変更してあげないからですね。

UNIXでgetche()の作り方というのを調べるといろいろと出てくると思います。
ポイントはtermiosでカノニカルモードを解除してあげていることと
標準出力のバッファリングをなしにしているところでしょうか?
標準入力の方はおまけです。
// gcc -Wall -std=c99 doukaku179.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
#include <stdbool.h>
#include <termios.h>
#include <time.h>

static struct termios termios_save;
static bool isContinued = true;
static bool enableOutputScreen = true;

int initKeyInput(void)
{
    struct termios t;
    tcgetattr(0, &termios_save);
    tcgetattr(0, &t);
    t.c_lflag &= ~(ICANON|ECHO);
    t.c_cc[VMIN]  = 0;
    t.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &t);
    setvbuf(stdin, NULL, _IONBF, 0);
    return 0;
}

int main(int argc, char *argv[])
{
    char key;
    ssize_t read_size;
    time_t old, now;

    initKeyInput();
    setvbuf(stdout, NULL, _IONBF, 0);

    old = 0;
    while( isContinued )
    {
        now = time(NULL);
        if( now != old )
        {
            old = now;
            if( enableOutputScreen == true )
            {
                printf("a");
            }
        }
        read_size = fread(&key, 1, sizeof(key), stdin);
        if( read_size > 0 )
        {
            switch( key )
            {
                case 'q':   /* quit */
                    isContinued = false;
                    break;
                case 'p':   /* pause */
                    enableOutputScreen = (enableOutputScreen != true);
                    break;
                default:
                    break;
            }
        }
    }
    tcsetattr(0, TCSANOW, &termios_save);
    printf("\n");
    return 0;
}
/* EOF */

手抜きです。Unix likeなシステム限定です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

void cleanup(void)
{
    system("stty sane");
    putc('\n', stderr);
}
int waitfor(int fd, int secs)
{
    fd_set fds;
    struct timeval tv = { secs, 0 };
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    return select(fd + 1, &fds, 0, 0, secs > 0 ? &tv : 0);
}
int main(void)
{
    int c = 0, timeout = 1;
    system("stty raw");
    atexit(cleanup);
    while (c != 'q')
        if (!waitfor(fileno(stdin), timeout))
            putc('a', stderr);
        else if ((c = getchar()) == 'p')
            timeout *= -1;
    return 0;
}

Index

Feed

Other

Link

Pathtraq

loading...