这是一个面试题,要求把类似下面的一个文件(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;
}