0

我质疑我对 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++ 中可能吗?如果是这样,怎么做?

4

5 回答 5

8

打印自身的程序称为Quine

我认为您的解决方案不会被认为是有效的:quines 通常不允许读取文件(也不允许获得任何其他类型的输入)。可以编写 Quine C++ 程序,在这里您可以找到多种语言的许多 quine 实现。

于 2011-02-19T20:22:12.400 回答
4

我想要更多的动态解决方案(不需要硬编码源文件位置的解决方案)

您知道,主函数中的参数(即 argc 和 argv)。那么第一个 argv 是程序可执行文件的文件名。因此,您只需剥离 .exe 并替换为 .cpp。或者,您可以从文件名中提取文件夹并找到所有源文件并输出它们。我会让你弄清楚的。以下是如何打印可执行文件的名称:

#include <iostream>

int main(int argc, char** argv) {
  std::cout << argv[0] << std::endl;
  return 0;
};

在您的系统上检查它,看看它提供了什么。如果它不显示完整路径,请不要担心所有文件打开操作都来自同一个起始相对目录,因此获取可执行文件的相对目录也会将相对目录提供给源(假设它们在同一个文件夹)。

于 2011-02-19T20:32:59.840 回答
0

这是我用 C++ 编写的一个简单的 quine。它不使用任何输入。我认为这本书正在寻找这些方面的东西,因为它们明确排除了输入(除此之外,您读取源文件的解决方案是一个很好的解决方案,我一开始也想到了这一点)。

https://gist.github.com/3363087

于 2012-08-15T19:59:37.160 回答
0

我刚上完那节课。编写一个不打开文本文件的文件并不难。你所要做的就是使用一个字符串向量推送每一行代码,除了向量上的推送,然后你一个接一个地用于循环实际上你可以看看我的代码,也许这会是一个更好的解释. 唯一你可能没有得到的是我使用的 for 循环 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;
}
于 2013-09-23T19:06:12.833 回答
0

如果允许内联汇编,请将其放在源文件中的某个位置。它依赖于 GNU 汇编器,这使得从外部嵌入任何数据成为可能。

#include <cstdint>
extern "C"
{
#if __gnu_linux__

#define BLOB(identifier,filename) \
asm(".pushsection .data\n" \
    "\t.local " #identifier "_begin\n" \
    "\t.type " #identifier "_begin, @object\n" \
    "\t.align 16\n" \
    #identifier "_begin:\n" \
    "\t.incbin \"" filename "\"\n\n" \
\
    "\t.local " #identifier "_end\n" \
    "\t.type " #identifier "_end, @object\n" \
    "\t.align 1\n" \
    #identifier "_end:\n" \
    "\t.byte 0\n" \
    "\t.popsection\n"); \
\
extern const uint8_t identifier##_begin[];\
extern const uint8_t identifier##_end[]

#elif _WIN32

#define BLOB(identifier,filename) \
asm(".data\n" \
    "\t.align 16\n" \
    #identifier "_begin:\n" \
    "\t.incbin \"" filename "\"\n\n" \
\
    "\t.align 1\n" \
    #identifier "_end:\n" \
    "\t.byte 0\n" \
    "\t.text\n"); \
\
extern const uint8_t identifier##_begin[];\
extern const uint8_t identifier##_end[]

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

BLOB(source,__FILE__);

现在你有两个标识符source_beginsource_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

于 2016-11-11T09:27:46.133 回答