閑來沒事,想起還有這樣一個玩意,所以就做了,不知道符合要求不-,-
記得以前有個很短的,不過無法通過編譯=。=
// File Name : print_self.cpp
// Author : keakon
// Create Date : 2006/5/27
// Last Edited Date : 2006/5/28
// Description : Print its own source code in stdout.
#include <algorithm>
//#include <cstdlib> //rand()和srand()需要,但<algorithm>和<fstream>已包含
#include <ctime>
#include <fstream>
#include <iostream>
//#include <iterator> //ostream_iterator需要,但<algorithm>已包含
#include <string>
using namespace std;
string& getCppPath(string& path)
//若只傳遞const char**型的參數,則必須返回一個string
//或一個static的string&,這都是無謂的開銷
//若傳遞string&型的參數,則最好傳遞前就用char*初始化,因此無需其他參數
//返回string&是讓其可以嵌套在其他參數為string&或string的函數中使用
//這個函數做了5個假設:
//1是可執行檔和來源程式的檔案名稱相同(不包括尾碼名)
//2是路徑用“/”作為分隔字元,可以改為“/”在UNIX和Linux下使用
//3是將最後一個“.”作為該可執行檔尾碼名的開始
//4是來源程式路徑為“./”,即當前工程的檔案夾下
//5是該來源程式的尾碼名為.cpp
//可見這個程式大部分都是判斷得出檔案名稱,若允許給main()傳遞參數的話,就簡單多了
{
typedef string::size_type str_sz;
const char PATH_DIVIDER[] = "//";
str_sz index = path.rfind(PATH_DIVIDER); //找最後一個“/”
const str_sz BEGIN = 0;
index = (index == string::npos) ? BEGIN : ++index;
//若沒找到則index為0,否則加1去掉“/”
path.erase(BEGIN, index); //去掉“/”之前的字元
const char SUFFIX_BEGIN[] = ".";
index = path.rfind(SUFFIX_BEGIN); //找最後一個“.”
if (index == string::npos)
{index = path.size();}
//若沒找到則index為最後的元素後面
//感覺返回npos很麻煩,為什麼不像STL中返回最後一個後面的索引呢=。=
path.erase(index, path.size() - index); //去掉“.”之後的字元
const string PATH(".//");
//預設路徑名,因為在VC++6.0中,來源程式在當前工程的檔案夾下
//這個不加也行,因為預設就是當前檔案夾
const string SUFFIX(".cpp");
//預設尾碼名,因為在VC++6.0中,C++來源程式的尾碼名為.cpp
path = PATH + path + SUFFIX; //補充檔案名稱的路徑和尾碼名
return path;
}
void print0(istream& in)
{
string buf;
while (getline(in, buf))
//檔案開啟失敗也沒有危害,因為只是簡單地返回false退出迴圈
//唯一的缺點是沒有提示出錯罷了,所以我不檢查in了
//這句改成getline(in, buf, '/0')一次讀取完檔案,理論上可行
//這假設了檔案中未使用'/0'字元,且檔案大小不超過64k
//因為string對象的最大字元數為64k
{
buf += '/n'; //getline丟棄了分行符號,需要添加
copy(buf.begin(), buf.end(), ostream_iterator<char>(cout));
//輸出一行內容到cout
}
}
void print1(istream& in)
//print0()也可改為用char處理
{
const streamsize BUF_SIZE = 1024;
char buf[BUF_SIZE];
while (in.getline(buf, BUF_SIZE))
{cout << buf << endl;}
}
void print2(istream& in)
//print1()也可以用copy來實現
{
const streamsize BUF_SIZE = 1024;
char buf[BUF_SIZE];
while (in.getline(buf, BUF_SIZE))
{
char* pc = find(buf, buf + BUF_SIZE, '/0');
//找字串的結尾('/0')
*pc = '/n'; //修改為換行以輸出
copy(buf, pc + 1, ostream_iterator<char>(cout));
//pc + 1為結束邊界
}
}
int main(int argc, char** agrv)
{
string path(*agrv); //將可執行檔的路徑儲存為path字串
ifstream in(getCppPath(path).c_str());
//從path中提取cpp檔案路徑,然後轉化為C風格的字串用以開啟檔案
void (* print[3])(istream&); //定義一個函數指標數組
print[0] = print0;
print[1] = print1;
print[2] = print2;
srand(time(0));
print[rand() % 3](in); //隨機播放一個函數運行
in.close();
return 0;
}