这是linux系统编程手册中的题目。

代码

废话不多说直接上代码,虽然感觉还有个小bug。。

#include "tlpi_hdr.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include <getopt.h>

#define BUFFSIZE 4096
char buf[BUFFSIZE] = {0};
int cntline = 0; //用于计算已经读取的行数
int showline = 10; //默认是10
bool over = false;

int serchline(int fd, int pos)
{
while (pos > BUFFSIZE)
{
pos = lseek(fd, -BUFFSIZE, SEEK_END); //如果文件长度大于4096,那么移动-4096字节开始读
read(fd, buf, BUFFSIZE);
for (int i = (BUFFSIZE - 1); i > 0; i--) //倒序访问
{
if (buf[i] == '\n')
{
cntline++;
}
if (cntline > showline) //如果读取到了10行
{
pos += i; //记录位置
over = true;
return pos;
}
}
memset(buf,0,BUFFSIZE);//要清空一下数组
}
//执行到这里说明找了4096字节都没找到showline行,或者是文件本身就没有这么长
lseek(fd, 0, SEEK_SET); //那么从头开始读
read(fd, buf, pos); //读postion个字节
for (int i = pos; i > 0; i--) //倒序访问
{
if (buf[i] == '\n')
{
cntline++;
// printf("cntline : %d postion : %d \n", cntline, pos);
}
if (cntline > showline) //如果读取到了showline行
{
pos = i; //记录位置
over = true;
return pos;
}
}
memset(buf,0,BUFFSIZE);//要清空一下数组
//执行到这里说明寻找结束也没有showline行
return -1;
}

int main(int argc, char *argv[])
{
int fd = -1;
char ch;
int postion = -1;
int readsize=0;
if (argc == 1)
{
usageErr("[ -n num ] filename \n to printf last num line of file\n");
}
while ((ch = getopt(argc, argv, "n:num")) != -1)
{
switch (ch)
{
case 'n':
showline = atoi(optarg);
break;
default:
usageErr("[ -n num ] filename \n to printf last num line of file\n");
break;
}
}
if (showline > 0)
{ //如果要显示大于0的行数
if ((fd = open(argv[optind], O_RDONLY)) == -1)
{
errExit("open");
}

if ((postion = lseek(fd, 0, SEEK_END)) == -1) //先得出文件总长度
{
errExit("lseek");
}
// printf("file all length: %d\n", postion);
postion = serchline(fd, postion);
if (postion != -1)
lseek(fd, postion, SEEK_SET); //说明找到了最后showline行
do
{
readsize=read(fd, buf, BUFFSIZE);
printf("%s",buf);
memset(buf,0,BUFFSIZE);//输出完了就清空
} while(readsize > BUFFSIZE);//输出所有
}
else
{
usageErr("[ -n num ] filename \n to printf last num line of file\n");
}
return 0;
}

总结

通过这个题目,学会了如何在vscode里面使用gdb: vscode自带的gdb调试不好使,还是要下载插件Native Debug才好使。我使用自带的gdb调试,第一句话就报错退出。但是我用上插件就没有问题了。