Will my program return the correct position I wanted after meeting a set number of newlines?

半城伤御伤魂 提交于 2019-12-11 16:01:10

问题


I'm trying to read a file backwards (say 10 lines at the end of the file). I would increment my new line counter (newline_counter) everytime it reads a '\n'. Once newline_counter reaches user_num (argument), say 10 lines, lseek() would stop at the current position (current_pos). I'm returning this position so that I can use this position in another function which uses lseek() to this position and start reading from this position and write until the end of the file. I have successfully compiled the program but once I start to run it, the program just keeps running and there is no output.

int func_line_mode(int infile, int user_num) {
    char c;
    int newline_counter = 0;
    int current_pos = 0;
    int end = lseek(infile, 0, SEEK_END);

    int counter = 0;

    while (counter < end || newline_counter <= user_num) {
        lseek(infile, current_pos, SEEK_END);
        read(infile, &c, sizeof(char));
        if (strcmp(&c,"\n") == 0) {
            newline_counter++;
        }
        current_pos--;
        counter++;
    }

    return current_pos;
}

回答1:


Some problems with your code:

  1. The while condition is wrong, it should be:

    while (counter < end && newline_counter <= user_num)
    
  2. After the while, you are left one byte before the last newline, so you should go forward 2 bytes to be precise:

    if (current_pos < 0)
        current_pos += 2;
    
  3. lseek() returns an off_t, not int, so you should do:

    off_t end = lseek(infile, 0, SEEK_END);
    
  4. As a consequence, other variables that you use to do comparisons should be off_t too, and most importantly the return type of the function too.

  5. strcmp(&c,"\n") is wrong, to compare a single character you can just do c == '\n'.

Number 1 is probably the reason of your problem. Other points should be fixed too, specially number 4.


Once all of the above is fixed, the function correctly works for me. Here's a working example:

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

off_t func_line_mode(int infile, int user_num) {
    char c;
    int newline_counter = 0;
    off_t current_pos = 0;
    off_t end = lseek(infile, 0, SEEK_END);
    off_t counter = 0;

    while (counter < end && newline_counter < user_num) {
        lseek(infile, current_pos, SEEK_END);
        read(infile, &c, 1);

        if (c == '\n')
            newline_counter++;

        current_pos--;
        counter++;
    }

    if (current_pos < 0)
        current_pos += 2;

    return current_pos;
}

int main() {
    char buf[100];
    int nread, nwrite;

    int fd = open("test.txt", O_RDONLY);

    // Last 3 lines.
    off_t off = func_line_mode(fd, 3);

    printf("off = %d\n", off);

    // Go back.
    lseek(fd, off, SEEK_END);

    while (nread = read(fd, buf, 100)) {
        nwrite = 0;

        while (nwrite < nread)
            nwrite += write(1, buf + nwrite, nread - nwrite);
    }

    return 0;
}


来源:https://stackoverflow.com/questions/57707383/will-my-program-return-the-correct-position-i-wanted-after-meeting-a-set-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!