講解了終端的基本控制方法,通過五個例子一步一步完善,最終形成了完善的終端控制例程.
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?