首先想到的最笨的办法就是打开文件,然后遍历一遍,计算出文件中的行数,然后在从头开始遍历文件,在某个位置开始打印从文件中读出的行。这是一个比较笨的方法,还有一种很巧妙的方法就是应用circular buffer,初次见到这个名称的人可能感觉很神奇,但是如果知道循环队列这个概念的话,那么就不难理解了。如果我们准备打印一个文件的最后n行,我们可以建立一个n+1空间的循环队列,至于为什么是n+1的循环队列,是为了表示队列什么时候满,什么时候是空的。接下来就解决怎么打印最后n行吧:首先我们把读出的每行的字符串的首地址放在队列中,如果队列已经被填满了,那么我们开始进行覆盖,也就是说第如果队列用n个空间,那么当第n+1行到来的时候,我们就把原来存放第一行字符串首地址的队列某空间用第n+1行的首地址覆盖掉,依次对之后的行来进行如此的操作,大家很容易发现,到最后队列中存留下来的就是最后n行的字符串的首地址。
下面给出wikipedia中,讲述circular buffer的连接:http://en.wikipedia.org/wiki/Circular_buffer 然后给出我自己写的代码:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
class Queue {
private:
void **elem;
int front, rear;
int size;
public:
Queue(int _size) {
size = _size + 1;
elem = (void**)malloc(size * sizeof(void*));
memset(elem, 0, size * sizeof(void*));
front = rear = 0;
}
Queue() {
free(elem);
}
void enQueue(void *addr);
void deQueue(void **addr);
bool isQueueEmpty();
};
void Queue::enQueue(void *addr) {
if ((rear + 1) % size == front) {
free(elem[front]);
elem[front] = NULL;
front = (front + 1) % size;
}
elem[rear] = addr;
rear = (rear + 1) % size;
}
void Queue::deQueue(void **addr) {
if (rear == front)
return;
*addr = elem[front];
elem[front] = NULL;
front = (front + 1) % size;
}
bool Queue::isQueueEmpty() {
return rear == front;
}
int main(int argc, char *argv[]) {
char temp[100];
Queue q(10);
ifstream fin;
fin.open("test.txt", ifstream::in);
while (fin >> temp) {
int n = strlen(temp);
char *s = (char*)malloc(n + 1);
strcpy(s, temp);
s[n] = '\0';
q.enQueue(s);
}
while (!q.isQueueEmpty()) {
char *s = NULL;
q.deQueue((void**)&s);
cout << s << endl;
free(s);
}
cin.get();
return 0;
}