Печать содержимого файла с помощью директивы #include (препроцессор)

StackOverflow https://stackoverflow.com/questions/1423297

  •  07-07-2019
  •  | 
  •  

Вопрос

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

one    
two

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

Есть какие-нибудь идеи?


Причина, по которой я спрашиваю, заключается в следующем:

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

Это было полезно?

Решение

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

Ты хочешь измениться

Text file with text
on multiple
lines

Для

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

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

Другие советы

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

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

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

xxd -i

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

Сработало бы что-то подобное для вас?

пример.c

static const char *var = 
#include "staticstring.txt"
;

int main() {
    printf( "%s\n" var );
    return 0;
}

staticstring.txt

"Some string that gets included at compile time"

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

Вы можете сделать это в make-файле:

all:  target

TEXT_FILES  = $(wildcard *.txt)
TEXT_OBJS   = $(patsubst %.txt,%.text.o,$(TEXT_FILES))


target: main.o $(TEXT_OBJS)
    $(CXX) -o app $^

%.text.cpp: %.txt
    @echo "Building Text Source $*"
    @echo "char const* $* =" > $@
    @awk '{print "\"" $0 "\\n\"";}' $^ >> $@
    @echo ";" >> $@

Что это делает.
Если у вас есть текстовый файл с именем plop.txt. Затем он создает файл plop.text.cpp с переменной 'char const * plop ='. После компиляции временный файл удаляется, но если вы измените файл plop.txt, он будет автоматически перестроен в plop.text.o

Затем все это объединяется:

Следующий пример - это то, что я тестировал:

> cat main.cpp

#include <iostream>
extern char* text;

int main()
{
std::cout << text;
}

> cat text.txt 

Hi there this is a file
with multiple lines
we want to print out.
> make
g++    -c -o main.o main.cpp
Building Text Source text
g++    -c -o text.text.o text.text.cpp
g++ -o app main.o text.text.o
rm text.text.cpp
> ./app

Hi there this is a file
with multiple lines
we want to print out.
> 

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

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

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

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

Насколько я знаю, самая короткая из возможных квин в 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' и '"' ), чтобы избежать раздражения от необходимости избегать вещей.

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

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

т.т:

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

т.к

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


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

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

т.к:

#include <stdio.h>
#include "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;
}

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

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

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

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

  • Добавьте файл ресурсов в свой проект.
  • Откройте редактор ресурсов, дважды щелкнув файл ресурсов ({projectname}.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);

И это все

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top