尾命令 - 使用fseek()和getline() - 输出乱序

时间:2017-03-01 03:46:46

标签: c linux

我需要帮助了解如何使用tailfseek()的组合在c中实现linux getline命令。

我正在使用fseek()到达文件末尾,然后使用while循环向后迭代。

如果检测到换行符('\ n')。我打印出该行,然后返回到我调用getline之前已到达的位置减去检测到'\ n'的位置。

否则如果没有检测到'\ n',那么使用我当前位置的偏移量-2将向后迭代。

我知道有更简单的方法来执行涉及缓冲区的tail命令,但我的算法是否正确?如果是这样,实施它的最佳方式是什么。

提前致谢。

void tail(FILE *ifp, int k) {
    int line_count=0;
    char *line=NULL;
    size_t len=0;

    //go to end of file
    if(fseek(ifp,-1,SEEK_END)) {
        fprintf(stderr,"Failure in reaching end of file\n");
    }

    //while loop which will iterate backward starting at the end of file until line_count = k.
    while(line_count != k) {
        //if detected a newline character, increment line_count, print out line then return back to previous position.          
        if(fgetc(ifp)=='\n') {
            getline(&line, &len, ifp);
            printf("%s", line);
            fseek(ifp,-strlen(line), SEEK_CUR);
            line_count++;
            //free(line);
        } else {
            //move back a single positon 
            fseek(ifp,-(strlen(line)+2), SEEK_CUR);
        }
    }
    //free(line);
    fclose(ifp);
    printf("-----\nfunction exited\n-------\n");
}

1 个答案:

答案 0 :(得分:0)

你可以:

  • 将最后N行保留在缓冲区中并继续前进,或

  • 从文件末尾开始,向后移动N行。

考虑到任意文件大小,第二种方法更有效。所以你的方法很好而且效率更高。 但是,您的代码需要工作。

在您的代码中,您可能需要检查文件中的行数少于k的情况。请查看GNU here中的尾部实现以获取更多信息。

1)内存泄漏:需要在最后释放分配了getline的内存:

if(line)
  free(line) 

2)当您点击'\n'时(您的if变为true),您仍然应该先退后(想想文件中最后'\n'会发生什么,那是你希望击中的第一个'\n'。但是,您的代码执行的是getline

3)您的else不会寻找单个位置,它取决于之前strlen(line)的值而不是当前行,并且您可能会错过这个搜索所需的'\n'或你的寻求可能是非法的 - >确保你不会在向后的时候点击文件的开头。