Печать содержимого файла с использованием директивы #include (препроцессор) - PullRequest
0 голосов
/ 14 сентября 2009

Допустим, у меня есть файл t.txt, который содержит следующие две строки:

one    
two

Теперь я хотел бы написать программу, которая каким-то образом #include запишет этот файл и напечатает его содержимое, не более того. То есть я хочу, чтобы содержимое этого файла отображалось в моем коде как статический текст во время компиляции.

Есть идеи?


Причина, по которой я спрашиваю, такова:

Я хотел бы создать квинну, включив свой собственный файл (с ifndefs, чтобы предотвратить рекурсивное включение после первых двух): http://en.wikipedia.org/wiki/Quine_(computing). Так что я все еще хотел бы получить ответ.

Ответы [ 12 ]

2 голосов
/ 14 сентября 2009

Альтернативное решение (поскольку оригинальное решение не будет работать без ограничений, как упомянуто в комментариях): как часть вашего процесса сборки, используйте сценарий (Perl или Python сделает это легко) для генерации staticstring.h из staticstring.txt, добавляя кавычки и \n, если необходимо, затем используйте другое решение. Таким образом, ваш исходный файл не изменится.

Вы хотите изменить

Text file with text
on multiple
lines

до

"Text file with text\n"
"on multiple\n"
"lines"

Я думаю, что сделать это чисто с препроцессором невозможно.

1 голос
/ 15 сентября 2009

xxd -i

Смотрите здесь: предыдущий ответ

1 голос
/ 14 сентября 2009

Это руководство Microsoft для этого: http://support.microsoft.com/kb/816181/en-us

Это не объясняет, как внедрить файл программно или через препроцессор, а через меню Visual Studio 2005+. И объясняет, как читать его из сектора ресурсов.

Borland Delphi делает это через препроцессор, я не знаю о C ++. Но я знаю, что можно редактировать ресурсы вручную и включать их, как VS.

0 голосов
/ 27 ноября 2013
  • Добавить файл ресурсов в ваш проект.
  • Откройте редактор ресурсов, дважды щелкнув файл ресурсов ({имя проекта} .rc).
  • В редакторе ресурсов добавьте пользовательский тип, например CPPCODE.
  • Введите некоторые двоичные данные в двоичное содержимое этого файла ресурсов.
  • Сохраните все и закройте редактор ресурсов.
  • Открыть файл {projectname} .rc в виде кода.
  • Найдите CPPCODE и замените путь файла в кавычках на файл, в котором находится ваш файл {projectname} .cpp (относительный путь). Это должно выглядеть примерно так:

Код:

IDR_FILE_DIRECTORYINFO_H    CPPCODE "DirectoryInfo.h"
IDR_FILE_DIRECTORYINFO_CPP  CPPCODE "DirectoryInfo.cpp"
  • Проверьте, содержит ли resource.h правильные #defines для IDR_FILE_DIRECTORYINFO_H, ..., если вы добавили дополнительные записи:

Код:

#define IDR_FILE_DIRECTORYINFO_H        312
#define IDR_FILE_DIRECTORYINFO_CPP      313
  • Доступ и печать содержимого ресурса:

Код:

HRSRC hRes = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_FILE_DIRECTORYINFO_CPP), _T("CPPCODE"));
DWORD dwSize = SizeofResource(GetModuleHandle(NULL), hRes);
HGLOBAL hGlob = LoadResource(GetModuleHandle(NULL), hRes);
const char* pData = reinterpret_cast<const char*>(::LockResource(hGlob));

MessageBoxA((HWND)0, pData, "This project source code:", MB_OK);

И это все

Несмотря на то, что я не вижу никакой точки в Куайне (вычисления). Полиморфизм это другая история;) веселиться.

0 голосов
/ 25 сентября 2009

Это очень просто:

#include <stdio.h>

// include the file somehow
#define one 
#define two 
#include "t.txt"

int main(int argc, char* argv[])
{
    // and print the contents of the file
    const char* static_text = "one\ntwo\n";
    printf(static_text);

    // nothing more ;-)
    return 0;
}

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

Если содержимое файла не произвольно, а содержит что-то значение для компилятора, вы можете взломать что-то все вместе. Чтобы сделать содержимое осмысленным, вы можете использовать C-код и / или определите, как я делал выше.

0 голосов
/ 25 сентября 2009

t.t:

printf ("int main () {\n");
printf ("#include <t.t>\n");
printf ("}");
return 0;

t.c

int main () {
#include <t.t>
}


$ gcc -I. t.c
$ ./a.out
int main () {
#include <t.t>
} 

Обновление: Если вам не нужен чистый квин, а просто что-то, что выплюнет содержимое включенного файла, вы можете сделать следующее:

t.c:

#include <stdio.h>
#include "t.t"

t.t:

#define FOO(f) do { \
        FILE * ff = fopen(f, "rb"); \
        char foo[255] = {0}; \
        while (fgets (foo, 255, ff)) { \
                printf ("%s", foo); \
        }\
        fclose(ff); \
} while (0)

int main () {
        FOO("t.t");
        return 0;
}

выполнение этого приводит к

$ gcc t.c
$ ./a.out
#define FOO(f) do { \
        FILE * ff = fopen(f, "rb"); \
        char foo[255] = {0}; \
        while (fgets (foo, 255, ff)) { \
                printf ("%s", foo); \
        }\
        fclose(ff); \
} while (0)

int main () {
        FOO("t.t");
        return 0;
}
0 голосов
/ 25 сентября 2009

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

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

0 голосов
/ 25 сентября 2009

Насколько я знаю, самый короткий из возможных кваинов в C такой:

main(){char*a="main(){char*a=%c%s%c;printf(a,34,a,34);}";printf(a,34,a,34);}

Обратите внимание, что это недопустимый C ++, поскольку он использует неявное определение printf(). Чтобы сделать его действительным C ++, вам нужно сделать следующее:

#include <stdio.h>
main(){char*a="#include <stdio.h>%cmain(){char*a=%c%s%c;printf(a,10,34,a,34);}";printf(a,10,34,a,34);}

Нет хитростей, включающих трюки - просто аккуратно создайте строку и напечатайте ее дважды, и используйте коды ASCII (10 и 34 вместо '\n' и '"'), чтобы избежать раздражения от необходимости избегать вещей.

0 голосов
/ 25 сентября 2009

Вы можете использовать objcopy, чтобы создать объектный файл из исходного файла и связать его с реальным объектным файлом. Он создает символы _binary_objfile_start, _binary_objfile_end and _binary_objfile_size, к которым вы можете обращаться как массив символов.

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

Что я сделал, это было:

COPYING.cc: ${top_srcdir}/COPYING
    echo "const char * COPYING = " >$@ || (rm $@;exit 1)
    sed -e 's/"/\\"/g' -e 's/^/\"/' -e 's/$$/\\n\"/' $< >>$@ || (rm $@;exit 1)
    echo ';' >>$@ || (rm $@;exit 1)

по моему Makefile. Затем я назвал его extern const char *COPYING, но можно и #include.

...