Unix/Linux编程实践教程(一)

-------------------------------前言

呃。。。。开始入坑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);
        }
      }

Unix/Linux编程实践教程(一)_第1张图片

测试是需要回车的,那么我们应该怎么办呢?。。。。看书说,在/dev/tty中,他是键盘和显示器的设备描述文件,向这个文件写相当于在显示器上显示,向这个文件读相当于获取键盘的按键,怪不得说一切皆是文件呢,可能就是这样吧,虽然我还是不太明白,反正先用着。然后,我的环境是,远程访问我的服务器,我的电脑连开虚拟机都好卡,所以我用了ssh登陆服务器在上面捣鼓,所以我的是不是不写tty啊?我百度了下,还是不直到怎么描述我的问题,等我学得差不多了,在回头来看看,至此结束。

总结:

1.stdin、stdout具体到底是什么?

2./dev/tty这些是什么鬼,到底我什么情况使用哪一个,怎么使用啥的,不太清楚

3.就是一些c库了,这个很久之前学的了,基本忘了,mark一下,fgets,fputs,getc,getchar,等等文件的操作,这些都要熟悉的。

好了,至此,第一章结束,往后还会更改的。

你可能感兴趣的:(Unix/Linux编程实践教程(一))