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

时间:2009-09-14 18:56:30

标签: c++ include c-preprocessor

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

one    
two

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

有什么想法吗?


我问的原因是:

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

12 个答案:

答案 0 :(得分:2)

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

您想要更改

Text file with text
on multiple
lines

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

我认为用纯预处理器完成它是不可能的。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

xxd -i

见这里:previous answer

答案 3 :(得分:0)

这样的事情对你有用吗?

<强> 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"

我确信有一种方法可以在文本文件中没有引号的情况下完成,但现在没有任何想法。

答案 4 :(得分:0)

您可以在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的文本文件。然后它创建一个文件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.
> 

答案 5 :(得分:0)

我做的是:

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

据我所知,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''"')以避免因为不得不逃避东西而烦人

答案 8 :(得分:0)

我不相信它是可能的,因为你不能在C中#include任意文本文件。原因是C中没有多行常量(尽管你可以连接多个单行-line string constants)。

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

答案 9 :(得分: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>
} 

更新: 如果你不是在纯粹的quine之后,而是只是吐出包含文件内容的东西,你可以执行以下操作:

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

答案 10 :(得分: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代码和/或 像我上面那样定义。

答案 11 :(得分:0)

  • 将资源文件添加到项目中。
  • 双击资源文件({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的#defines,...,如果您添加了其他条目:

代码:

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

就是这样

Al trough我在Quine(计算)中没有看到任何意义。 多态性是另一个故事;) 玩得开心。