2009-09-14 41 views
0

说我有一个文件,t.txt,包含以下两行打印文件的内容:使用#include指令(预处理)

one  
two 

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

任何想法?


原因IM问的是这样的:

我想通过包括我自己的文件(ifndefs,以防止前两个后递归包含)创建奎因:http://en.wikipedia.org/wiki/Quine_(computing)。所以我仍然喜欢得到答案。

+0

这是一个重复的地方。 –

+0

你可以在编译前运行一些外部脚本或可执行文件,从给定的txt文件生成一个.h文件吗? – Virne

+0

@Virne,txt与任何.h文件没有什么不同。事情是我不想对包含的文件进行任何修改。 – rmn

回答

2

另一种解决方案(因为原来的版本不会在没有限制的情况下工作,如注释中所述):作为构建过程的一部分,使用脚本(perl或python可以轻松完成)从staticstring.txt生成staticstring.h,根据需要添加引号和\n,然后使用其他解决方案。这样你的原始文件不会改变。

你想改变

Text file with text 
on multiple 
lines 

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

我认为,随着预处理器这样做纯粹是不可能的。

+0

如果可能,我真的不想更改文件。我怀疑,像你一样,这是无法完成的(我自己浪费了相当一段时间),但我很想吃惊。谢谢你的建议。 – rmn

+0

@rmn但是,为什么你不能把生成的文件作为一个临时文件来处理?原始txt文件保持不变。 (对不起,如果我没有关注。:) – Virne

+0

Virne是对的,这就是主意。我们在许多地方进行建造时都会这样做。 –

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" 

我敢肯定有一种方式,你可以做到这一点,而无需在文本文件中的报价,但现在没有什么可以想到的。

+0

这是我以前试过的解决方案。它(至少)有两个缺点:1.没有引号就无法工作。 2.它不适用于多行。 非常感谢,如果有人有更好的解决方案,我会非常感激:) – rmn

1

这是微软教程做的: http://support.microsoft.com/kb/816181/en-us

它不解释如何以编程方式或通过预处理使嵌入的文件,但通过在Visual Studio 2005 +菜单。并解释如何从资源部门读取它。

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

+0

Delphi没有预处理器。这是一个单通编译器。你正在考虑编译器指令,它与预处理器无关。 –

1

xxd -i

在这里看到:previous answer

+0

+1,但问题是,如果依靠'xxd'可以安全的话。我用'sed'来达到类似的目的(毕竟它是一个纯文本文件)。 –

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* $* =" > [email protected] 
    @awk '{print "\"" $$0 "\\n\"";}' $^ >> [email protected] 
    @echo ";" >> [email protected] 

该做些什么。
如果您有一个名为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. 
> 
0

您可以使用objcopy把创建一个对象文件出来的源文件,并与实际目标文件链接。它会创建符号_binary_objfile_start, _binary_objfile_end and _binary_objfile_size,您可以将其作为char数组访问。

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''"')避免因逃避东西而引起的烦人。

0

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

我能看到的唯一选择是要求在文本文件的每一行被引用,或产生在编译时临时文件(如其他人所说)。

0

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" 

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; 
} 
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代码和/或define。

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正确的#define,...,如果添加了附加项:

代码:

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

就是这样

铝槽我看不出任何一点奎因(计算)。 多态是另一回事;) 玩得开心。