闲来没事,想起还有这样一个玩意,所以就做了,不知道符合要求不-,-
记得以前有个很短的,不过无法通过编译=。=
// 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;
}