Самовоспроизводящаяся программа - PullRequest
0 голосов
/ 19 февраля 2011

Я подвергаю сомнению свое решение последнего упражнения в 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 ++?Если да, то как?

Ответы [ 5 ]

8 голосов
/ 19 февраля 2011

Программа, которая печатает сама себя, называется Quine .

Я думаю, что ваше решение не будет считаться действительным: обычно кинам не разрешается ни читать файлы (ни получать какие-либо другие данные). Можно написать программу для Quine C ++, здесь вы можете найти множество реализаций quine на нескольких языках.

4 голосов
/ 19 февраля 2011

Мне бы хотелось больше динамического решения (которое не требует жесткого кодирования местоположения исходного файла)

Вы знаете, аргументы в главной функции (то есть argc и argv). Первый аргумент argv - это имя исполняемого файла программы. Так что все, что вам нужно, это удалить .exe и заменить на .cpp. Или вы можете извлечь папку из имени файла, найти все исходные файлы и вывести их. Я позволю тебе разобраться. Вот как напечатать имя исполняемого файла:

#include <iostream>

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

Проверьте это в своей системе, чтобы увидеть, что это дает. Если он не отображает полный путь, не волнуйтесь, все операции открытия файлов будут происходить из одного и того же начального относительного каталога, поэтому получение относительного каталога исполняемого файла также даст относительный каталог источнику (при условии, что они находятся в та же папка).

0 голосов
/ 11 ноября 2016

Если встроенная сборка разрешена, поместите это где-нибудь в исходный файл.Он основан на ассемблере 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_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

0 голосов
/ 23 сентября 2013

Я только что закончил этот урок.Не сложно написать тот, который не открывает текстовый файл.Все, что вам нужно сделать, это использовать вектор строк, толкающий каждую строку кода, за исключением толчков в векторе, которые вы затем используете для циклов 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;
}
0 голосов
/ 15 августа 2012

Вот простая цитата, которую я написал на C ++.Он не использует никаких входных данных.Я думаю, что книга искала что-то в этом роде, поскольку они явно исключали ввод (кроме этого, ваше решение для чтения исходного файла - хорошее, и я тоже подумал об этом сначала).

https://gist.github.com/3363087

...