自复制程序

发布于 2024-10-18 08:16:40 字数 915 浏览 3 评论 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++ 中可能吗?如果是这样,怎么办?

I am questioning my solution to the last exercise in Accelerated C++:

Write a self-reproducing program. Such a program is one that does no input, and that, when run, writes a copy of its own source text on the standard output stream.

My solution:

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

    }

}

This only prints out the source text of the solution (this function). Is this the solution that they had in mind?

I would like a dynamic solution that does not require hard-coding the location of the source file. However, I am not aware of a way to get the location of a source file automatically during runtime.

Another point related to that is the inclusion of "included" files, and (when encountering a function call), automatically obtaining the location of the source file that the function is stored in. To me, this would be a true "self-reproducing" program.

Is this possible in C++? If so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

近箐 2024-10-25 08:16:40

打印自身的程序称为 Quine

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

A program that prints itself is called Quine.

I think your solution wouldn't be considered valid: quines usually aren't allowed to read files (nor to get any other kind of input). It's possible to writ a Quine C++ program, here you could find many quine implementations in several languages.

鼻尖触碰 2024-10-25 08:16:40

<块引用>

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

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

#include <iostream>

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

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

I would like more of a dynamic solution (one that does not require hard-coding the location of the source file)

You know, the arguments in the main function (i.e. argc and argv). Well the first argv is the filename of the program executable. So all you need is to strip the .exe and replace with .cpp. Or, you can extract the folder from the filename and find all source files and output them. I'll let you figure it out. Here is how to print the executable's name:

#include <iostream>

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

Check it out on your system to see what it gives. If it does not display a full-path, don't worry all file opening operations will be from the same starting relative directory, so getting the relative directory of the executable will also give the relative directory to the source (assuming they are in the same folder).

毅然前行 2024-10-25 08:16:40

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

https://gist.github.com/3363087

Here's a simple quine I wrote in C++. It doesn't use any input. I think the book was looking for something along these lines, since they explicitly ruled out input (other than that, your solution to read the source file is a good one, and I thought of that too, at first).

https://gist.github.com/3363087

何处潇湘 2024-10-25 08:16:40

我刚刚上完那节课。编写一个不打开文本文件的程序并不难。您所要做的就是使用字符串向量推送每一行代码,除了对向量的推送,然后您将用于一个接一个的 for 循环事实上您可以查看我的代码,也许这将是一个更好的解释。你可能无法得到的唯一的东西是 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;
}

I just finished that lesson. It is not hard to write one that does not open a text file. All you have to do is use a vector of strings push every line of code except for the pushes on the vector you then use to for loops one right after the other in fact you can look at my code and maybe that will be a better explanation. The only thing you might not get is the for loop I used it for(auto b:a) b is an iterator on a and auto is just a quick way of declaring it.Here is the source code.

    #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;
}
留一抹残留的笑 2024-10-25 08:16:40

如果允许内联汇编,请将其放在源文件中的某个位置。它依赖于 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

If inline assembly is allowed, put this somewhere in the source file. It relies on the GNU assembler, which makes it possible to embed any data from outside.

#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__);

Now you have two identifiers source_begin and source_end. Loop through the array and print data through your favourite interface.

int main()
    {
    auto ptr=source_begin;
    auto ptr_end=source_end;
    while(ptr!=ptr_end)
        {
        putchar(*ptr);
        ++ptr;
        }
    return 0;
    }

Demo: http://coliru.stacked-crooked.com/a/d283f6dd9118b164

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文