I came across this tricky question a few weeks ago.
Write a small C program, which while compiling takes another program from input terminal, and on running gives the result for the second program. (NOTE: The key is, think UNIX).
At first, it looked like a strange puzzle. How can a C code force the compiler to request for input while it is already compiling the code? After a little thinking, the solution became obvious. I assumed that the compiler is allowed to accept the input during the preprocessing step.
The preprocessor allows us to direct the compiler to include another
file with the #include directive. So, why not use it to
read the standard input?
So, the solution has only one line of code: #include
"/dev/stdin". On Windows machine, CON represents the
standard input, so: #include "CON"
andromeda:/home/susam# cat reader.c
#include "/dev/stdin"
andromeda:/home/susam# gcc -o reader reader.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("hello, world\n");
return 0;
}
andromeda:/home/susam# ./reader
hello, world



11 comments:
Vallabha said:
Very simple and very neat solution. Yet another complex puzzle with a simple solution. :)
MS Vivek Chaitanya said:
Wow!
Sharath said:
Thanks. It was bugging my head for long.
Shaffu said:
Hi. I am not able to terminate the program compilation, when does it stop taking the input and when will the executable ./reader will be created? I am trying it in my Red Hat Linux machine?
Susam Pal said:
Shaffu,
You need to press Ctrl + D to indicate termination of input stream. Note that you need to press Ctrl + D while you are on a blank line. So, you would press Enter first to move to the next blank line and then press Ctrl + D.
Once you end the input stream by pressing Ctrl + D, gcc would compile the code and create the executable.
Shaffu said:
Thanks Susam. It's working!
Hunter said:
Compile-time generated C source code. This is scary :D
Jay Garcia said:
That is damn cool!
Sam said:
I am not sure how closely it fits the overall idea behind this puzzle, but you can also use a [bash] here-file to accomplish this.
sam@box$ ls sam@box$ gcc -x c - << EOF > #include <stdio.h> > int main(int argc, char *argv[]) { > printf("Hi planet!\n"); > return 0; > } > EOF sam@box$ ls a.out sam@box$ ./a.out Hi planet! sam@box$Razee Marikar said:
Hey, this is spinellis' entry for the IOCCC, submitted on 1988. See http://www.ioccc.org/years-spoiler.html, search for spinellis. It's under 1988.
Susam Pal said:
Razee,
Thank you for the URL. It indeed seems like a very old puzzle. I came across it for the first time in an internal blog at my workplace.