1. 程式人生 > >Unix/Linux程式設計實踐教程(一)

Unix/Linux程式設計實踐教程(一)

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

呃。。。。開始入坑linux。參考書當然是《Unix/Linux程式設計實踐教程》

現寫下心得筆記,有什麼不對的,請大家指正哈。

------------------------------修正

2018.5.13

貌似我用自己的虛擬機器也不行,先暫時放下吧,這個還分析不了原因。。。。難道是因為虛擬機器?要自己裝一個系統才能使用tty?暫時不懂。。。。。

試了這位博主的程式,/dev/tty可以用,不知道自己的問題出在哪,不過有方向了,先mark

-------------------------------正文

直接上程式碼:這是書上的例程,我直接敲了一遍

/*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 <stdlib.h>
#include <stdio.h>
#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()

   /*** 
                    *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 <ctype.h>

功能:讀鍵

說明:從鍵盤上讀取一個鍵,並返回該鍵的鍵值 getch是到getchar的巨集定義

舉例:

// getchar.c
      
      #include <stdio.h>

      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,等等檔案的操作,這些都要熟悉的。

好了,至此,第一章結束,往後還會更改的。

相關推薦

Unix/Linux程式設計實踐教程

-------------------------------前言呃。。。。開始入坑linux。參考書當然是《Unix/Linux程式設計實踐教程》現寫下心得筆記,有什麼不對的,請大家指正哈。------------------------------修正2018.5.13貌

Unix-Linux程式設計實踐教程》讀書筆記

寫在最前:          第一遍:零零散散的花了近兩個月的時間讀了本書的第一遍,這是一本很適合剛剛掌握一些計算機基礎知識的人讀的書。學習的思路非常明確,能做什麼?怎麼做?自己動手?三個方面符合認知順序,由淺入深讓人易於接受;而且每章的內容相對獨立和簡單,適合初次接觸類

unix/linux程式設計實踐教程C語言補充2

1 getchar()和putchar()函式 getchar()函式的功能是從終端接受一個字元。可以將其置於程式中實現暫停功能。 getchar()函式接受的字元可以賦給一個字元型或整型變數,也可以賦給任何變數,直接輸出。 putchar(引數)  引數可以是一個字元

Linux C/C++教程-- 面向過程和麵向物件

目錄   一、面向過程 二、面向物件 一、面向過程 面向過程是一種以過程為中心的程式設計思想。分析問題的解決步驟,通過函式一步步實現,然後順序呼叫函式來執行。主要缺點在於複用性、維護性、拓展性比較差。 二、面向物件 面向物件採用物件(實體)的方式建立抽象

Linux C語言教程 資料型別

一、基礎型別 1.1 整型 整型常量的第一個字元是數字0,該常量會被視作八進位制,千萬不要為了格式對齊,將十進位制整型寫成八進位制。 1.1.2 列舉 1.2 浮點型 1.3 指標 1.3.1 字元指標 C語言是靜態弱型別語言,型別在編譯時需要確定,對於st

Unix-Linux 程式設計實踐教程 第十章 小結

檔案描述符是一個資源陣列的索引,每次取最小的用,0、1、2分別代表stdin,stdout,stderr三個標準IO的描述符。重定向只需close其中其中一個,然後再開啟一個檔案描述符,系統自動將關閉掉的索引重新使用。比如close(0),open(x-file,"r"),此時就是將stdi

Unix-Linux 程式設計實踐教程 第八章 小結

執行程式的函式---execvp()                     &n

Unix-Linux 程式設計實踐教程 第七章 小結

設定傳送訊號的計時器---alarm()alarm()設定當前程序的計時器到seconds秒後收到由核心發來的SIGALARM訊號 pause()掛起呼叫程序知道一個訊號到達,如果呼叫程序被整個訊號終止,pause()則不會返回。 三種計時器: ITIMER_

Unix-Linux 程式設計實踐教程 第五章 小結

裝置檔案中用逗號連線起來的兩個數字為主裝置號和從裝置號。主裝置號確定實際的裝置驅動程式,從裝置號作為引數。 如下圖中的,主裝置號-4,從裝置號-2 裝置檔案中的i-node儲存的是指向核心子程式指標 fcntl()針對當前fd描述的連線,執行操作,並不會改變檔案本身的屬性。

Unix-Linux 程式設計實踐教程 第四章 小結

建立目錄的函式---mkdir(const char *pathname, mode_t mode); #include <sys/stat.h> #include <sys/types.h> //pathname中可接受,“/home/tmp”和“/home/t

Unix-Linux 程式設計實踐教程 第三章 小結

Linux下一切皆檔案,所以目錄也只是一種特殊的檔案,可以同文件一樣open,read,close,只是函式換成了opendir(),readdir(),closedir() 用於讀取目錄檔案的資料結構---struct dirent #include <dirent.h>

Unix-Linux 程式設計實踐教程 第二章 小結

utmp檔案記錄當前正在本系統中的使用者的登入資訊 wtmp檔案記錄登入過本系統的使用者的登入資訊     PS:man who命令即可查詢到utmp和wtmp檔案在當前系統的位置 who命令相關: who顯示當前已登入使用

Unix/Linux程式設計實踐教程–ac在Ubuntu 14.04的實現

環境:Ubuntu 14.04 32位 為什麼這回不寫在OS x上的實現了?因為OS X使用的是utmpx,然後我用getutxent_wtmp()這個函式也沒有辦法正確獲取wtmp的日誌資訊,所以先在Ubuntu上實現好了。 預設沒有帶ac這個程式,需要自

Unix/Linux程式設計實踐教程–od在OS X的實現

環境:OS X 10.12.4 抱歉,本文章並不是關於Ollydbg的實現(笑)。 照舊man 1 od。 od 是一個能把指定的檔案或者標準輸入按照使用者定義的格式列印。( The od utility is a filter which displa

Unix/Linux程式設計實踐教程–chmod在Centos7.3的實現

環境:centos 7.3 x86_64 如果搜一下man就會發現,裡面有兩個chmod,一個是chmod(1),一個是chmod(2)。根據牛頓-萊布尼茲公式,立即推,第一個是使用者命令,第二個是系統呼叫。系統呼叫裡,函式的原型是這樣的: int chmo

學習《Unix/Linux程式設計實踐教程》(2):實現 more

0.目錄 1.more 能做什麼? 2.more 是如何實現的? 3.實現 more 3.1 more01.c 3.2 more02.c 3.3 more03.c 1.more 能做什麼? more 可以分頁顯示檔案的內容。正常執行後 more 會顯示檔案第一屏的內容,在螢幕的底

Unix/Linux程式設計實踐教程–書評

花了兩個月的時間把這本書讀完了,完成了一部分的課後習題。 總的來說,這是一本挺好的Unix\Linux程式設計的入門書(雖然書中的小錯誤一大堆),書的開始部分簡要介紹了Unix系統程式設計,講述瞭如何使用男人(man page),這也是我比較看好的,授人以漁,

Unix/Linux程式設計實踐教程–cat在OS X的實現

環境:OS X 10.12.4 cat 這玩意兒在哪個Unix平臺實現都一樣吧- - cat這個程式是把引數中的檔名的檔案內容輸出到標準輸出,如果引數中沒有檔名,預設是把標準輸入的內容輸出到標準輸出。 這裡使用了utmplib類似的程式碼用於快取資料,減少

unix/linux程式設計實踐教程:who命令

1. who命令的編寫 1) 通過man命令的幫助,找到who命令的儲存檔案 man who2) 在man who的幫助下,找到utmp這個資訊 man -k utmp 3) 看man -k utmp的輸出,找到以下這條資訊: utmp (5)

人工智慧實踐教程

 本文為《人工智慧實踐教程》學習總結和感悟,先寫書中內容,再寫自己的思考     2017年10月20日,實驗室      現在人工智慧就是用計算機去模擬人類智慧。為什麼計算機可以模擬人類的智慧? 這是因為人和計算機都是物理符號系統。能夠實現輸入符號、輸出符號、儲存符號、複