按行逆向复制一个文件

这是一个面试题,要求把类似下面的一个文件(a.txt)的行逆向复制到另一个文件(anew.txt)。如下,

a.txt:

------begin------
a
b
c
d
e
f
------end------

anew.txt

------end------
f
e
d
c
b
a
------begin------

下面是我写的程序,利用了递归算法。算法描述在代码后面

//C program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZ 1024

void reverse_line_copy(FILE *fp_in, FILE *fp_out)
{
	if (fp_in!=NULL && feof(fp_in)==0) 
    {
		char buf[SIZ] = {0};
		int first_line = (ftell(fp_in)==0L) ? 1 : 0;    //the first_line
		int last_line = 0;      //the last_line

		fgets(buf, SIZ, fp_in);  //read a line to buf
		last_line = feof(fp_in)!=0;

		reverse_line_copy(fp_in, fp_out);   //递归
		if (first_line && !last_line && strlen(buf)!=0)  //first_line
			buf[strlen(buf)-1] = '\0';
		else if (last_line && !first_line)  //last_line
			buf[strlen(buf)] = '\n';
		fputs(buf, fp_out);
	}
}

int main(void)
{
	FILE *file_in, *file_out;
	if ((file_in=fopen("a.txt", "r"))==NULL) {
		perror("fopen error");
		exit(1);
	}
	if ((file_out=fopen("anew.txt", "w+"))==NULL) {
		perror("fopen error");
		exit(1);
	}
	reverse_line_copy(file_in, file_out);

	fclose(file_in);
	fclose(file_out);
	return 0;
} 

算法描述:

(1)本算法的主体是函数reverse_line_copy

(2)递归过程是:现在我要把1~n行字符逆向复制到别的文件中,那么我假定:如果能先把2~n行逆向复制到别的文件中,然后再把第一行复制到文件后,那么这个任务就算完成了。同理,逆向复制2~n行用的办法正是最开始的算法,从而形成递归调用。

(3)reverser_line_copy函数,先读取第一行,文件指针fp_in随即跳到第二行,然后递归调用reverser_line_copy函数,最后把第一行复制进文件中。完成!

依据这个递归算法,也可以用C++程序实现,稍微简单一点!虽说程序简单,但下面这个程序也揭示了一个大家不太关注的细节。

//C++ program
#include <iostream>
#include <fstream>
#include <deque>
#include <string>
using namespace std;

void reverse_line_copy(ifstream &inf, ofstream &outf);
int main()
{
	ifstream file_in("a.txt");
	if (!file_in) {
		cerr << "can't open file \"" << "a.txt" << "\"" << endl;
		exit(1);
	}
	ofstream file_out("anew.txt");
	if (!file_out) {
		cerr << "can't open file \"" << "anew.txt" << "\"" << endl;
		exit(1);
	}
	reverse_line_copy(file_in, file_out);
	file_in.close();
	file_out.close();
	return 0;
}

void reverse_line_copy(ifstream &inf, ofstream &outf)
{
	string aline;
	if (getline(inf, aline))
	{
		bool last_line = inf.eof() ? true : false;
		reverse_line_copy(inf, outf);
		if (last_line)
			outf << aline;
		else
			outf << aline << endl;
	}
}

上面这段C++程序之所以简单一些,是因为:

C程序里的读一行的函数fgets()返回的字符串里包含行末的换行符;而C++程序里的getline()不返回行末的换行符。

又鉴于C++提供的方便的流操作和容量可扩展的容器,下面又提供了一个C++程序的顺序实现算法。

//C++ program
#include <iostream>
#include <fstream>
#include <deque>
#include <string>
using namespace std;

int main()
{
	ifstream file_in("a.txt");
	if (!file_in) {
		cerr << "can't open file \"" << "a.txt" << "\"" << endl;
		exit(1);
	}
	deque<string> file_deque;
	string aline;
	while (file_in.good()) {
		getline(file_in, aline);
		file_deque.push_back(aline);
	}
	file_in.close();

	ofstream file_out("anew.txt");
	if (!file_out) {
		cerr << "can't open file \"" << "anew.txt" << "\"" << endl;
		exit(1);
	}
	while(!file_deque.empty()) {
		if (file_deque.size()==1)
			file_out << file_deque.back();
		else
			file_out << file_deque.back() << endl;
		file_deque.pop_back();
	}

	file_out.close();
	return 0;
}

点赞