-------------------------------前言
呃。。。。开始入坑linux。参考书当然是《Unix/Linux编程实践教程》
现写下心得笔记,有什么不对的,请大家指正哈。
------------------------------修正
2018.5.13
貌似我用自己的虚拟机也不行,先暂时放下吧,这个还分析不了原因。。。。难道是因为虚拟机?要自己装一个系统才能使用tty?暂时不懂。。。。。
试了这位博主的程序,/dev/tty可以用,不知道自己的问题出在哪,不过有方向了,先mark
https://blog.csdn.net/a7055117a/article/details/50558089
-------------------------------正文
直接上代码:这是书上的例程,我直接敲了一遍
/*more01.c - version 0.1 of more
*read and print 24 lines then pause for a few special commands
**************************Modify*************************
*************************Version0.2**********************
*add the file (/dev/tty) which is able to imput and output like keyboard and screen directly
*result:i don't need to press the 'Entry' to use my function
*/
#include
#include
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more(FILE* ); //add a parameter,FILE*
int main(int ac,char *av[])
{
FILE * fp;
if(1 == ac)
do_more(stdin);
else
while(--ac)
{
if((fp = fopen(*++av,"r")) != NULL)
{
do_more(fp);
fclose(fp);
}
else
exit(1);
}
return 0;
}
/*
* read PAGELEN lines,then call see_more() for further instructions
*/
void do_more(FILE * fp)
{
char line[LINELEN];
int num_of_lines = 0;
int see_more(),reply;
FILE * tty_fp; //add the file for tty
tty_fp = fopen("/dev/tty","r");
if(tty_fp == NULL)
{
printf("eeeee");
exit(1);
}
while(fgets(line,LINELEN,fp)) //fget will get LINELEN charaters for a array(line),and it will go on its memory
//last time
{
if(num_of_lines == PAGELEN) //full of screen?
{
reply = see_more(tty_fp);
if(reply == 0)
break;
num_of_lines -= reply;
}
if(fputs(line,stdout) == EOF) //output in screen of a line
exit(1);
num_of_lines++;
}
}
/*
* print message,wait for response,return # of lines to advance
* q means no,space means yes,CR means one line
* add a parameter for tty
*/
int see_more(FILE * cmd)
{
int c;
printf("\033[7m more?\033[m");
while((c = getc(cmd)) != EOF) //get charater on the keyboard .the cycle will stop until user press key.
//getchar and getc are different in something ...
{
if(c == 'q') //q
return 0; //quit more
if(c == ' ') //" "
return PAGELEN; //next page
if(c == '\n') //press "Enter"
return 1; //next line
}
return 0;
}
这只是书上的第一章,其实也就是概述,我现在对以上的代码重要部分做一些解释。
一.整体思路:
整篇内容都围绕着:
1.有什么功能?
2.怎么做到的?
3.我们应该怎么做?
这三个问题进行的。more有什么功能?他能实现什么功能?他是系统上的一个程序,我们可以使用man进行联机查看他的作用,至于怎么使用man,怎么使用联机查看的手册,下一章中讲解,这里先不谈。但是我们应该知道我们是可以查得到他的功能的。他的功能是:一行有512个字符,一页有24行,按下回车跳一行,按下q退出,按下空格键跳一页,这个基本的功能。
ok,我们已经知道了他有什么功能,就是可以分页浏览文本文件的功能,还有一些配套的功能,比如说,-number,-f之类的,这些扩展功能,但是我们先一步步来,先能实现浏览文本文件。官方是怎么做的呢?下一章再说明我们怎么查。
好,第一章,书上直接给了例程,我们先直接分析例程,感受一下就ok了。
二、
1.我们首先要清楚unix/linux下的系统编程,main函数上面是有参数的,即main(int ac,char *av[]),这个带参数是干啥的呢?第一个ac是表示程序运行时输入的参数个数(int型),第二个是一个指针数组,表示参数的符号。举个例子:
./more01 执行之后,ac=1,av[0]=./more01,./more01 more01.c执行之后,ac=2,av[0]=./more01,av[1]=more01.c 如果执行./more01 -f more01.c 的话,ac=3,av[0]=./more01,av[1]=-f ,av[2]=more01.c,然后至于怎么实现的这样的功能的,这里不是讨论的重点,知道就好。
知道这些以后,很容易就可以从主函数中看出,这个函数do_more(FILE *fp)就是实现显示的,而ac==1的时候,是后面不接文本文件的时候,但是可以显示你的标准输入流中的数。while的功能就是为了,应对多输入的时候的策略,具体为了更好的服务用户的话,还要加上许多的操作来使显示更简洁清新。
2.do_more(FILE* fp)显示字符,关键点就在于fgets()和fputs()
while(fgets(line,LINELEN,fp)),我们来分析一些fgets,参考:https://blog.csdn.net/daiyutage/article/details/8540932
/***
*char *fgets(string, count, stream) - input string from a stream
*
*Purpose:
* get a string, up to count-1 chars or '\n', whichever comes first,
* append '\0' and put the whole thing into string. the '\n' IS included
* in the string. if count<=1 no input is requested. if EOF is found
* immediately, return NULL. if EOF found after chars read, let EOF
* finish the string as '\n' would.
*
*Entry:
* char *string - pointer to place to store string
* int count - max characters to place at string (include \0)
* FILE *stream - stream to read from
*
*Exit:
* returns string with text read from file in it.
* if count <= 0 return NULL
* if count == 1 put null string in string
* returns NULL if error or end-of-file found immediately
*
*Exceptions:
*
*******************************************************************************/
官方文档的说明,还是挺清晰的,返回为NULL的时候我们的while就退出了,非NULL的时候继续循环,而FileSream是指针,会保留住未读完的“行”,直到EOF或者ERROR。
/****************************************************
char *fgets(char *s, int n, FILE *stream)
{
register int c;
register char *cs;
cs=s;
while(--n>0 &&(c = getc(stream))!=EOF)
if ((*cs++= c) =='\n')
break;
*cs ='\0';
return (c == EOF && cs == s) ?NULL :s ;
}
/********************************************************
这是源码,从上面的博主那顺来的,可是我没有找到getc,所以我猜是getc 的原因使指针stream才得以保留。好,读取的一行已经保存再line[]里面了,怎么显示呢?那就是fputs函数的功劳了。fputs是一个函数,具有的功能是向指定的文件写入一个字符串(不自动写入字符串结束标记符‘\0’)。成功写入一个字符串后,文件的位置指针会自动后移,函数返回值为非负整数;否则返回EOF(符号常量,其值为-1)。输出到标准输出流stdout中,那就可以显示了,虽然现在还不知道stdout具体是啥子东西,先放着。经过一次循环就可以显示一行了,在循环了一页(24行)后,就进入if,进行选择命令中,此时,你已经进入了新的循环中,直到你做出选择,是按下回车,还是q,还是空格,然后做出相应的动作,即返回相应的数值,回到do_more中,进行循环。ok,这就ok了。
但是,经过我们的试验,效果不是很理想,输入q后还得按下回车才执行,输入空格后,回车后才执行,这是为什么呢?
根据我的代码,获取version0.1中,是c=getchar()来捕捉我们的按键输入的,那么
原型:extern int getchar(void);
用法:#include
功能:读键
说明:从键盘上读取一个键,并返回该键的键值 getch是到getchar的宏定义
举例:
// getchar.c
#include
main()
{
int c;
printf("Press key...");
while((c=getchar())!='Q')
{
printf("key: %c\nvalue: %x",c,c);
}
}
测试是需要回车的,那么我们应该怎么办呢?。。。。看书说,在/dev/tty中,他是键盘和显示器的设备描述文件,向这个文件写相当于在显示器上显示,向这个文件读相当于获取键盘的按键,怪不得说一切皆是文件呢,可能就是这样吧,虽然我还是不太明白,反正先用着。然后,我的环境是,远程访问我的服务器,我的电脑连开虚拟机都好卡,所以我用了ssh登陆服务器在上面捣鼓,所以我的是不是不写tty啊?我百度了下,还是不直到怎么描述我的问题,等我学得差不多了,在回头来看看,至此结束。
总结:
1.stdin、stdout具体到底是什么?
2./dev/tty这些是什么鬼,到底我什么情况使用哪一个,怎么使用啥的,不太清楚
3.就是一些c库了,这个很久之前学的了,基本忘了,mark一下,fgets,fputs,getc,getchar,等等文件的操作,这些都要熟悉的。
好了,至此,第一章结束,往后还会更改的。