打印自身的程序

来源:互联网 发布:淘宝网自动充值平台 编辑:程序博客网 时间:2024/05/16 09:51

闲来没事,想起还有这样一个玩意,所以就做了,不知道符合要求不-,-

记得以前有个很短的,不过无法通过编译=。=


// 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;
}

原创粉丝点击