LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1132|回复: 6

请教一个程序的逻辑,谢谢!

[复制链接]
发表于 2005-8-10 01:19:34 | 显示全部楼层 |阅读模式
有一个程序,他的运行逻辑我看了几遍,还是不太清楚。请大家指点一下,十分感谢!

程序比较长,但应该不是太难,就是<linux程序设计>一书的例程,检测有无击键动作的。

如下:

#include <stdio.h>
#include <termios.h>
#include <term.h>
#include <curses.h>
#include <unistd.h>

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

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

int main()
{
    int ch = 0;

    init_keyboard();
    while(ch != 'q') {
        printf("looping\n");
        sleep(1);
        if(kbhit()) {
            ch = readch();
            printf("you hit %c\n",ch);
        }
    }
    close_keyboard();
    exit(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);
}

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

int kbhit()
{
    char ch;
    int nread;

    if(peek_character != -1)
        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(nread == 1) {
        peek_character = ch;
        return 1;
    }
    return 0;
}

int readch()
{
    char ch;

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

================================

我就是最后两个语句没有看明白,我想,怎样才有可能执行到这两个语句呢,以我的思维,似乎永远也执行不到,呵呵,当然是我没看懂:(

按照主程序,应该是kbhit()返回值为1时,才有可能执行吧这两条语句所在的readch()。而kbhit()返回1只有两种情况,一种是peek_character != -1,另外一种是,peek_character = ch,也就是击键所代表的字符。这两种情况,peek_character都不等于-1。

但在readch()中,只有当peek_character等于-1时,才会执行到这两条语句,也就是说,这两条语句永远不会被执行到。

很显然,是我哪里理解错误,但因为linux是自学的,没有人指导,因此苦思不得其解,请大家指点一下,不胜感激。谢谢!
发表于 2005-8-10 10:03:55 | 显示全部楼层
注意书中代码之前的那段话, 本程序是为了模仿MS-DOS的KBHIT函数. 也就是说
程序提供了一个kbhit, 作用是检测系统有无按键事件.有按键, 则返回1, 无按键 0.
程序中的  readch 函数是能与kbhit 函数正常工作的read函数(需要注意的是原始READ不能与KBHIT联合会工作, 因为KBHIT已经把按键读到 peek_character里了, 而READ本身是不知道的, 这也正是此处 readch 所作的扩展工作).

也就是说, 在主程序中
if(kbhit()) {
ch = readch();
如果有按键, 则读取到 ch  这种逻辑下确是会使得
readch 中
read(0,&ch,1);
return ch;
执行不到.


但是, 一个良好设计的函数是与它所使用的环境相对无关的(耦合度), readch 本身不应强调一定要在kbhit执行后使用, 所以,如果主程序中没有调用kbhit ,直接调用 readch 了, 难道它就不应作一个基本
read 应作的本份的事了吗?
回复 支持 反对

使用道具 举报

发表于 2005-8-10 19:42:58 | 显示全部楼层
呵呵,你们两位都在看同一本书,正好可以互相交流。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-8-11 00:54:50 | 显示全部楼层
感谢楼上两位老兄的回复,因为事情太多,只能这时候来看。

我看看,再想想,如有问题,再麻烦各位。

十分感谢!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-8-11 01:06:10 | 显示全部楼层
感谢二楼朋友的指点,明白了,感谢!
回复 支持 反对

使用道具 举报

发表于 2010-6-30 18:52:19 | 显示全部楼层
不是很明白peek_character这个变量,刚开始设置为int,怎么后来又可以给它赋值字符串。
回复 支持 反对

使用道具 举报

发表于 2010-7-13 22:01:35 | 显示全部楼层
是字符,不是字符串。
int可以用来表示字符。
  1. printf("%c", itIsACharButUsesIntType);
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表