繁体   English   中英

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

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

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

one    
two

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

有任何想法吗?


我问的原因是这样的:

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

另一种解决方案(因为原来的人会并非没有限制的工作,如在评论中提到的):作为构建过程的一部分,使用脚本(Perl或Python很容易做到这一点)来生成staticstring.hstaticstring.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

看到这里: 以前的答案

这样的事情对您有用吗?

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"

我敢肯定有一种方法可以在文本文件中不加引号的情况下完成此操作,但是现在什么都没想到。

您可以在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.
> 

我所做的是:

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

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

据我所知,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''"' ),就可以避免不得不转义的麻烦。

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

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

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

更新:如果您不是追求纯粹的奎因,而是仅仅吐出包含文件内容的东西,则可以执行以下操作:

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

这很简单:

#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代码和/或定义上面的代码。

  • 将资源文件添加到您的项目。
  • 双击资源文件({projectname} .rc),打开资源编辑器。
  • 在资源编辑器中添加自定义类型,例如CPPCODE。
  • 在该资源文件的二进制内容中输入一些二进制数据。
  • 保存所有,然后关闭资源编辑器。
  • 打开{projectname} .rc文件作为代码。
  • 找到CPPCODE并将引号中的文件路径替换为{projectname} .cpp文件所在的文件(相对路径)。 它看起来应该像这样:

码:

IDR_FILE_DIRECTORYINFO_H    CPPCODE "DirectoryInfo.h"
IDR_FILE_DIRECTORYINFO_CPP  CPPCODE "DirectoryInfo.cpp"
  • 如果添加了其他条目,请检查resource.h是否包含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);

就是这样

槽我看不到Quine(计算)中的任何内容。 多态是另一个故事;)玩得开心。

暂无
暂无

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

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