By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,932 Members | 1,540 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,932 IT Pros & Developers. It's quick & easy.

C++ quine

P: n/a
I was bored, so I just wrote a quine (program that will print out it's own
source code when run) in 100% ansi c++, without using any c-library
functions (such as printf), and not making any assumptions on the character
set.
Any comments? bugs? ideas on how to shorten it?

Emlyn
#include <string>
#include <iostream>
using namespace std;
int main() {
string s = "s", s0 = "\n", s1 = "\"", s2 = "\\", s3 = "n", s4 = ";";
string s5 = " string s", s6 = ", s", s7 = " = ", s8 = s7+s1, s9 = "+";
string s10 = "#include <string>", s11 = "#include <iostream>";
string s12 = "using namespace std;", s13 = "int main() {";
string s14 = " return 0;", s15 = "}";
string s20 = " cout<<s10<<s0<<s11<<s0<<s12<<s0<<s13<<s0;";
string s21 = "
cout<<s5<<s8<<s<<s1<<s6<<0<<s8<<s2<<s3<<s1<<s6<<1< <s8<<s2<<s1<<s1<<s6;";
string s22 = "
cout<<2<<s8<<s2<<s2<<s1<<s6<<3<<s8<<s3<<s1<<s6<<4< <s8<<s4<<s1<<s4<<s0;";
string s23 = "
cout<<s5<<5<<s8<<s5<<s1<<s6<<6<<s8<<s6<<s1<<s6<<7< <s8<<s7<<s1;";
string s24 = "
cout<<s6<<8<<s7<<s<<7<<s9<<s<<1<<s6<<9<<s8<<s9<<s1 <<s4<<s0;";
string s25 = " cout<<s5<<10<<s8<<s10<<s1<<s6<<11<<s8<<s11<<s1<<s4 <<s0;";
string s26 = " cout<<s5<<12<<s8<<s12<<s1<<s6<<13<<s8<<s13<<s1<<s4 <<s0;";
string s27 = " cout<<s5<<14<<s8<<s14<<s1<<s6<<15<<s8<<s15<<s1<<s4 <<s0;";
string s28 = "
cout<<s5<<20<<s8<<s20<<s1<<s4<<s0<<s5<<21<<s8<<s21 <<s1<<s4<<s0<<s5<<22<<s8<<
s22<<s1<<s4<<s0;";
string s29 = "
cout<<s5<<23<<s8<<s23<<s1<<s4<<s0<<s5<<24<<s8<<s24 <<s1<<s4<<s0<<s5<<25<<s8<<
s25<<s1<<s4<<s0;";
string s30 = "
cout<<s5<<26<<s8<<s26<<s1<<s4<<s0<<s5<<27<<s8<<s27 <<s1<<s4<<s0<<s5<<28<<s8<<
s28<<s1<<s4<<s0;";
string s31 = "
cout<<s5<<29<<s8<<s29<<s1<<s4<<s0<<s5<<30<<s8<<s30 <<s1<<s4<<s0<<s5<<31<<s8<<
s31<<s1<<s4<<s0;";
string s32 = "
cout<<s5<<32<<s8<<s32<<s1<<s4<<s0<<s5<<33<<s8<<s33 <<s1<<s4<<s0<<s5<<34<<s8<<
s34<<s1<<s4<<s0;";
string s33 = "
cout<<s5<<35<<s8<<s35<<s1<<s4<<s0<<s5<<36<<s8<<s36 <<s1<<s4<<s0;";
string s34 = "
cout<<s20<<s0<<s21<<s0<<s22<<s0<<s23<<s0<<s24<<s0< <s25<<s0<<s26<<s0<<s27<<s0
<<s28<<s0;";
string s35 = "
cout<<s29<<s0<<s30<<s0<<s31<<s0<<s32<<s0<<s33<<s0< <s34<<s0<<s35<<s0<<s36<<s0
;";
string s36 = " cout<<s14<<s0<<s15<<s0;";
cout<<s10<<s0<<s11<<s0<<s12<<s0<<s13<<s0;
cout<<s5<<s8<<s<<s1<<s6<<0<<s8<<s2<<s3<<s1<<s6<<1< <s8<<s2<<s1<<s1<<s6;
cout<<2<<s8<<s2<<s2<<s1<<s6<<3<<s8<<s3<<s1<<s6<<4< <s8<<s4<<s1<<s4<<s0;
cout<<s5<<5<<s8<<s5<<s1<<s6<<6<<s8<<s6<<s1<<s6<<7< <s8<<s7<<s1;
cout<<s6<<8<<s7<<s<<7<<s9<<s<<1<<s6<<9<<s8<<s9<<s1 <<s4<<s0;
cout<<s5<<10<<s8<<s10<<s1<<s6<<11<<s8<<s11<<s1<<s4 <<s0;
cout<<s5<<12<<s8<<s12<<s1<<s6<<13<<s8<<s13<<s1<<s4 <<s0;
cout<<s5<<14<<s8<<s14<<s1<<s6<<15<<s8<<s15<<s1<<s4 <<s0;

cout<<s5<<20<<s8<<s20<<s1<<s4<<s0<<s5<<21<<s8<<s21 <<s1<<s4<<s0<<s5<<22<<s8<<
s22<<s1<<s4<<s0;

cout<<s5<<23<<s8<<s23<<s1<<s4<<s0<<s5<<24<<s8<<s24 <<s1<<s4<<s0<<s5<<25<<s8<<
s25<<s1<<s4<<s0;

cout<<s5<<26<<s8<<s26<<s1<<s4<<s0<<s5<<27<<s8<<s27 <<s1<<s4<<s0<<s5<<28<<s8<<
s28<<s1<<s4<<s0;

cout<<s5<<29<<s8<<s29<<s1<<s4<<s0<<s5<<30<<s8<<s30 <<s1<<s4<<s0<<s5<<31<<s8<<
s31<<s1<<s4<<s0;

cout<<s5<<32<<s8<<s32<<s1<<s4<<s0<<s5<<33<<s8<<s33 <<s1<<s4<<s0<<s5<<34<<s8<<
s34<<s1<<s4<<s0;
cout<<s5<<35<<s8<<s35<<s1<<s4<<s0<<s5<<36<<s8<<s36 <<s1<<s4<<s0;

cout<<s20<<s0<<s21<<s0<<s22<<s0<<s23<<s0<<s24<<s0< <s25<<s0<<s26<<s0<<s27<<s0
<<s28<<s0;

cout<<s29<<s0<<s30<<s0<<s31<<s0<<s32<<s0<<s33<<s0< <s34<<s0<<s35<<s0<<s36<<s0
;
cout<<s14<<s0<<s15<<s0;
return 0;
}
Jul 19 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Emlyn> I was bored, so I just wrote a quine (program that will print
Emlyn> out it's own source code when run) in 100% ansi c++, without
Emlyn> using any c-library functions (such as printf), and not making
Emlyn> any assumptions on the character set.

Emlyn> Any comments? bugs? ideas on how to shorten it?

Here's a C89 version, written in a form that I find easier to
understand. The interested reader may enjoy translating it to C++:

#include <stdio.h>

char *self[] = {
"#include <stdio.h>",
"",
"char *self[] = {",
"\n",
"\t0",
"};",
"",
"main()",
"{",
"\tchar *p, **s;",
"",
"\tfor (s = self; *s; s++) {",
"\t\tif (**s == '\\n') {",
"\t\t\tchar **t;",
"\t\t\tfor (t = self; *t; t++) {",
"\t\t\t\tputchar ('\\t');",
"\t\t\t\tputchar ('\"');",
"\t\t\t\tfor (p = *t; *p; p++) {",
"\t\t\t\t\tif (*p == '\\t') {",
"\t\t\t\t\t\tputchar ('\\\\');",
"\t\t\t\t\t\tputchar ('t');",
"\t\t\t\t\t} else if (*p == '\"') {",
"\t\t\t\t\t\tputchar ('\\\\');",
"\t\t\t\t\t\tputchar ('\"');",
"\t\t\t\t\t} else if (*p == '\\n') {",
"\t\t\t\t\t\tputchar ('\\\\');",
"\t\t\t\t\t\tputchar ('n');",
"\t\t\t\t\t} else if (*p == '\\\\') {",
"\t\t\t\t\t\tputchar ('\\\\');",
"\t\t\t\t\t\tputchar ('\\\\');",
"\t\t\t\t\t} else",
"\t\t\t\t\t\tputchar (*p);",
"\t\t\t\t}",
"\t\t\t\tputchar ('\"');",
"\t\t\t\tputchar (',');",
"\t\t\t\tputchar ('\\n');",
"\t\t\t}",
"\t\t} else {",
"\t\t\tfor (p = *s; *p; p++) {",
"\t\t\t\tputchar (*p);",
"\t\t\t}",
"\t\t\tputchar ('\\n');",
"\t\t}",
"\t}",
"\treturn 0;",
"}",
0
};

main()
{
char *p, **s;

for (s = self; *s; s++) {
if (**s == '\n') {
char **t;
for (t = self; *t; t++) {
putchar ('\t');
putchar ('"');
for (p = *t; *p; p++) {
if (*p == '\t') {
putchar ('\\');
putchar ('t');
} else if (*p == '"') {
putchar ('\\');
putchar ('"');
} else if (*p == '\n') {
putchar ('\\');
putchar ('n');
} else if (*p == '\\') {
putchar ('\\');
putchar ('\\');
} else
putchar (*p);
}
putchar ('"');
putchar (',');
putchar ('\n');
}
} else {
for (p = *s; *p; p++) {
putchar (*p);
}
putchar ('\n');
}
}
return 0;
}
--
Andrew Koenig, ar*@acm.org
Jul 19 '05 #2

P: n/a
Emlyn Corrin wrote:
I was bored, so I just wrote a quine (program that will print out it's own
source code when run) in 100% ansi c++, without using any c-library
functions (such as printf), and not making any assumptions on the character
set.
Any comments? bugs? ideas on how to shorten it?

Emlyn


Here is my attempt :) I'm fairly certain is this standard C++, I also
suspect it can be made shorter by someone with more C++ knowledge than
me. If this gets eaten by your newsreader, note that I don't have a
multi-line literal :)

The only minor point is that I suspect that I can't do
b.insert(it,'\\'), as this will invalidate it (which suggests to me it
would have been sensible to have insert put things in afterwards *sigh*)
, so I should perhaps make a temporary decremented copy, but I can't be
bothered :) Also I could hard-wire the a.insert line, and the b.reserve
line, but wanted to keep them general for now :)

#include<string>
#include<iostream>
using namespace std;
string a("#include<string>\n#include<iostream>\nusing namespace
std\nstring a(\"X\")int main(){\nstring
b=a;\nb.reserve(b.length()*2);\nstring::iterator
it=b.begin();\nwhile(it!=b.end()) {\nif(*it=='\n') {*it='n';
b.insert(it,'\\\\');}\nit++;\n}\na.insert(find(a.b egin(),a.end(),'X'),b.begin(),b.end());\ncout<<a<< endl;\n}\n");
int main(){
string b=a;
b.reserve(b.length()*2);
string::iterator it=b.begin();
while(it!=b.end()) {
if(*it=='\n') {*it='n'; b.insert(it,'\\');}
it++;
}
a.insert(find(a.begin(),a.end(),'X'),b.begin(),b.e nd());
cout<<a<<endl;
}

Jul 19 '05 #3

P: n/a
I hope the newsreader doesn't mess this up too much. There are no newlines in
the definition of f.

Owner@machine ~/projects/quine
$ cat Quine.cpp
#include <iostream>
#include <string>
template <typename T> char cast (T x) { return static_cast <char> (x); }
void replace (std::string & s, char x, char y) { for (std::string::iterator b =
s.begin (), e = s.end (); b != e; ++ b) if (* b == x) * b = y; }
std::string f ();
int main () {
std::string s (f ());
replace (s, cast (37), cast (10));
std::cout << s << cast (34) << f () << cast (34) << ';' << ' ' << '}' << cast
(10);
}
std::string f () { return "#include <iostream>%#include <string>%template
<typename T> char cast (T x) { return static_cast <char> (x); }%void replace
(std::string & s, char x, char y) { for (std::string::iterator b = s.begin (), e
= s.end (); b != e; ++ b) if (* b == x) * b = y; }%std::string f ();%int main ()
{% std::string s (f ());% replace (s, cast (37), cast (10));% std::cout << s
<< cast (34) << f () << cast (34) << ';' << ' ' << '}' << cast
(10);%}%std::string f () { return "; }

Owner@machine ~/projects/quine
$ g++ -o Quine Quine.cpp

Owner@machine ~/projects/quine
$ ./Quine > Quine2.cpp

Owner@machine ~/projects/quine
$ diff Quine.cpp Quine2.cpp

Owner@machine ~/projects/quine
$
Jul 19 '05 #4

P: n/a
> I was bored, so I just wrote a quine (program that will print out it's own
Man! You must have been really bored!

Radek
Jul 19 '05 #5

P: n/a
Dammit. I didn't notice the "No assumptions on the character set" bit. I'll work
on it.
Jul 19 '05 #6

P: n/a
Andrew Koenig wrote:
Emlyn> I was bored, so I just wrote a quine (program that will print
Emlyn> out it's own source code when run) in 100% ansi c++, without
Emlyn> using any c-library functions (such as printf), and not making
Emlyn> any assumptions on the character set.

Emlyn> Any comments? bugs? ideas on how to shorten it?

Here's a C89 version, written in a form that I find easier to
understand. The interested reader may enjoy translating it to C++:

[SNIP]

It will take another century or so until the Vatican will be able to decide
if these programs are a form of the virgin birth or self abuse. :-)

--
WW aka Attila
Jul 19 '05 #7

P: n/a
Owner@machine ~/projects/quine
$ g++ -o Quine Quine.cpp; ./Quine > Quine2.cpp; diff Quine.cpp Quine2.cpp

Owner@machine ~/projects/quine
$ cat Quine.cpp
#include <iostream>
#include <string>
#include <locale>
using namespace std;

void qprint (string s)
{
const ctype <char> & ct = use_facet <ctype <char> > (locale ());
for (string::iterator i = s.begin (), e = s.end (); i != e; ++ i)
if (ct.is (ctype_base::upper, * i)) switch (ct.tolower (* i))
{
case 'n': cout << endl; break;
case 's': cout << s; break;
case 'q': cout << '\"'; break;
case 'b': cout << '\\'; break;
}
else cout << * i;
}

int main ()
{
qprint ("#include <iostream>N#include <string>N#include <locale>Nusing
namespace std;NNvoid qprint (string s)N{N const ctype <char> & ct = use_facet
<ctype <char> > (locale ());N for (string::iterator i = s.begin (), e = s.end
(); i != e; ++ i)N if (ct.is (ctype_base::upper, * i)) switch (ct.tolower (*
i))N {N case 'n': cout << endl; break;N case 's': cout << s; break;N
case 'q': cout << 'BQ'; break;N case 'b': cout << 'BB'; break;N }N else
cout << * i;N}NNint main ()N{N qprint (QSQ);N}N");
}
Jul 19 '05 #8

P: n/a
<Emlyn Corrin>
I was bored, so I just wrote a quine


Yesterday night I fell asleep on my keyboard. Again! And when I woke up,
nah, I couldn't belief my eyes! Can you? And I also had that email spammer
sending me happy talk about something. I'll add it below, to feed your e-trash.
#define/**/X
char*d="X0[!4cM,!"
"4cK`*!4cJc(!4cHg&!4c$j"
"8f'!&~]9e)!'|:d+!)rAc-!*m*"
":d/!4c(b4e0!1r2e2!/t0e4!-y-c6!"
"+|,c6!)f$b(h*c6!(d'b(i)d5!(b*a'`&c"
")c5!'b+`&b'c)c4!&b-_$c'd*c3!&a.h'd+"
"d1!%a/g'e+e0!%b-g(d.d/!&c*h'd1d-!(d%g)"
"d4d+!*l,d7d)!,h-d;c'!.b0c>d%!A`Dc$![7)35E"
"!'1cA,,!2kE`*!-s@d(!(k(f//g&!)f.e5'f(!+a+)"
"f%2g*!?f5f,!=f-*e/!<d6e1!9e0'f3!6f)-g5!4d*b"
"+e6!0f%k)d7!+~^'c7!)z/d-+!'n%a0(d5!%c1a+/d4"
"!2)c9e2!9b;e1!8b>e/! 7cAd-!5fAe+!7fBe(!"
"8hBd&!:iAd$![7S,Q0!1 bF 7!1b?'_6!1c,8b4"
"!2b*a,*d3!2n4f2!${4 f. '!%y4e5!&f%"
"d-^-d7!4c+b)d9!4c-a 'd :!/i('`&d"
";!+l'a+d<!)l*b(d=!' m- a &d>!&d'"
"`0_&c?!$dAc@!$cBc@!$ b < ^&d$`"
":!$d9_&l++^$!%f3a' n1 _ $ !&"
"f/c(o/_%!(f+c)q*c %! * f &d+"
"f$s&!-n,d)n(!0i- c- k) ! 3d"
"/b0h*!H`7a,![7* i] 5 4 71"
"[=ohr&o*t*q*`*d *v *r ; 02"
"7*~=h./}tcrsth &t : r 9b"
"].,b-725-.t--// #r [ < t8-"
"752793? <.~;b ].t--+r / # 53"
"7-r[/9~X .v90 <6/<.v;-52/={ k goh"
"./}q; u vto hr `.i*$engt$ $ ,b"
";$/ =t ;v; 6 =`it.`;7=` : ,b-"
"725 = / o`. .d ;b]`--[/+ 55/ }o"
"`.d : - ?5 / }o`.' v/i]q - "
"-[; 5 2 =` it . o;53- . "
"v96 <7 / =o : d =o"
"--/i ]q-- [; h. / = "
"i]q--[ ;v 9h ./ < - "
"52={cj u c&` i t . o ; "
"?4=o:d= o-- / i ]q - "
"-[;54={ cj uc& i]q - -"
"[;76=i]q[;6 =vsr u.i / ={"
"=),BihY_gha ,)\0 " , o [
3217];int i, r,w,f , b ,x ,
p;n(){return r <X X X X X
768?d[X(143+ X r++ + *d ) %
768]:r>2659 ? 59: ( x = d
[(r++-768)% X 947 + 768] ) ?
x^(p?6:0):(p = 34 X X X )
;}s(){for(x= n (); ( x^ ( p
?6:0))==32;x= n () ) ;return x ; }
void/**/main X () { r = p
=0;w=sprintf (X X X X X X o
,"char*d="); for ( f=1;f < * d
+143;)if(33-( b=d [ f++ X ] )
){if(b<93){if X(! p ) o
[w++]=34;for X(i = 35 +
(p?0:1);i<b; i++ ) o
[w++]=s();o[ w++ ]
=p?s():34;} else X
{for(i=92; i<b; i
++)o[w++]= 32;} }
else o [w++ ]
=10;o [
w]=0 ;
puts(o);}


Best Layout:

Don Yang
UCSD
259 E. Bellbrook St.
Covina, CA 91722
USA

http://omoikane.cjb.net
Judges' Comments:

To build:

make dhyang

Try:

cc dhyang.c -o saitou
./saitou > aku.c
cat aku.c

cc aku.c -o soku
./soku > soku.c
cat soku.c

cc soku.c -o zan
./zan > zan.c
cat zan.c

cc zan.c -o aku
./aku | diff - aku.c

A beautiful combination of solving several different problems, but
mostly, the single most impressive layout we've ever seen. Many
programs have *one* interesting layout; this one has four.

It may be informative to run the code through a "beautifier", to
study it, but the layout itself is where most of the interest lies.
Selected Author's Comments:

This one is dedicated to Saitou Hajime fans ^_^x

Instead of making one self reproducing program, what I made was a
program that generates a set of mutually reproducing programs, all of
them with cool layout!

For your enjoyment:
1. Compile saitou.c
2. Run a.out and pipe output to another .c file
3. Compile that file
4. Repeat steps 2 and 3 until eventually the output cycles

To interpret the output: the saitou.c is an image of Saitou Hajime,
which eventually generates three sources files that are images of
"aku soku zan" (sin swift slay), Saitou's motto ;)

For best viewing, set tab spaces to 8 characters, and set your
terminal fonts to as close to square as possible. I hate to do this
but you know, size...

saitou.c and all its output compiles with gcc if your OS uses ASCII
character set. No file is included and all functions assume default
int return type (a source of compile warnings)

Jul 19 '05 #9

P: n/a
OK, using locales was silly. Here's my final answer:

Owner@machine ~/projects/quine
$ g++ -o Quine Quine.cpp; ./Quine > Quine2.cpp; diff Quine.cpp Quine2.cpp

Owner@machine ~/projects/quine
$ ./Quine
#include <iostream>
#include <ostream>
#include <string>
using namespace std;

void quine (string s)
{
for (string::iterator b = s.begin (), e = s.end (); b != e; ++ b)
if (* b == '%') switch (* ++ b)
{
case 's': cout << s; break;
case '%': cout << '%'; break;
case 'n': cout << '\n'; break;
case 'q': cout << '\"'; break;
case 'b': cout << '\\'; break;
}
else cout << * b;
}

int main ()
{
quine ("#include <iostream>%n#include <ostream>%n#include <string>%nusing
namespace std;%n%nvoid quine (string s)%n{%n for (string::iterator b = s.begin
(), e = s.end (); b != e; ++ b)%n if (* b == '%%') switch (* ++ b)%n {%n
case 's': cout << s; break;%n case '%%': cout << '%%'; break;%n case
'n': cout << '%bn'; break;%n case 'q': cout << '%b%q'; break;%n case
'b': cout << '%b%b'; break;%n }%n else cout << * b;%n}%n%nint main ()%n{%n
quine (%q%s%q);%n}%n");
}
Jul 19 '05 #10

P: n/a
OK, how about this, it should be a bit more readable:

#include <string>
#include <iostream>
using namespace std;

string escape(const string & s) {
string ret(s);
string::size_type i = 0;
while ((i = ret.find_first_of("\\\"", i)) < ret.length()) {
ret.insert(i, "\\");
i += 2;
}
return ret;
}

int main() {
static const string self[] = {
"#include <string>",
"#include <iostream>",
"using namespace std;",
"",
"string escape(const string & s) {",
" string ret(s);",
" string::size_type i = 0;",
" while ((i = ret.find_first_of(\"\\\\\\\"\", i)) < ret.length()) {",
" ret.insert(i, \"\\\\\");",
" i += 2;",
" }",
" return ret;",
"}",
"",
"int main() {",
" static const string self[] = {",
" };",
" for (int i = 0; i < (sizeof self / sizeof *self); ++i) {",
" cout << self[i] << endl;",
" if (i == 15) {",
" for (int j = 0; j < (sizeof self / sizeof *self); ++j) {",
" cout << \" \\\"\" << escape(self[j]) << \"\\\",\" << endl;",
" }",
" }",
" }",
" return 0;",
"}",
};
for (int i = 0; i < (sizeof self / sizeof *self); ++i) {
cout << self[i] << endl;
if (i == 15) {
for (int j = 0; j < (sizeof self / sizeof *self); ++j) {
cout << " \"" << escape(self[j]) << "\"," << endl;
}
}
}
return 0;
}
Jul 19 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.