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

发布于 2024-08-04 22:07:22 字数 394 浏览 3 评论 0原文

假设我有一个文件 t.txt,其中包含以下两行:

one    
two

现在,我想编写一个程序,以某种方式 #include 该文件并打印其内容,仅此而已。也就是说,我希望该文件的内容在编译时作为静态文本出现在我的代码中。

有什么想法吗?


我问的原因是这样的:

我想通过包含我自己的文件(使用 ifndefs 来防止在前两个文件之后递归包含)来创建一个 quine: wikipedia.org/wiki/Quine_(计算)" rel="nofollow noreferrer">http://en.wikipedia.org/wiki/Quine_(计算)。所以我还是很想得到答案。

Say I have a file, t.txt, that contains the following two lines:

one    
two

Now, I would like to write a program which will #include that file somehow and print its contents, nothing more. 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). So I'd still love to get an answer.

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

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

发布评论

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

评论(12

优雅的叶子 2024-08-11 22:07:22

替代解决方案(因为原始解决方案无法无限制地工作,如评论中所述):作为构建过程的一部分,使用脚本(perl 或 python 可以轻松完成)生成 staticstring.h 来自 staticstring.txt,根据需要添加引号和 \n,然后使用其他解决方案。这样你的原始文件就不会改变。

你想改成

Text file with text
on multiple
lines

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

认为纯粹用预处理器来做是不可能的。

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

栖迟 2024-08-11 22:07:22

这是 Microsoft 教程:
http://support.microsoft.com/kb/816181/en-us

它没有解释如何以编程方式或通过预处理器嵌入文件,而是通过 Visual Studio 2005+ 菜单嵌入文件。并解释了如何从资源部门读回它。

Borland Delphi 通过预处理器做到这一点,我不了解 C++。但我知道可以手动编辑资源并包含它,就像 VS 所做的那样。

This is the Microsoft Tutorial to do that:
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. And explains how to read it back from the resources sector.

Borland Delphi does that via preprocessor, I don't know about C++. But I know it is possible to edit the resources by hand and include it, just like the VS do.

羁〃客ぐ 2024-08-11 22:07:22

xxd -i

请参阅此处:之前的回答

xxd -i

See here: previous answer

邮友 2024-08-11 22:07:22

这样的事情对你有用吗?

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

我确信有一种方法可以在文本文件中不包含引号的情况下完成此操作,但现在什么也没有想到。

Would something like this work for you?

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

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.

安穩 2024-08-11 22:07:22

您可以在 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 ";" >> $@

这是做什么的。
如果您有一个名为 plop.txt 的文本文件。然后它使用变量“char const* plop =”创建一个文件 plop.text.cpp。编译后,临时文件将被删除,但如果您更改 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.
> 

You could do this in the 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. Then it creates a file plop.text.cpp with the variable 'char const* plop ='. 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

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.
> 
妄想挽回 2024-08-11 22:07:22

我所做的是这样的:

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 它。

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\"/' 
lt; >>$@ || (rm $@;exit 1)
    echo ';' >>$@ || (rm $@;exit 1)

in my Makefile. I then referred to it as extern const char *COPYING, but one can #include it as well.

装迷糊 2024-08-11 22:07:22

您可以使用 objcopy 从源文件创建目标文件并将其与实际目标文件链接。它创建符号 _binary_objfile_start、_binary_objfile_end 和 _binary_objfile_size,您可以将其作为字符数组进行访问。

You can use objcopy to create an object file out of the source file and link it with the actual object file. It creates the symbols _binary_objfile_start, _binary_objfile_end and _binary_objfile_size, which you can access as an array of char.

残花月 2024-08-11 22:07:22

据我所知,C 中最短的 quine 是这样的:

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''"') 以避免因必须转义内容而烦恼。

As far as I'm aware, the shortest possible quine in C is this:

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(). To make it valid C++, you need to do this:

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

淡忘如思 2024-08-11 22:07:22

我不相信这是可能的,因为你不能在 C 中 #include 任意文本文件。原因是 C 中没有多行常量(尽管你可以连接多个单行字符串)常数)。

我能看到的唯一选项是要求引用文本文件的每一行,或者在构建时生成一个临时文件(正如其他人所建议的那样)。

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

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

老街孤人 2024-08-11 22:07:22

tt:

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

tc

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


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

更新:
如果您不是追求纯粹的 quine,而只是追求包含文件内容的东西,您可以执行以下操作:

tc:

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

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

运行此产量

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

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

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:

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

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;
}
青春有你 2024-08-11 22:07:22

这非常简单:

#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 代码和/或
正如我上面所做的那样定义。

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

与他有关 2024-08-11 22:07:22
  • 将资源文件添加到您的项目中。
  • 双击资源文件 ({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 for 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);

就这样

了在奎因(计算)中看不到任何意义。
多态性是另一个故事;)
玩得开心。

  • Add resource file to your project.
  • Open resource editor by double clicking on resource file ({projectname}.rc).
  • In resource editor add custom type, for example CPPCODE.
  • Enter some binary data into binary content of that resource file.
  • Save all, and close resource editor.
  • Open {projectname}.rc file as code.
  • Locate CPPCODE and replace file path in quotes to file where your {projectname}.cpp file resides (relative path). 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:

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).
Polymorphism is another story ;)
have fun.

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