為了加深一下對linux下正常指令的了解順帶寫作業,就用c語言模拟了一下tail指令。
首先簡單介紹一下tali指令的用法。
tail test.txt
:顯示test.txt檔案的最後十行
tail -n 5 test.txt
:顯示test.txt檔案最後五行
當然tail指令還有
tail -f
這個用法,用于實時更新檔案的最後十行,不過為了偷懶就沒寫了,思路差不多,隻是需要隔一段時間重新重新整理一下。
同時,如果後面給的檔案路徑或者檔案名等寫錯了,或者寫的參數不正确,導緻參數錯誤或檔案找不到的話,也會有提示資訊。
作為小白,下面寫的内容隻要會c語言基本文法就能看懂,不會的地方我均寫了解釋或者放上了參考文檔。
廢話不多說,開始講解思路:
1、初始化預設讀取長度line=10,如果使用了-n參數設定了長度為x,那麼就讓line=x
2、一行一行讀取檔案并儲存在數組。但是我是模拟了一下循環數組,即當數組長度達到line了就将數組下一次寫入的位置下标設定為0,這樣在一定程度上保證了不會因為檔案太大而溢出。
舉個例子:假如檔案一共15行,儲存檔案每一行資料的數組為
char buffer[][]
,第0-9行存放在buffer[0][] - buffer[9][] 之中,但是第10行資料又會被儲存到buffer[0][]中,因為最後隻需要輸出10行即可,是以隻需要儲存距離目前位置的最後十行。不過為了輸出時候保證位置正确,肯定是要記錄數組下标的。
3、開始輸出了,輸出是對buffer數組進行循環周遊,循環的次數等于min(line,文章行數)。
然後從前面儲存的下标開始輸出即可。
思路清晰了,就到了具體實作中存在的問題了。
首先,main函數的參數是什麼意思?
然後,既然需要讀取
-n 5 檔案路徑
這些資訊,而且并不知道
-n 5
這樣的參數是否會存在,如何解決?
再之後,如何一行一行讀取檔案?
有兩個思路,使用read,或者是用fgets。我們要求是使用read的,但是太麻煩了,我偷懶就還是使用fgets了。下面先簡要介紹一下用read實作的思路:
想了解一下read的童鞋請參考:
read的配套用法——open詳解
read的用法詳解
1) 定義一個緩沖區,用read将檔案全部存入緩沖區再通過\n來識别換行。明顯的一個缺陷就是當檔案太大的時候緩沖區會存不下,浪費了存儲空間。
2) 每次讀一個字元,然後儲存到一個臨時緩沖隊列裡,讀取到第一個\n後将緩沖隊列裡的資料當成一行存儲。缺點在于效率低下。
這兩種思路是在一個論壇裡總結出來的,論壇連結
總之使用read是很麻煩的一件事
,是以接下來還是老實使用fgets吧。
這個就很簡單啦,參考:fgets讀取檔案
可運作源代碼
最後就是我的源碼咯,頭檔案可能多了點,因為原來使用read加上去的,但是嫌read太麻煩還是改成fgets了。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#define BUFFSIZE 512
int main(int argc,char **argv)
{
char c;
int line = 10;
int count = 0;
char buffer[BUFFSIZE][BUFFSIZE];
//如果有-n,就将line的預設值改了。這裡有錯誤預設是會自動提示的。
while((c=getopt(argc,argv,"n:"))!=-1)
{
int x = atoi(optarg);
line = x;
}
//擷取檔案路徑,optind是某個頭檔案裡的東西,不是我定義的,訓示的是argv中下一個要讀取的資料的下标
char *path = argv[optind];
FILE *fp;
int index = 0;
//如果檔案打開不成功,肯定是檔案沒找到,就報錯
if((fp = fopen(path,"r")) == NULL)
{
printf("File dosen't exit!");
return -1;
}
//下面就是前面講的思路了,讀取檔案儲存到數組
while(!feof(fp))
{
count++;
fgets(buffer[index],BUFFSIZE,fp);
if(index+1 >= line)
{
index = 0;
}
else{
index++;
}
}
//記得關閉fp
fclose(fp);
int i;
if(count < line)
{
line = count;
}
//因為前面是用的++,多加了1
if(index != 0)
{
index--;
}
for(i = 0;i<line;i++)
{
printf("%s",buffer[index++]);
if(index >= line)
{
index = 0;
}
}
}
運作如圖: