讲解了终端的基本控制方法,通过五个例子一步一步完善,最终形成了完善的终端控制例程.
1.play_again0.c
功能:读入用户输入,输入y 返回0,输入n 返回1
1 #include <stdio.h>
2 #include <termios.h>
3
4 #define QUESTION "Do you want another transaction"
5
6 int get_response(char *);
7
8 int main()
9 {
10 int response;
11 response = get_response(QUESTION);
12 if (response == 0)
13 printf("the char you put is y\n");
14 else
15 printf("the char you put is n\n");
16
17 return response;
18
19 }
20
21 int get_response(char *question)
22 {
23 printf("%s (y/n)?", question);
24 while(1)
25 {
26 switch(getchar())
27 {
28 case 'y':
29 case 'Y': return 0;
30 case 'n':
31 case 'N':
32 case EOF:return 1;
33
34 }
35 }
36 }
37
缺陷: -用户输入y 和n 后必须回车才能使程序接收输入
-输入非y 和n 的字符程序没有提示和处理
2, play_again1.c
功能:立即响应用户输入输入不合法,给出提示信息.
1 /*
2 * set tty into char -by char mode, read char, return result
3 * response the input immediately
4 */
5 #include <stdio.h>
6 #include <termios.h>
7
8 #define QUESTION "Do you want another transaction"
9
10 int get_response(char *);
11 void tty_mode(int );
12 void set_crmode();
13
14 int main()
15 {
16 int response;
17 tty_mode(0);
18 set_crmode();
19 response = get_response(QUESTION);
20 if (response == 0)
21 printf("\n the char you put is y\n");
22 else
23 printf("\n the char you put is n\n");
24
25 tty_mode(1);
26 return response;
27
28 }
29
30 int get_response(char *question)
31 {
32 printf("%s (y/n)?", question);
33 while(1)
34 {
35 switch(char input = getchar())
36 {
37 case 'y':
38 case 'Y': return 0;
39 case 'n':
40 case 'N':
41 case EOF:return 1;
42 default:
43 printf("\n cannot understatnd %c,", input);
44 printf("please type y or n \n");
45
46 }
47 }
48 }
49
50 void set_crmode()
51 /*
52 * put file descriptor 9 into char -by -char mode
53 * in common mode ,you can input 'stty -icanon' .
54 */
55 {
56 struct termios ttystate;
57 tcgetattr(0, &ttystate);
58 ttystate.c_lflag &= ~ICANON;
59 ttystate.c_cc[VMIN] = 1; //get 1 char at a time
60 tcsetattr(0, TCSANOW, &ttystate);
61 }
62
63 void tty_mode(int how)
64 {
65 static struct termios original_mode;
66 if (how==0)
67 tcgetattr(0, &original_mode);
68 else
69 tcsetattr(0, TCSANOW, &original_mode);
70
71 }
72
缺陷:每次给出提示,不友好,可以不显示用户输入
3,play_again2.c
功能:对于输入的字符不显示,当输入合法字符时正确返回
1 /*
2 * set tty into char -by char mode, read char, return result
3 * response the input immediately
4 * ingore non-y or non-n char
5 * todo: timeout if user walks away
6 */
7 #include <stdio.h>
8 #include <termios.h>
9
10 #define QUESTION "Do you want another transaction"
11
12 int get_response(char *);
13 void tty_mode(int );
14 void set_crmode();
15
16 int main()
17 {
18 int response;
19 tty_mode(0);
20 set_crmode();
21 response = get_response(QUESTION);
22 if (response == 0)
23 printf("\n the char you put is y\n");
24 else
25 printf("\n the char you put is n\n");
26
27 tty_mode(1);
28 return response;
29
30 }
31
32 int get_response(char *question)
33 {
34 char input;
35 printf("%s (y/n)?", question);
36 while(1)
37 {
38 switch(input = getchar())
39 {
40 case 'y':
41 case 'Y': return 0;
42 case 'n':
43 case 'N':
44 case EOF:return 1;
45 //default:
46 //printf("\n cannot understatnd %c,", input);
47 //printf("please type y or n \n");
48
49 }
50 }
51 }
52
53 void set_crmode()
54 /*
55 * put file descriptor 9 into char -by -char mode
56 * in common mode ,you can input 'stty -icanon' .
57 */
58 {
59 struct termios ttystate;
60 tcgetattr(0, &ttystate);
61 ttystate.c_lflag &= ~ICANON; //no buffering
62 ttystate.c_lflag &= ~ECHO; // no echo either
63 ttystate.c_cc[VMIN] = 1; //get 1 char at a time
64 tcsetattr(0, TCSANOW, &ttystate); //install settings
65 }
66
67 void tty_mode(int how)
68 {
69 static struct termios original_mode;
70 if (how==0)
71 tcgetattr(0, &original_mode);
72 else
73 tcsetattr(0, TCSANOW, &original_mode);
74
75 }
76
缺陷:当用户什么都没有输入时,程序还在运行
4.play_again3.c
功能:用户不输入时,程序超时退出
1 /*
2 * set tty into char -by char mode, read char, return result
3 * response the input immediately
4 * ingore non-y or non-n char
5 * add timeout machemism
6 * todo: reset terminal mode on interrupt
7 */
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <termios.h>
11 #include <fcntl.h>
12 #include <string.h>
13
14
15 #define QUESTION "Do you want another transaction"
16 #define TRIES 3
17 #define SLEEPTIME 2
18 #define BEEP putchar('\a')
19
20 int get_response(char *);
21 void tty_mode(int );
22 void set_crmode();
23 void set_nodelay_mode(); //timeout set
24
25 int main()
26 {
27 BEEP;
28
29 int response, maxtries;
30 maxtries = TRIES;
31 tty_mode(0);
32 set_crmode();
33 set_nodelay_mode();
34 response = get_response(QUESTION);
35 if (response == 0)
36 printf("\n the char you put is y\n");
37 else if (response == 1)
38 printf("\n the char you put is n\n");
39 else if (response == 2)
40 printf("\n timeout\n");
41
42 tty_mode(1);
43 return response;
44
45 }
46
47 char get_ok_char()
48 {
49 int c;
50 while( (c = getchar()) != EOF && strchr("yYNn", c) == NULL);
51 return c;
52 }
53 int get_response(char *question)
54 {
55 char input;
56 int maxtries = TRIES;
57 printf("%s (y/n)?", question);
58 fflush(stdout);
59 while(1)
60 {
61 sleep(SLEEPTIME);
62 //input = tolower(get_ok_char());
63 input = get_ok_char();
64 if (input == 'y') return 0;
65 if (input == 'n') return 1;
66 if (maxtries-- == 0) return 2;
67
68 BEEP;
69
70 }
71 }
72
73 void set_crmode()
74 /*
75 * put file descriptor 9 into char -by -char mode
76 * in common mode ,you can input 'stty -icanon' .
77 */
78 {
79 struct termios ttystate;
80 tcgetattr(0, &ttystate);
81 ttystate.c_lflag &= ~ICANON; //no buffering
82 ttystate.c_lflag &= ~ECHO; // no echo either
83 ttystate.c_cc[VMIN] = 1; //get 1 char at a time
84 tcsetattr(0, TCSANOW, &ttystate); //install settings
85 }
86
87 void tty_mode(int how)
88 {
89 static struct termios original_mode;
90 static int original_flags;
91 if (how==0){
92 tcgetattr(0, &original_mode);
93 original_flags = fcntl(0, F_GETFL);
94 }
95 else
96 {
97 tcsetattr(0, TCSANOW, &original_mode);
98 fcntl(0, F_SETFL, original_flags);
99 }
100
101 }
102
103 void set_nodelay_mode()
104 /*
105 * put file descriptor 9 into no-0delay mode
106 * use fcntl to set bits
107 * notes: tcsetattr() will do something similar, but it is complicated
108 */
109 {
110 int termflags;
111 termflags = fcntl(0, F_GETFL); // read curr. settings
112 termflags |= O_NDELAY;
113 fcntl(0, F_SETFL, termflags);
114 }
115
缺陷:如果用户通过ctrl-c中止程序,系统不能恢复到原来的状态
5.play_again4.c
功能:加入了信号处理
1 /*
2 * set tty into char -by char mode, read char, return result
3 * response the input immediately
4 * ingore non-y or non-n char
5 * add timeout machemism
6 * add reset terminal mode on interrupt
7 * ignore ctrl-C signal
8 */
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <termios.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <signal.h>
15
16 #define QUESTION "Do you want another transaction"
17 #define TRIES 3
18 #define SLEEPTIME 2
19 #define BEEP putchar('\a')
20
21 int get_response(char *);
22 void tty_mode(int );
23 void set_crmode();
24 void set_nodelay_mode(); //timeout set
25 void ctrl_c_handler(int signum);
26
27 int main()
28 {
29 BEEP;
30
31 int response, maxtries;
32 maxtries = TRIES;
33 tty_mode(0);
34 set_crmode();
35 set_nodelay_mode();
36 signal(SIGINT, ctrl_c_handler);
37 signal(SIGQUIT, SIG_IGN);
38 response = get_response(QUESTION);
39 if (response == 0)
40 printf("\n the char you put is y\n");
41 else if (response == 1)
42 printf("\n the char you put is n\n");
43 else if (response == 2)
44 printf("\n timeout\n");
45
46 tty_mode(1);
47 return response;
48
49 }
50
51 char get_ok_char()
52 {
53 int c;
54 while( (c = getchar()) != EOF && strchr("yYNn", c) == NULL);
55 return c;
56 }
57 int get_response(char *question)
58 {
59 char input;
60 int maxtries = TRIES;
61 printf("%s (y/n)?", question);
62 fflush(stdout);
63 while(1)
64 {
65 sleep(SLEEPTIME);
66 //input = tolower(get_ok_char());
67 input = get_ok_char();
68 if (input == 'y') return 0;
69 if (input == 'n') return 1;
70 if (maxtries-- == 0) return 2;
71
72 BEEP;
73
74 }
75 }
76
77 void set_crmode()
78 /*
79 * put file descriptor 9 into char -by -char mode
80 * in common mode ,you can input 'stty -icanon' .
81 */
82 {
83 struct termios ttystate;
84 tcgetattr(0, &ttystate);
85 ttystate.c_lflag &= ~ICANON; //no buffering
86 ttystate.c_lflag &= ~ECHO; // no echo either
87 ttystate.c_cc[VMIN] = 1; //get 1 char at a time
88 tcsetattr(0, TCSANOW, &ttystate); //install settings
89 }
90
91 void tty_mode(int how)
92 {
93 static struct termios original_mode;
94 static int original_flags;
95 if (how==0){
96 tcgetattr(0, &original_mode);
97 original_flags = fcntl(0, F_GETFL);
98 }
99 else
100 {
101 tcsetattr(0, TCSANOW, &original_mode);
102 fcntl(0, F_SETFL, original_flags);
103 }
104
105 }
106
107 void set_nodelay_mode()
108 /*
109 * put file descriptor 9 into no-0delay mode
110 * use fcntl to set bits
111 * notes: tcsetattr() will do something similar, but it is complicated
112 */
113 {
114 int termflags;
115 termflags = fcntl(0, F_GETFL); // read curr. settings
116 termflags |= O_NDELAY;
117 fcntl(0, F_SETFL, termflags);
118 }
119 void ctrl_c_handler(int signum)
120 {
121 //called if SIGINT is detected and reset tty and scram
122 tty_mode(1);
123 exit(1);
124 }
125