简体   繁体   English

使用#include指令(预处理器)打印文件的内容

[英]Printing the contents of a file using the #include directive (preprocessor)

Say I have a file, t.txt, that contains the following two lines: 假设我有一个文件t.txt,其中包含以下两行:

one    
two

Now, I would like to write a program which will #include that file somehow and print its contents, nothing more. 现在,我想编写一个程序,它将以某种方式#include该文件并打印其内容,仅此而已。 That is, I want the contents of that file to appear in my code as a static text, at compile time. 也就是说,我希望该文件的内容在编译时以静态文本的形式出现在我的代码中。

Any ideas? 有任何想法吗?


The reason im asking is this: 我问的原因是这样的:

I would like to create a quine by including my own file (with ifndefs to prevent recursive inclusion after the first two): http://en.wikipedia.org/wiki/Quine_(computing) . 我想通过包含我自己的文件(使用ifndefs来防止在前两个之后包含递归包含)来创建一个quine: http : //en.wikipedia.org/wiki/Quine_ ( ifndefs So I'd still love to get an answer. 所以我仍然很想得到答案。

Alternative solution (since the original one won't work without limitations, as mentioned in the comments): As part of your build process, use a script (perl or python would do it easily) to generate staticstring.h from staticstring.txt , adding quotes and \\n 's as necessary, then use the other solution. 另一种解决方案(因为原来的人会并非没有限制的工作,如在评论中提到的):作为构建过程的一部分,使用脚本(Perl或Python很容易做到这一点)来生成staticstring.hstaticstring.txt ,根据需要添加引号和\\n ,然后使用其他解决方案。 This way your original file does not change. 这样,您的原始文件不会更改。

You want to change 你想改变

Text file with text
on multiple
lines

to

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

I think that doing it purely with the preprocessor is not possible. 我认为仅靠预处理器是不可能的。

This is the Microsoft Tutorial to do that: http://support.microsoft.com/kb/816181/en-us 这是要执行此操作的Microsoft教程: http : //support.microsoft.com/kb/816181/en-us

It is not explaining how to embedd the file programatically or via preprocessor, but via the Visual Studio 2005+ menus. 它不是在解释如何以编程方式或通过预处理器嵌入文件,而是通过Visual Studio 2005+菜单。 And explains how to read it back from the resources sector. 并说明如何从资源部门读回它。

Borland Delphi does that via preprocessor, I don't know about C++. Borland Delphi是通过预处理器完成的,我不了解C ++。 But I know it is possible to edit the resources by hand and include it, just like the VS do. 但是我知道可以像VS一样手动编辑资源并将其包含在内。

xxd -i

看到这里: 以前的答案

Would something like this work for you? 这样的事情对您有用吗?

example.c example.c

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

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

staticstring.txt staticstring.txt

"Some string that gets included at compile time"

I'm sure there's a way that you can do it without having the quotes inside the text file, but nothing is coming to mind right now. 我敢肯定有一种方法可以在文本文件中不加引号的情况下完成此操作,但是现在什么都没想到。

You could do this in the makefile: 您可以在makefile中执行此操作:

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 ";" >> $@

What this does. 这是做什么的。
If you have a text file called plop.txt. 如果您有一个名为plop.txt的文本文件。 Then it creates a file plop.text.cpp with the variable 'char const* plop ='. 然后,它使用变量'char const * plop ='创建文件plop.text.cpp。 Once compiled the temporary file is removed but if you change the plop.txt file it will be auto-magically be rebuilt into plop.text.o 编译后,临时文件将被删除,但是如果您更改plop.txt文件,它将自动神奇地重新构建为plop.text.o

This is then all combined together: 然后将它们全部组合在一起:

The following Example is what I tested: 以下示例是我测试的:

> 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.
> 

What I did was this: 我所做的是:

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)

in my Makefile . 在我的Makefile I then referred to it as extern const char *COPYING , but one can #include it as well. 然后,我将其称为extern const char *COPYING ,但也可以#include它。

You can use objcopy to create an object file out of the source file and link it with the actual object file. 您可以使用objcopy从源文件中创建一个目标文件,并将其与实际目标文件链接。 It creates the symbols _binary_objfile_start, _binary_objfile_end and _binary_objfile_size , which you can access as an array of char. 它创建符号_binary_objfile_start, _binary_objfile_end and _binary_objfile_size ,您可以将其作为char数组进行访问。

As far as I'm aware, the shortest possible quine in C is this: 据我所知,C语言中最短的quine是这样的:

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

Note that this is not valid C++, since it uses an implicit definition of printf() . 请注意,这不是有效的C ++,因为它使用了printf()的隐式定义。 To make it valid C++, you need to do this: 要使其成为有效的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);}

No tricky include tricks -- just carefully constructing a string and printing it out twice, and using ASCII codes (10 and 34 instead of '\\n' and '"' ) to avoid annoyingness with having to escape stuff. 没有棘手的技巧,只需精心构造一个字符串并将其打印两次,然后使用ASCII码(用10和34代替'\\n''"' ),就可以避免不得不转义的麻烦。

I don't believe it's going to be possible, as you can't #include an arbitrary text file in C. The reason is that there are no multi-line constants in C (although you can concatenate a number of single-line string constants). 我不相信这是有可能的,因为您无法#在C中包含任意文本文件。原因是C中没有多行常量(尽管您可以连接多个单行字符串)常量)。

The only options I can see are to require that each line of the text file be quoted, or generate a temporary file at build-time (as others have suggested). 我能看到的唯一选项是要求文本文件的每一行都加引号,或者在构建时生成一个临时文件(如其他建议)。

tt: TT:

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

tc TC

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


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

Update: If you are not after a pure quine, but just something that will spit out the contents of the included file, you can do the following: 更新:如果您不是追求纯粹的奎因,而是仅仅吐出包含文件内容的东西,则可以执行以下操作:

tc: TC:

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

tt: TT:

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

running this yields 运行这个产量

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

It's very easy: 这很简单:

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

Seriously, it's not possible to "#include" an arbitrary file. 严重的是,不可能“ #include”任意文件。 (Go with one of the preprocessing suggestions given in other answers if you need this.) (如果需要,请使用其他答案中给出的预处理建议之一。)

If the contents of the file is not arbitrary, but contains something meaningful to the compiler, you might be able to hack something together. 如果文件的内容不是任意的,而是包含对编译器有意义的内容,则您可以将某些内容结合在一起。 To make the contents meaningful, you can use C code and/or define's as I did above. 为了使内容有意义,您可以使用C代码和/或定义上面的代码。

  • Add resource file to your project. 将资源文件添加到您的项目。
  • Open resource editor by double clicking on resource file ({projectname}.rc). 双击资源文件({projectname} .rc),打开资源编辑器。
  • In resource editor add custom type, for example CPPCODE. 在资源编辑器中添加自定义类型,例如CPPCODE。
  • Enter some binary data into binary content of that resource file. 在该资源文件的二进制内容中输入一些二进制数据。
  • Save all, and close resource editor. 保存所有,然后关闭资源编辑器。
  • Open {projectname}.rc file as code. 打开{projectname} .rc文件作为代码。
  • Locate CPPCODE and replace file path in quotes to file where your {projectname}.cpp file resides (relative path). 找到CPPCODE并将引号中的文件路径替换为{projectname} .cpp文件所在的文件(相对路径)。 It should look something like this: 它看起来应该像这样:

Code: 码:

IDR_FILE_DIRECTORYINFO_H    CPPCODE "DirectoryInfo.h"
IDR_FILE_DIRECTORYINFO_CPP  CPPCODE "DirectoryInfo.cpp"
  • Check resource.h does it contains correct #defines for IDR_FILE_DIRECTORYINFO_H, ..., if you have added additional entries: 如果添加了其他条目,请检查resource.h是否包含IDR_FILE_DIRECTORYINFO_H ...的正确#定义,...:

Code: 码:

#define IDR_FILE_DIRECTORYINFO_H        312
#define IDR_FILE_DIRECTORYINFO_CPP      313
  • Access, and print resource content: 访问和打印资源内容:

Code: 码:

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

And that's it 就是这样

Al trough I don't see any point in Quine (computing). 槽我看不到Quine(计算)中的任何内容。 Polymorphism is another story ;) have fun. 多态是另一个故事;)玩得开心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM