#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
/*
问题:用C++方法,打印输入文件的最后K行。
分析:假设文件一共N行,最后K行,那就是从N-k+1~N。之前打印链表倒数第k个结点可以用两个指针,这里不能用了。
暴力破解:先读取整个文件确定N,下次每读一行就计数,从第N-k+1行开始存储结果直到第N行。
另外一种方法就是:采用回滚数组,节省空间,设一个字符串数组strings[k],长度为k,每次存储新读取的一行到该数组,
举例:设共有6行,读取最后4行,各行内容如下
1
2
3
4
5
6
那么读取第1行数组中为:[1, , ], 数组元素个数<K,直接存储
2 [1,2,],直接存储该行
3 [1,2,3],直接存储
4 [1,2,3,4],直接存储
5 [5,2,3,4],元素个数=K,必须替换掉最先进来的1
6 [5,6,3,4],替换次最先进来的2
记录最后一行在数组下标index,则index+1~k-1下标对应的数组元素是前面部分(如上述3,4),再加上0~index下标对应元素是后面部分(如上述的5,6)
输入:
4(倒数第K行)
输出:(这个是在我输入文件共有6行,各行分别为:1,2,3,4,5,6的情况下)
3
4
5
6
关键:
1 采用回滚数组,节省空间,设一个字符串数组strings[k],长度为k,每次存储新读取的一行到该数组,当长度>=k时,采用替换最先进入的行
记录最后一行在数组下标index,则index+1~k-1下标对应的数组元素是前面部分,再加上0~index下标对应元素是后面部分
2 文件操作:读取一行用字符数组infile.getline(line , 1024);,判断是否结束用while(!infile.eof()),判断文件是否打开成功用if(!infile)
*/
void printResult(vector<string>& lines, int endIndex)
{
if(lines.empty())
{
cout << "no result" << endl;
return;
}
int size = lines.size();
int i;
for(i = endIndex + 1 ; i < size; i++)
{
cout << lines.at(i) << endl;
}
for(i = 0 ; i <= endIndex ; i++)
{
cout << lines.at(i) << endl;
}
}
void process()
{
int k;
while(cin >> k)
{
string fileName("test.txt");
ifstream infile(fileName);
if(!infile)
{
cout << "file open error" << endl;
return;
}
char line[1024];//读取一行,不能用字符串
vector<string> lines;
int replaceIndex = 0;
while(!infile.eof())
{
infile.getline(line , 1024);
string content(line);
if(lines.size() < k)
{
lines.push_back(content);
}
//此时需要将最先进入的那一行替换掉
else
{
if(replaceIndex >= k)
{
replaceIndex = 0;
}
lines.at(replaceIndex) = content;
replaceIndex++;
}
}
//关闭文件
infile.close();
printResult(lines , replaceIndex - 1);
}
}
int main(int argc, char* argv[])
{
process();
getchar();
return 0;
}
09-23