ITT: make your best, most elegant implementation of cat(1) in C. Doesn't have to be POSIX compliant; for example, mine takes no option arguments because that's how I think it should be, whereas I think that POSIX specifies a few options.
#include <stdio.h>
int main(int argc, char **argv) {
char b[4096];
FILE *f = stdin;
int i;
size_t s;
if (argc == 1)
goto noargs;
for (i = 1; i < argc; i++) {
f = fopen(argv[i], "rb");
if (!f) {
fprintf(stderr, "%s: failed to open %s\n", argv[0], argv[i]);
continue;
}
noargs:
while ((s = fread(b, 1, 4096, f)))
fwrite(b, 1, s, stdout);
}
return 0;
}
Why is this the best in my opinion? It is short, simple, fast, serves just the purpose of concatenating files and no more, and even has a clever and elegant trick to handle the special case of no arguments without code duplication.
Mine isn't really POSIX compliant either, but it correctly returns something other than EXIT_SUCCESS when it fails to concatenate the files, so I feel it's still adequate.
Name:
Anonymous2012-02-16 3:47
>>2
Well, I could argue that while yours is adequate, mine is superior because yours has a provably 100% failure rate, while my failure rate is <= 100% depending on external factors.
This is perfect example of why declaring functions within functions with lexical scoping for the variables is a good language feature.
Name:
Anonymous2012-02-16 3:48
>>4
I don't see how this is an example of the necessity of nested functions with lexical scoping. Please elaborate.
Name:
Anonymous2012-02-16 4:05
>>5
I can't do it using standard C, but:
while ((s = fread(b, 1, 4096, f)))
fwrite(b, 1, s, stdout);
could be wrapped in a function, and then this function can be called from within the loop, and instead of using a goto to jump into the middle of the loop, you can just call the function.
Or is that correct? When you jump into the middle of the loop there, you expect the loop to terminate right? IE, the catting code is only run once? I don't think i is necessarily initialized when the comparison, i < argc is made.
Name:
Anonymous2012-02-16 4:22
>>6
Thanks for the catch; I can probably move the initialisation of i to the declaration, and leave the first 'trimester' of the for statement empty, so that i is always initialised. I suppose a function could be used, though in a program as trivial as this, there isn't any benefit that I can see.
Name:
Anonymous2012-02-16 4:25
>>6
Why should C need nested lexical scoping when the function could just be passed the FILE* as an argument? Using scoping captures instead of function arguments introduces the same problems as using global variables. void writeout(FILE *f) {
char b[4096];
size_t s;
while ((s = fread(b, 1, 4096, f)))
fwrite(b, 1, s, stdout);
}
>>16
Can you enumerate the possible inputs it doesn't fail on?
Name:
Anonymous2012-02-24 4:33
>>7
The program may be small, but even in small programs code duplication can come up, and factoring the duplicated code in a function and then calling it from each duplication point would be the safest way to factor it. And variable initialization is very explicit in function calls. Using gotos to jump into the middle of loops creates many implicit situations amongst the local variables, and very quickly, the only method for finding out is happening becomes manually tracing through it. When this happens, it means the concept of the program is destroyed, and all that remains is code to compute. The only way to recover the conceptual methods employed in the program is to become the computer and then realize what you are doing.
Name:
cat.hs2012-02-24 5:59
main = do
args <- getArgs
map (\x -> readFile x >>= putStr) args
. . . Did someone say elegant?
Name:
Anonymous2012-02-24 6:24
You can always just use redirects ...
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
>>20
Except that's neither elegant, nor efficient.
Name:
Anonymous2012-02-24 7:34
>>23
It achieves cat function in very little code. I suppose if you wanted to include the error message, it'll be a bit longer. I'm not sure how one could achieve a denser solution than in any other practical language.
>>20 haskell
elegant (Show a, Show b, Show c) => Show (a, b, c)
(Show a, Show b, Show c, Show d) => Show (a, b, c, d)
(Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e)
(Show a, Show b, Show c, Show d, Show e, Show f) => Show (a, b, c, d, e, f)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g) => Show (a, b, c, d, e, f, g)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h) => Show (a, b, c, d, e, f, g, h)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i) => Show (a, b, c, d, e, f, g, h, i)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j) => Show (a, b, c, d, e, f, g, h, i, j)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k) => Show (a, b, c, d, e, f, g, h, i, j, k)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l) => Show (a, b, c, d, e, f, g, h, i, j, k, l)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n)
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n, Show o) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
>>29
You think with all the academics pouting over haskell night and day that it's just some silly implementation problem that can be fixed in a new version? It's a design issue that clashes with the entire foundation of the language -- short of significant theoretical advances it won't ever be fixed.
Exactly. However, as the problem is framed, one can never hope to expect a rational number being output from such a generator in practice, albeit every number (even rational ones) have the same probability to occur. Despite, the practicality of an experiment of this sort is indeed rather dubious.
Name:
Anonymous2012-02-24 15:25
>>36,37
It never happens, the probability is exactly zero.
This has to do with the cardinality of the rational numbers versus the cardinality of the irrational numbers.
Try doing the (lebesgue) integral of the probability distribution over any real interval that extends over more than a single real number.
Name:
Anonymous2012-02-24 15:30
>>38 the probability is exactly zero.
Read the definition of the term in >>36. Its probability is zero, but it CAN happen, the same way P(x = sqrt(2)) = 0 but it obviously can occur.