打印一个文件的最后n行
原创
©著作权归作者所有:来自51CTO博客作者不死鸟jgc的原创作品,请联系作者获取转载授权,否则将追究法律责任
问题
命令tail用来打印一个文件的最后n行。其格式为:
tail [-n] filename
其中:
-n :n表示需要打印的行数,省略时n的值为10。
filename :给定文件名。
如,命令tail –20 example.txt 表示打印文件example.txt的最后20行。
实现该程序,该程序应具有一定的错误处理能力,如能处理非法命令参数和非法文件名。
算法分析
1、如何得到需要打印的行数和文件名?
使用命令行参数
int main(int argc, char *argv[])
行数 n = atoi(argv[1]+1)
文件名为 argv[2]
2、如何得到最后n行?
方法一:使用n个节点的循环链表。
首先创建一个空的循环链表;
然后再依次读入文件的每一行挂在链表上,最后链表上即为最后n行。
方法二:使用一个n个元素的指针数组。
依次读入每一行,然后循环挂到指针数组上。
char *lineptr[N]; /存入所读入的行/
char *line; /当前读入行/
int i; /读入的行数/
lineptr[i % n] = (char *)malloc(strlen(line)+1);
strcpy(lineptr[i%n], line);
方法三:两次扫描文件。
第一遍扫描文件,用于统计文件的总行数N;
第二遍扫描文件时,首先跳过前面N-n行,只读取最后n行。
如何开始第二遍扫描?
fseek(fp, 0, SEEK_SET);
算法实现(循环链表)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define
#define
struct Tail {
char *line;
struct Tail *next;
};
int main(int argc, char *argv[ ])
{
char curline[MAXLEN],*filename;
int n = DEFLINES, i;
struct Tail *first, *ptr;
FILE *fp;
if( argc == 3 && argv[1][0] == '-') {
n = atoi(argv[1]+1); //C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。stdlib.h中声明
filename = argv[2];
}
else if( argc == 2)
filename = argv[1];
else {
fprintf(stderr, "Usage: tail [-n] filename\n");
return (1);
}
if((fp = fopen(filename, "r")) == NULL){
fprintf(stderr, " Cann't open file: %s !\n", filename);
return (-1);
}
first = ptr = (struct Tail *)malloc(sizeof ( struct Tail));
first->line = NULL;
for(i=1; i<n; i++){
ptr->next = (struct Tail *)malloc(sizeof ( struct Tail));
ptr = ptr->next;
ptr->line = NULL;
}
ptr->next = first;
ptr = first;
while(fgets(curline, MAXLEN, fp) != NULL){
if(ptr->line != NULL)
free(ptr->line);
ptr->line = (char *) malloc ( strlen(curline)+1);
strcpy(ptr->line, curline);
ptr = ptr->next;
}
for(i=0; i<n; i++) {
if(ptr->line != NULL)
printf("%s",ptr->line);
ptr = ptr->next;
}
fclose(fp);
return 0;
}