0

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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
rmn
  • 2,386
  • 1
  • 14
  • 21
  • This is a duplicate somewhere. – Daniel A. White Sep 14 '09 at 18:58
  • Can you run some external script or executable before compiling, that generates one .h file from given txt file? – Virne Sep 14 '09 at 19:13
  • @Virne, a txt isn't different from an .h file in anything. The thing is I would not want to make any changes to the file im including.. – rmn Sep 14 '09 at 19:15
  • It used to do that in Delphi Preprocessor, it is something like embedding it to the resources (the same way you do it with Icons and Dialogs), I just don't know how to do the same with C++. – Havenard Sep 14 '09 at 19:19
  • 1
    I mean that I would just load the text and convert it to includable C-string during build using script or something. It would output something like: static const char* text = "\none\n\two" – Virne Sep 14 '09 at 19:22
  • Duplicates: http://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char http://stackoverflow.com/questions/1155578/which-program-creates-a-c-array-given-any-file – CB Bailey Sep 14 '09 at 20:58
  • What ide/compiler are you using? – Alan Sep 21 '09 at 21:29
  • I would like a portable solution, if there's any. I'm using either vs 2008 or gnu g++ – rmn Sep 22 '09 at 20:39
  • Wait... you're trying to write a quine by... asking StackOverflow how to write a quine? Perhaps you deserve points for the meta-quine of asking a question that produces a quine as its answer... – Daniel Pryden Sep 23 '09 at 08:43
  • I don't think your program would technically be a quine, since it consists of two strings (the program and itself as a char array) but outputs only one of them. – Ozan Sep 25 '09 at 01:33

12 Answers12

2

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.

Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
  • I really would not want to change the file, if possible. I suspect, like you, that it can't be done (I've wasted quite some time on this myself), but i'd love to be surprised.. Thanks for the suggestion. – rmn Sep 14 '09 at 19:20
  • @rmn But why can't you treat generated file as a temporary file required just for build? Original txt-file stays intact. (Sorry if I am not following. :) – Virne Sep 14 '09 at 19:29
  • Virne is right, that's the idea. We do this during our build in a number of places. – Graeme Perrow Sep 14 '09 at 19:33
  • OK, if you can explain why it's not suitable, we might be able to come up with something. – Graeme Perrow Sep 14 '09 at 20:00
  • 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) . I'd still love to get an answer, though :) – rmn Sep 15 '09 at 17:56
1

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.

Havenard
  • 27,022
  • 5
  • 36
  • 62
  • Delphi doesn't have a preprocessor. It's a single pass compiler. You're thinking of compiler directives, which have nothing to do with a preprocessor. – Ken White Sep 15 '09 at 18:06
1

xxd -i

See here: previous answer

Community
  • 1
  • 1
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
0

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.

Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
  • That's a solution i've tried before. It has (at least) two downsides: 1. it will not work without the quotes. 2. it will not work with multiple lines. Thanks alot, and I'd really appreciate it if anybody has a better solution :) – rmn Sep 14 '09 at 19:08
0

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.
> 
Martin York
  • 257,169
  • 86
  • 333
  • 562
0

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.

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
0

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.

Ozan
  • 4,345
  • 2
  • 23
  • 35
0

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.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
0

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

Martin
  • 3,703
  • 2
  • 21
  • 43
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;
}
ezpz
  • 11,767
  • 6
  • 38
  • 39
0

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.

Ralph
  • 5,154
  • 1
  • 21
  • 19
0
  • 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.

SoLaR
  • 778
  • 7
  • 22