Too*_*ool 2 c string function lines
#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;
}
Run Code Online (Sandbox Code Playgroud)
该程序打印最后一行输入,将行存储到指针数组中.
在readlines函数中,如果指向缓冲区的指针超过其最大大小,它将被包装.但我不明白包装/解包功能究竟做了什么.有人可以向我解释一下吗?包装的工作原理以及为什么如果缓冲区溢出,这段代码的编写器只返回-1?
为了演示原理:假设您使用相同的方案将10个字符'0'添加到'9'到8字节缓冲区:
7个字符后:
+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
+---+---+---+---+---+---+---+---+
^ ^
buffer p
Run Code Online (Sandbox Code Playgroud)
在第8个字符后:
+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
^ ^
buffer p
Run Code Online (Sandbox Code Playgroud)
所以现在p
重置并wrapped
设置为1:
+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
^
buffer
p
Run Code Online (Sandbox Code Playgroud)
在第10个字符之后:
+---+---+---+---+---+---+---+---+
| 8 | 9 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
^ ^
buffer p
Run Code Online (Sandbox Code Playgroud)
现在unwrap()
代码将缓冲区重新排列为如下所示:
+---+---+---+---+---+---+---+---+
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+
^ ^
buffer p
Run Code Online (Sandbox Code Playgroud)
程序正在执行此操作(而不是仅仅放弃),以便即使文件比缓冲区大得多,它仍然可以正常工作.(除非最后10行的总长度大于缓冲区,否则最后10行中的某些行将丢失).
归档时间: |
|
查看次数: |
2120 次 |
最近记录: |