看看谁能用gcc实现这个不回显非阻塞键盘输入的超简单TC,VC程序,不是高手恐怕做不到

cxdzxc 2012-06-05 11:08:10
TC程序如下:
#include <stdio.h>
#define esc 27
main()
{
int key,i=1;
while(1)
{
printf("+");
sleep(1);
if (i++>=5)
{i=1;
system("cls");}
while(kbhit())
{
key=getch();
if (key==esc)
{exit (0);}
printf("%c ",key);
}
}
}


...全文
623 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
cxdzxc 2012-06-07
  • 打赏
  • 举报
回复
继续简化^_^
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#define esc 27

int main()
{
int key, i = 0;
system("stty -echo");
while (1)
{
printf("+");
sleep(1);
if (i++ >= 5)
{
i = 0;
printf("%c[2J", 27);
gotoxy(10, 5);
}
while (kbhit())
{
key = getch();
if (key == esc)
{
if (!kbhit() || getch() != '[')
exit(0);
}
printf("%c ", key);
}
}
}

int gotoxy(x, y)
{ printf("%c[%d;%dH",27,x,y);
}

int kbhit(void)
{
struct termios oldt, newt;
int ch, oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if (ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;
}

int getch(void)
{
return getchar();
}
cxdzxc 2012-06-07
  • 打赏
  • 举报
回复
没格式了,发个连接吧http://my.oschina.net/zengsai/blog/2975
cxdzxc 2012-06-07
  • 打赏
  • 举报
回复
谢谢楼上,找到了
一般人不知道的东西:来自 城市猎人

 

实为printf 函数的拓展应用

可设置字背景颜色;字体颜色m字符串

int ESC =27;

ptintf("%c[参数",ESC);

 


//cusor_ctrl.h #ifndef __CUSOR_CTRL_H_ #define __CUSOR_CTRL_H_ #include #include #define COLOR_RED 31 #define COLOR_BLACK 30 #define COLOR_GREEN 32 #define COLOR_BLUE 34 #define COLOR_YELLOW 33 #define COLOR_WHITE 37 #define COLOR_CYAN 36 #define COLOR_MAGENTA 35 int ESC = 27; //清屏 void clear_screen(void); //清除从光标位置到行末的内容 void clear_to_end(void); //光标移动到(x,y) void cusor_moveto(int x, int y); //保存光标位置 void cusor_get_pos(void); //恢复光标位置 void cusor_set_pos(void); //光标上移num行 void cusor_up(int num); //光标下移num行 void cusor_down(int num); //光标左移num个字符 void cusor_lift(int num); //光标右移num个字符 void cusor_right(int num); //设置前景颜色 void set_fg_color(int color); //设置背景颜色 void set_bg_color(int color); #endif //__CUSOR_CTRL_H_ int main() { int x=0;int y = 0; int color=31; clear_screen(); cusor_moveto(20,10); while(1) { cusor_get_pos(); printf("(20,10)"); fflush(stdout); sleep(1); cusor_up(5); sleep(1); cusor_down(5); sleep(1); cusor_right(5); sleep(1); cusor_lift(5); sleep(1); cusor_moveto(50,10); printf("(50,10)\n"); sleep(1); set_bg_color(COLOR_BLACK); set_fg_color(COLOR_RED); printf("\ngood morning\n"); sleep(1); set_bg_color(COLOR_YELLOW); set_fg_color(COLOR_GREEN); printf("gaorenwei\n"); cusor_set_pos(); } return 0; } void clear_screen(void) { printf("%c[2J",ESC); fflush(stdout); } void clear_to_end(void) { printf("%c[K",ESC); fflush(stdout); } void cusor_moveto(int x, int y) {// ESC[y;xH printf("%c[%d;%dH",ESC,y,x); fflush(stdout); } void cusor_get_pos(void) {// ESC[s printf("%c[s",ESC); fflush(stdout); } //恢复光标位置 void cusor_set_pos(void) {// ESC[u printf("%c[u",ESC); fflush(stdout); } //光标上移num行 void cusor_up(int num) { while(num--) { // up = ESC[A printf("%c[A",ESC); } fflush(stdout); } //光标下移num行 void cusor_down(int num) { while(num--) {// down = ESC[B printf("%c[B",ESC); } fflush(stdout);} //光标左移num个字符 void cusor_lift(int num) { while(num--) {// lift = ESC[D printf("%c[D",ESC); } fflush(stdout); } //光标右移num个字符 void cusor_right(int num) { while(num--) {// right = ESC[C printf("%c[C",ESC); } fflush(stdout); } //设置前景颜色 void set_fg_color(int color) {// ESC[#m printf("%c[%dm",ESC,color); fflush(stdout); } //设置背景颜色 void set_bg_color(int color) {// ESC[#m printf("%c[%dm",ESC,(color+10)); fflush(stdout); }
sevk 2012-06-07
  • 打赏
  • 举报
回复
[Quote=引用 46 楼 的回复:]

搜遍网络都找不到printf 中%c[ 控制符用法的完整介绍
[/Quote]

搜索: ANSI控制码
cxdzxc 2012-06-07
  • 打赏
  • 举报
回复
搜遍网络都找不到printf 中%c[ 控制符用法的完整介绍
cxdzxc 2012-06-07
  • 打赏
  • 举报
回复
在Linux下,有时需要在屏幕打印出带颜色的文字和光标移动到特定的坐标,如何实现呢,其实很简单,看下面的例子:
#include   <stdio.h>
#define   ESC           '\033 '
#define   WHITE       37
#define   RED           31
#define   YELLOW     33
#define   GREEN       32
#define   BLUE         34
#define   BROWN       35
#define   MEGEN       36
#define   GRAY         38
#define   HI_WHI     58
#define   HI_RED     39
#define   HI_YEL     52
#define   HI_GRE     51
#define   HI_BLU     53
#define   HI_BRO     54
#define   HI_MEG     55
#define   BLACK       30
#define   MAXX         80
#define   MAXY         25
void   my_setcol(int   color);
void   my_cancelcol();
void   my_moveto(int   x,   int   y);
void   my_setcol(int   color)
{
                printf( "%c[%dm ",ESC   ,   color);
}
void   my_cancelcol()
{
                printf( "%c[m ",ESC);
}
void   my_moveto(int   x,   int   y)
{
                if((x   <   MAXX)   &&   (y   <   MAXY))  
                                printf( "%c[%d;%dH ",   ESC,   y,   x);
}
int   main()
{
                printf( "Stopping   mypro:\t[   ");
                my_setcol(YELLOW);
                printf( "FAILED ");
                my_cancelcol();
                printf( "   ]\n ");
                printf( "Starting   tpcomm:\t[   ");
                my_setcol(GREEN);
                printf( "OK ");
                my_cancelcol();
                printf( "   ]\n ");
                my_moveto(20,   20);
                printf( "move   cursor   to   x,   y\n ");
                return   0;
}
Lactoferrin 2012-06-06
  • 打赏
  • 举报
回复
还想发什么,继续
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
重新整理,更加强大,gotoxy,kbhit,getch都有了,写字符模式下的贪吃蛇,俄罗斯方块都够用了,期待大牛写出更加简洁的函数模拟来
#include <stdio.h>  
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#define esc 27

int main()
{
int key,i=0;
system("stty -echo");
while(1)
{
printf("+");
sleep(1);
if (i++>=5)
{i=0;
printf("%c[2J",27);
gotoxy(10,5);
}
while(kbhit())
{
fflush(stdin);
key=getch();
if(key==esc)
{
if(!kbhit()||getch()!='[')exit(0);
}
printf("%c ",key); }
}
}

int gotoxy(x,y)
{printf("%c[%d;%dH",27,x,y);}

int kbhit(void)
{ struct termios oldt, newt;
int ch,oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{ ungetc(ch, stdin); return 1; }
return 0; }

int getch(void)
{
struct termios oldattr,newattr;
int ch;
tcgetattr(STDIN_FILENO,&oldattr);
newattr=oldattr;
newattr.c_lflag &=~(ICANON|ECHO);
tcsetattr(STDIN_FILENO,TCSANOW,&newattr);
ch=getchar();
tcsetattr(STDIN_FILENO,TCSANOW,&oldattr);
return ch;
}
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
谢谢楼上大侠,还有点小问题,在这个程序里,如何让TAB键不跳格,回车不换行
Lactoferrin 2012-06-06
  • 打赏
  • 举报
回复
if(key==esc)
{
if(!kbhit()||getchar()!='[')exit(0);
}
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
上面的大侠,方向键避免触发esc键的代码麻烦也教一下呗,谢谢先
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
原来这样就可以去掉回显了
int main()
{
int key,i=1;
struct termios oldattr,newattr;
tcgetattr(STDIN_FILENO,&oldattr);
newattr=oldattr;
newattr.c_lflag &=~(ICANON|ECHO);
tcsetattr(STDIN_FILENO,TCSANOW,&newattr);

while(1)
{
printf("+");
sleep(1);
if (i++>=5)
{i=1;
system("clear");}
while(kbhit())
{
fflush(stdin);
key=getch();
if (key==esc)
{exit (0);}
printf("%c ",key); }
}
}
Lactoferrin 2012-06-06
  • 打赏
  • 举报
回复
int main()
{
int key,i=1; struct termios attr;

tcgetattr( STDIN_FILENO, attr );
attr.c_lflag &= ~( ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &attr );

while(1)
{
printf("+");
sleep(1);
if (i++>=5)
{i=1;
system("clear");}
while(kbhit())
{
key=getch();
if (key==esc)
{exit (0);}
printf("%c ",key); }
}
}
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
楼上能不能用下面的测试程序写个完整的呢
#define esc 27
int main()
{
int key,i=1;
while(1)
{
printf("+");
sleep(1);
if (i++>=5)
{i=1;
system("clear");}
while(kbhit())
{
key=getch();
if (key==esc)
{exit (0);}
printf("%c ",key); }
}
}
——这是测试代码
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
清除屏幕:printf("%c[2J",27);
光标跳转到屏幕x(1~25)行、y(1~80)列:printf("%c[%d;%dH",27,x,y);

getch这样的函数太垃圾了,在LINUX下可以控制一切输入函数是否会显,包括scanf、gets等,方法是:
禁止输入时回显:system("stty -echo");
允许输入时回显:system("stty echo");
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
总结整理下
#include <stdio.h>  
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#define esc 27

int main()
{
int key,i=1;
struct termios attr;
tcgetattr(STDIN_FILENO,&attr);
attr.c_lflag &=~(ICANON|ECHO);
tcsetattr(STDIN_FILENO,TCSANOW,&attr);

while(1)
{
printf("+");
sleep(1);
if (i++>=5)
{i=1;
system("clear");}
while(kbhit())
{
fflush(stdin);
key=getch();
if(key==esc)
{
if(!kbhit()||getch()!='[')exit(0);
}
printf("%c ",key); }
}
}

int kbhit(void)
{ struct termios oldt, newt;
int ch,oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{ ungetc(ch, stdin); return 1; }
return 0; }

int getch(void)
{
struct termios oldattr,newattr;
int ch;
tcgetattr(STDIN_FILENO,&oldattr);
newattr=oldattr;
newattr.c_lflag &=~(ICANON|ECHO);
tcsetattr(STDIN_FILENO,TCSANOW,&newattr);
ch=getchar();
tcsetattr(STDIN_FILENO,TCSANOW,&oldattr);
return ch;
}
Lactoferrin 2012-06-06
  • 打赏
  • 举报
回复
如果你不要回显,程序一开始就执行
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
因为终端的反应并不需要程序执行读终端的api,你程序while(1);时按键终端都会有反应,所以需要预先设定好
这个和windows不一样
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
/*
AUTHOR: zobayer
INSTRUCTION:
just make this file a header like "conio.h"
and use the getch() and getche() functions.
*/
#include <termios.h>
#include <unistd.h>
#include <stdio.h>

/* reads from keypress, doesn't echo */
int getch(void)
{
struct termios oldattr, newattr;
int ch;
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
return ch;
}

/* reads from keypress, echoes */
int getche(void)
{
struct termios oldattr, newattr;
int ch;
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
return ch;
}

这段由网络上复制过来,中间有非法字符,去掉非法字符,可以编译过,但还是有回显,另外方向键和功能键问题依然存在
  • 打赏
  • 举报
回复
核心不就是要自己实现 kbhit和getch嘛,给你贴段代码。


/**
* file encode: UTF-8
* date: 12-03-2010
* author: Vincent
* msn:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <string.h>

/**********************************
* defination *
**********************************/
#define ESC 27
#define ENTER 10
#define BACKSPACE 127

static struct termios initial_settings, new_settings;
static int peek_character = -1;

void init_keyboard();
void close_keyboard();
int kbhit();
int readch();


/*******************************
* implementation *
*******************************/
int main(int argc, char* argv[])
{
int ch;
ch = 0;
init_keyboard();
while(ESC != ch)
{
if(kbhit())
{
ch = readch();
switch(ch)
{
case ESC:
break;
}
}
}
close_keyboard();
return 0;
}


void init_keyboard()
{
tcgetattr(0, &initial_settings);
new_settings = initial_settings;
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
new_settings.c_lflag &= ~ISIG;
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &new_settings);
return;
}

void close_keyboard()
{
tcsetattr(0, TCSANOW, &initial_settings);
return;
}

int kbhit()
{
char ch;
int nread;

if(-1 != peek_character)
{
return 1;
}
new_settings.c_cc[VMIN] = 0;
tcsetattr(0, TCSANOW, &new_settings);
nread = read(0, &ch, 1);
new_settings.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &new_settings);
if(1 == nread)
{
peek_character = ch;
return 1;
}
return 0;
}

int readch()
{
char ch;

if(-1 != peek_character)
{
ch = peek_character;
peek_character = -1;
return ch;
}
read(0, &ch, 1);
return ch;
}



readch就是getch 以前写的代码提取出来的,要给分。
cxdzxc 2012-06-06
  • 打赏
  • 举报
回复
12楼说错了,用的getchar是有回显的,等大虾来解决getch的模拟
加载更多回复(28)

69,381

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧