自我复制程序

我在质疑我对Accelerated C ++的最后一个练习的解决方案:   写一个自我复制的程序。这样的程序是没有输入的程序,并且在运行时,在标准输出流上写入其自己的源文本的副本。 我的解决方案
using std::string;
using std::cout;
using std::endl;
using std::ifstream;
using std::getline;

void selfReproduce16_1()
{
    ifstream thisFile("C:\Users\Kevin\Documents\NetBeansProjects\Accelerated_C++_Exercises\Chapter_16.cpp", ifstream::in);

    string curLine;

    bool foundHeader = false;

    while(getline(thisFile, curLine))
    {
        if(!curLine.compare("void selfReproduce16_1()") || foundHeader)
        {
            foundHeader = true;
            cout << curLine << endl;
        }

    }

}
这仅打印出解决方案的源文本(此功能)。这是他们想到的解决方案吗? 我想要一个动态解决方案,不需要硬编码源文件的位置。但是,我不知道在运行时自动获取源文件位置的方法。 与此相关的另一点是包含“包含”文件,以及(当遇到函数调用时),自动获取存储函数的源文件的位置。对我来说,这将是一个真正的“自我复制” “节目。 这在C ++中是否可行?如果是这样,怎么样?     
已邀请:
打印自己的程序称为Quine。 我认为你的解决方案不会被认为是有效的:quines通常不允许读取文件(也不能获得任何其他类型的输入)。编写Quine C ++程序是可能的,在这里您可以找到许多语言的许多quine实现。     
       我想要一个更动态的解决方案(一个不需要硬编码源文件位置的解决方案)    你知道,main函数中的参数(即argc和argv)。那么第一个argv是程序可执行文件的文件名。所以你需要的是剥离.exe并替换为.cpp。或者,您可以从文件名中提取文件夹并查找所有源文件并输出它们。我会让你搞清楚的。以下是如何打印可执行文件的名称:
#include <iostream>

int main(int argc, char** argv) {
  std::cout << argv[0] << std::endl;
  return 0;
};
在您的系统上查看它,看看它给出了什么。如果它没有显示完整路径,请不要担心所有文件打开操作都来自相同的起始相对目录,因此获取可执行文件的相对目录也会将相对目录提供给源(假设它们位于同一文件夹)。     
这是我用C ++编写的一个简单的quine。它不使用任何输入。我认为这本书正在寻找这些方面的东西,因为他们明确排除了输入(除此之外,你阅读源文件的解决方案是一个很好的解决方案,起初我也想到了这一点)。 https://gist.github.com/3363087     
我刚完成那一课。编写一个不打开文本文件的文件并不难。所有你需要做的就是使用一个字符串向量推送每一行代码,除了推动向量然后用于一个接一个的循环,实际上你可以查看我的代码,也许这将是一个更好的解释。你可能得不到的唯一东西是我用它的for循环(auto b:a)b是a上的迭代器而auto是一种快速声明它的方法。这是源代码。
    #include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<string> a;
push:
a.push_back("#include "stdafx.h"");
a.push_back("#include <vector>");
a.push_back("#include <string>");
a.push_back("#include <iostream>");
a.push_back("using namespace std;");
a.push_back("using namespace std;");
a.push_back("int main()");
a.push_back("{");
a.push_back("vector<string> a;");
a.push_back("push:");
a.push_back("for(auto b:a)");
a.push_back("{");
a.push_back("cout << b << endl;");
a.push_back("if(b == "push:")");
a.push_back("{");
a.push_back("for(auto c:a)");
a.push_back("{");
a.push_back("cout << "a.push_back(\"" << c << \"";" << endl;");
a.push_back("}");
a.push_back("}");
a.push_back("}");
a.push_back("return 0;");
a.push_back("}");
for(auto b:a)
{
    cout << b << endl;
    if(b == "push:")
    {
        for(auto c:a)
        {
            cout << "a.push_back("" << c << "");" << endl;
        }
    }
}
return 0;
}
    
如果允许内联汇编,请将其放在源文件中的某处。它依赖于GNU汇编程序,可以从外部嵌入任何数据。
#include <cstdint>
extern "C"
{
#if __gnu_linux__

#define BLOB(identifier,filename) 
asm(".pushsection .datan" 
    "t.local " #identifier "_beginn" 
    "t.type " #identifier "_begin, @objectn" 
    "t.align 16n" 
    #identifier "_begin:n" 
    "t.incbin "" filename ""nn" 

    "t.local " #identifier "_endn" 
    "t.type " #identifier "_end, @objectn" 
    "t.align 1n" 
    #identifier "_end:n" 
    "t.byte 0n" 
    "t.popsectionn"); 

extern const uint8_t identifier##_begin[];
extern const uint8_t identifier##_end[]

#elif _WIN32

#define BLOB(identifier,filename) 
asm(".datan" 
    "t.align 16n" 
    #identifier "_begin:n" 
    "t.incbin "" filename ""nn" 

    "t.align 1n" 
    #identifier "_end:n" 
    "t.byte 0n" 
    "t.textn"); 

extern const uint8_t identifier##_begin[];
extern const uint8_t identifier##_end[]

#else
    #error "Cannot include binary files"
#endif
}

BLOB(source,__FILE__);
现在你有两个标识符
source_begin
source_end
。循环遍历数组并通过您喜欢的界面打印数据。
int main()
    {
    auto ptr=source_begin;
    auto ptr_end=source_end;
    while(ptr!=ptr_end)
        {
        putchar(*ptr);
        ++ptr;
        }
    return 0;
    }
演示:http://coliru.stacked-crooked.com/a/d283f6dd9118b164     

要回复问题请先登录注册