簡體   English   中英

打印輸入的最后-n行

[英]print last -n lines of input

#include <stdio.h>

#define MAXLINES    5000    /* Maximum number of lines to display. */

char *lineptr[MAXLINES];    /* Pointer to input lines. */

#define BUFFERSIZE 1000

#define DEFAULT_LAST 10

int readlines(char *lineptr[], char *buffer, int maxlines);
static void unwrap(char *buffer, int index);
static void reverse(char *lineptr[], int nlines);

main(int argc, char *argv[])
{
    int nlines, i, last, offset;
    char buffer[BUFFERSIZE];
    char *p;

    last = DEFAULT_LAST;
    for (i = 0; i < argc; i++) {
        p = argv[i];
        if (*p++ == '-') {
            last = 0;
            while (isdigit(*p)) {
                last = last * 10 + *p - '0';
                p++;
            }
            if (*p != '\0') {
                printf("invalid argument: %s\n", argv[i]);
                last = DEFAULT_LAST;
            }
        }
    }

    nlines = readlines(lineptr, buffer, MAXLINES);
    if (nlines < 0) {
        printf("error: input too big to process\n");
        return 1;
    }
    if (nlines < last) {
        printf("error: only printing the last %d lines.\n", nlines);
        offset = 0;
    } else if (last > MAXLINES) {
        offset = nlines - MAXLINES;
    } else {
        offset = nlines - last;
    }
    for (i = 0; i < nlines && i < last; i++)
        printf("%s\n", lineptr[offset + i]);

    return 0;
}

int readlines(char *lineptr[], char *buffer, int maxlines)
{
    int c, nlines;
    int wrapped;
    char *p;

    /* The input lines are stored end-to-end in the buffer, with
       newlines converted to null bytes. */
    wrapped = 0;
    p = buffer;
    while ((c = getchar()) != EOF) {
        if (c == '\n')
            *p = '\0';
        else
            *p = c;
        p++;
        if (p >= buffer + BUFFERSIZE) {
            p = buffer;
            wrapped = 1;
        }
    }
    /* Rearrange the buffer so the oldest byte comes first. */
    if (wrapped) {
        unwrap(buffer, p - buffer);
        p = buffer + BUFFERSIZE;
    }
    p--;
    *p = '\0';
    nlines = 0;
    while (p >= buffer && nlines < maxlines) {
        p--;
        if (*p == '\0')
            lineptr[nlines++] = p + 1;
    }
    reverse(lineptr, nlines);

    return nlines;
}

static void unwrap(char *buffer, int index)
{
    char work[BUFFERSIZE];

    memmove(work, buffer + index, BUFFERSIZE - index);
    memmove(work + BUFFERSIZE - index, buffer, index);
    memmove(buffer, work, BUFFERSIZE);

    return;
}

static void reverse(char *lineptr[], int nlines)
{
    char *tmp;
    int i;

    for (i = 0; i < nlines / 2; i++) {
        tmp = lineptr[i];
        lineptr[i] = lineptr[nlines - i - 1];
        lineptr[nlines - i - 1] = tmp;
    }
return;
}

該程序打印輸入的最后-n行,並將行存儲到指針數組中。

在readlines函數中,如果指向緩沖區的指針超過了其最大大小,它將被包裝。 但是我不明白包裝/拆包功能的確切作用。 有人可以向我解釋嗎? 自動換行的方式,如果緩沖區溢出,為什么代碼的編寫者為什么不返回-1?

為了演示該原理:假設您使用相同的方案將10個字符(從0到9)放入8字節緩沖區中:

7個字符后:

+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |   |
+---+---+---+---+---+---+---+---+
  ^                           ^
buffer                        p

第8個字符之后:

+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
  ^                               ^
buffer                            p

所以現在p重置並且wrapped設置為1:

+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
  ^
buffer
  p

第10個字符之后:

+---+---+---+---+---+---+---+---+
| 8 | 9 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
  ^       ^
buffer    p

現在, unwrap()代碼重新排列緩沖區,使其看起來像這樣:

+---+---+---+---+---+---+---+---+
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+
  ^                               ^
buffer                            p

該程序正在執行此操作(而不僅僅是放棄操作),因此即使文件比緩沖區大很多,它仍然可以工作。 (除非最后10行的總長度大於緩沖區,否則最后10行中的較早的一些將丟失)。

該程序將所有行讀入行數組。 數組中的每個元素都有固定的大小。 如果一行大於一行的最大大小,它將“包裝”它並在緩沖區的開頭重新開始填充緩沖區。

然后解包將最舊的內容放到末尾,因此該行從行的開頭開始就被截斷了。 (10個字符的緩沖區中的12個字符行將顯示從第3個字符開始的最后10個字符。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM