Reputation: 2426
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.
Upvotes: 0
Views: 2849
Reputation: 886
Code:
IDR_FILE_DIRECTORYINFO_H CPPCODE "DirectoryInfo.h"
IDR_FILE_DIRECTORYINFO_CPP CPPCODE "DirectoryInfo.cpp"
Code:
#define IDR_FILE_DIRECTORYINFO_H 312
#define IDR_FILE_DIRECTORYINFO_CPP 313
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.
Upvotes: 0
Reputation: 5232
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.
Upvotes: 0
Reputation: 12047
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;
}
Upvotes: 0
Reputation: 3753
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).
Upvotes: 0
Reputation: 400434
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.
Upvotes: 0
Reputation: 4415
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.
Upvotes: 0
Reputation: 143169
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
. I then referred to it as extern const char *COPYING
, but one can #include
it as well.
Upvotes: 0
Reputation: 264531
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.
>
Upvotes: 0
Reputation: 27894
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.
Upvotes: 1
Reputation: 57258
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.
Upvotes: 2
Reputation: 57258
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.
Upvotes: 0