這是一個面試題,要求把類似下面的一個文件(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;
}