[英]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.