more指令的簡單實現

2015-07-29 晴 成都

more指令的簡單實現

遇到的問題和我的處理

1. 問題:換行時,“--more()--”提示輸入指令這行會多次不停的向屏幕上方移動。

     處理:每次都從進行滿屏輸出,不管是翻頁還是換行,總是將“--more--”擠到屏幕的最下方。

     iCurrentLine = iCurrentLine - (sliPageLen-1) + reply;

    等式右邊

    iCurrentLine當前顯示到的行數,每次計算的時候先減去一頁的行數(sliPageLen - 1),再加上用戶響應的行數reply,就得出如果滿屏顯示應該從哪一行開始顯示

2. 問題:從問題1中引發了一個新的問題——不知道終端一屏是多少行,多少列

    處理:可以使用stty-a或者ioctl( STDIN_FILENO, TIOCGSIZE, ... )[ or ioctl( STDIN_FILENO,TIOCGWINZE, ... ) ]獲取。

<pre name="code" class="cpp"><pre name="code" class="cpp">fp = popen("stty-a","r");
while( fgets(caLine,LINELEN,fp) != NULL )
{
	/*
	** fetch the rows
	*/
	cpStart = strstr(caLine,"rows");
	cpEnd  = strstr(caLine,"columns"); 
	if( cpStart != NULL && cpEnd!=NULL )
	{
		strncpy(caPart,cpStart,cpEnd-cpStart);
		caPart[cpEnd-cpStart]='\0';
		sscanf(caPart,"%*s%[^;]",caAim);
		*iRows=atoi(caAim); 
		/*
		** fetch the cols
		*/
		cpStart=strstr(caLine,"columns");
		cpEnd   =strstr(caLine,"line"   );
		strncpy(caPart,cpStart,cpEnd-cpStart);
		caPart[cpEnd-cpStart]='\0';
		sscanf(caPart,"%*s%[^;]",caAim);
		*iCols=atoi(caAim);
	}/* end if( cpStart != NULL&& cpEnd != NULL ) */
}/* end while( fgets(caLine, LINELEN, fp ) != NULL  ) */




3. 問題:問題1引發的第二問題,要想控制文件從哪一個顯示,需要記錄每一行的起始位置。

    處理:設計一個簡單的可隨機訪問的數據結構記錄每一個顯示行的起始位置

/*
**    st_line_node* init_line_manager( long liLineNum );
**        precondition:  liLineNum > 0
**        postcondition: generate a dynamic array whose length
**                       is liLineNum
**
**     intfree_line_manager( st_line_node *stpLine );
**        precondition:  stpLine not NULL
**        postcondition: free the dynamic array, success returns true
**                       otherwise returns false
**
** TOOLKIT of the line manager
**     voidinsert_line_node( st_line_node *stpLine, long liLineNo, long liOffset );
**        precondition:  liLineNo andliOffset both greater than zero, and
**                       liLineNo is less than the maximum line no
**        postcondition: insert the line node into the array
**
**     long fetch_line_offset(st_line_node *stpLine, long liLineNo );
**        precondition:  liLineNo greaterthan zero and less than the maximum
**                       line no
**        postcondition: return the specific offset
**
**     intis_filled( st_line_node *stpLine, long liLineNo );
**        precondition:  liLineNo greaterthan zero and less than the maximum
**                       line no
**        postcondition: the current line no has a offset, return true; otherwise
**                       respond a false
**
*/
4. 問題:問題3連帶一個新的問題,一個文件行可能需要佔用終端的多個行來進行顯示,如果按照換行符的標準進行行輸出,可能會造成某些內容被擠到終端外而無法顯示。

    處理:所以不能依靠換行符來進行分行,而應該依靠終端的列數作爲行的劃分

long
get_file_lines_base_len(FILE*fp,intiLineLen)
{
    longliLines=0;
    charcaLine[iLineLen];
    while(fgets(caLine,iLineLen,fp)!=NULL)
    {
       ++liLines;
    }
    returnliLines;
}/* end get_file_lines_depond_len( FILE *fp,int iLineLen ) */
5. 問題:在接受用戶的指令時,需要無回顯和立即響應

    處理:控制終端屬性來達到需求

/* 關閉回顯 */
term.c_lflag&=~ECHO;
/* 關閉終端緩存,每次接收一個字符就馬上反應 */
term.c_lflag&=~ICANON;
term.c_cc[VMIN]=1;      /* one character one time*/
6.問題:系統more在顯示提示的時候會顯示當前顯示內容大約處於文件什麼位置(百分比),e.g--more(%12)--

   處理:由於已經記錄了當前顯示行的位置,只需要知道整個文件的字節數,即可求得當前顯示行所處的百分比

long
get_file_bytes(FILE*fp)
{
    longliAllBytes=0;
    if(fseek(fp,0,SEEK_END)==-1)
    {
       fprintf(stderr,"fseek error\n");
       return-1;
    }/* end if( fseek( fp, 0,SEEK_END ) == -1 ) */
    liAllBytes=ftell(fp);   /* all the bytes from thebyte 0 */
    if(fseek(fp,0,SEEK_SET)==-1)   /* rewind the file */
    {
       fprintf(stderr,"fseek error\n");
        return-1;
    }/* end if( fseek( fp, 0,SEEK_SET ) == -1 ) */
    returnliAllBytes;
}/* end get_file_bytes( FILE *fp ) */
7. 問題:編寫Makefile時候,將終端操作、文件操作和more操作的內容分別打成了對應的靜態庫,再最終編譯的時候,報錯了。


  處理:出錯原因是libmoremanager.a這個庫需要依賴於libfilemanager.a和libtermmanager.a,所以應該將libmoremanager.a放在前面。應該是:


8. make文件包括兩個文件,一個定義變量的文件Make.defines,一個是用於編譯的Makefile文件。在Makefile文件中通過include將Make.defines中定義的變量引入,其中ROOT是Make.defines文件相對Makefile文件的文件路徑。

最後整個程序的目錄和Makefile如下:

 

Make.defines的內容如下:

 

Makefile文件內容如下:

ROOT=../..
include $(ROOT)/Make.defines
CINCLUDE+= -I./include
VPATH+= include src obj lib
CLDIR+= -L./lib -L./src
CLIBS+= -lmoremanager -lfilemanager-ltermmanager
ARFLAGS+=
TMPFILE+= ./lib/*.a ./obj/*.o *.a
# PRGS= more4 more5 more6 more7
PRGS= more9

define AR_CMD
       $(AR)$(ARFLAGS) $@ $<
       $(MV)$< ./obj
       $(MV)$@ ./lib
endef

.PHONY=all
all: $(PRGS)

%: %.c libfilemanager.a libtermmanager.alibmoremanager.a
       $(CC)$(CFLAGS) -DDEBUG $(CINCLUDE) $(CLDIR) -o $@ $< $(CLIBS)

libfilemanager.a: file_manager.ofile_manager.h
       $(AR_CMD)
 
libtermmanager.a: term_manager.oterm_manager.h
       $(AR_CMD)

libmoremanager.a: more_manager.omore_manager.h
       $(AR_CMD)

# generate the .o file
%.o: %.c %.h
       $(CC)$(CINCLUDE) -DDEBUG -c $^

.PHONY=clean
clean:
       $(RM) $(TMPFILE) $(PRGS)

9. 源代碼

http://download.csdn.net/detail/qq123386926/8942937

發佈了45 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章