Skip to main content
Corrected as per comment from ChrisW
Source Link
William Morris
  • 9.4k
  • 19
  • 43

That is a lot of code for the job. It can be done significantly more easily in two areas:

  • use an array instead of a queue
  • use the POSIX function, getline, which will handle lines of any size.

If you don't want to use getline (which admittedly might not have existed when K&R wrote their book), concentrate on writing its equivalent.

Here is a version that uses an allocated array or char* pointers. The array is zeroed (by calloc) so that we can tell whether the entry holds a line (which might not be so if the input is less than 10 (or the requested number of) lines.

int
tail(size_t n_lines, FILE *fp)
{
    char **lines = calloc(sizeof(char*), n_lines);
    if (!lines) {
        perror("calloc");
        return -1;
    }
    size_t size = 0;
    size_t in = 0;
    for (char *ln = 0; getline(&ln, &size, fp) > 0; in = (in + 1) % n_lines) {
        if (lines[in]) {
            free(lines[in]);
        }
        lines[in] = ln;
        ln = NULL;
        size = 0;
    }
    for (size_t i = 0; i < n_lines; ++i) {
        if (lines[in]) {
            printf("%s", lines[in]);
            free(lines[in]);
        }
        in = (in + 1) % n_lines;
    }
    free(lines);
    return 0;
}

That is a lot of code for the job. It can be done significantly more easily in two areas:

  • use an array instead of a queue
  • use the POSIX function, getline, which will handle lines of any size.

If you don't want to use getline (which admittedly might not have existed when K&R wrote their book), concentrate on writing its equivalent.

Here is a version that uses an allocated array or char* pointers. The array is zeroed (by calloc) so that we can tell whether the entry holds a line (which might not be so if the input is less than 10 (or the requested number of) lines.

int
tail(size_t n_lines, FILE *fp)
{
    char **lines = calloc(sizeof(char*), n_lines);
    if (!lines) {
        perror("calloc");
        return -1;
    }
    size_t size = 0;
    size_t in = 0;
    for (char *ln = 0; getline(&ln, &size, fp) > 0; in = (in + 1) % n_lines) {
        lines[in] = ln;
        ln = NULL;
    }
    for (size_t i = 0; i < n_lines; ++i) {
        if (lines[in]) {
            printf("%s", lines[in]);
            free(lines[in]);
        }
        in = (in + 1) % n_lines;
    }
    free(lines);
    return 0;
}

That is a lot of code for the job. It can be done significantly more easily in two areas:

  • use an array instead of a queue
  • use the POSIX function, getline, which will handle lines of any size.

If you don't want to use getline (which admittedly might not have existed when K&R wrote their book), concentrate on writing its equivalent.

Here is a version that uses an allocated array or char* pointers. The array is zeroed (by calloc) so that we can tell whether the entry holds a line (which might not be so if the input is less than 10 (or the requested number of) lines.

int
tail(size_t n_lines, FILE *fp)
{
    char **lines = calloc(sizeof(char*), n_lines);
    if (!lines) {
        perror("calloc");
        return -1;
    }
    size_t size = 0;
    size_t in = 0;
    for (char *ln = 0; getline(&ln, &size, fp) > 0; in = (in + 1) % n_lines) {
        if (lines[in]) {
            free(lines[in]);
        }
        lines[in] = ln;
        ln = NULL;
        size = 0;
    }
    for (size_t i = 0; i < n_lines; ++i) {
        if (lines[in]) {
            printf("%s", lines[in]);
            free(lines[in]);
        }
        in = (in + 1) % n_lines;
    }
    free(lines);
    return 0;
}
Source Link
William Morris
  • 9.4k
  • 19
  • 43

That is a lot of code for the job. It can be done significantly more easily in two areas:

  • use an array instead of a queue
  • use the POSIX function, getline, which will handle lines of any size.

If you don't want to use getline (which admittedly might not have existed when K&R wrote their book), concentrate on writing its equivalent.

Here is a version that uses an allocated array or char* pointers. The array is zeroed (by calloc) so that we can tell whether the entry holds a line (which might not be so if the input is less than 10 (or the requested number of) lines.

int
tail(size_t n_lines, FILE *fp)
{
    char **lines = calloc(sizeof(char*), n_lines);
    if (!lines) {
        perror("calloc");
        return -1;
    }
    size_t size = 0;
    size_t in = 0;
    for (char *ln = 0; getline(&ln, &size, fp) > 0; in = (in + 1) % n_lines) {
        lines[in] = ln;
        ln = NULL;
    }
    for (size_t i = 0; i < n_lines; ++i) {
        if (lines[in]) {
            printf("%s", lines[in]);
            free(lines[in]);
        }
        in = (in + 1) % n_lines;
    }
    free(lines);
    return 0;
}