Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

cat.c

Name: Anonymous 2012-02-16 3:42

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.

Name: Anonymous 2012-02-16 3:46

int main(void)
{
    return 1;
}


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: Anonymous 2012-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.

Name: Anonymous 2012-02-16 3:48

>>1

This is perfect example of why declaring functions within functions with lexical scoping for the variables is a good language feature.

Name: Anonymous 2012-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: Anonymous 2012-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: Anonymous 2012-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: Anonymous 2012-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);
}

Name: Anonymous 2012-02-16 4:35

>>3
Your failure rate is also 100%, since there are infinity possible inputs it fails on.

Name: Anonymous 2012-02-16 4:42

>>9
There are also infinity possible inputs it doesn't fail on.

Name: Anonymous 2012-02-16 6:21

>>10
Pick a real number. What's the probability that it's rational?

Name: Anonymous 2012-02-16 6:43

>>11
what does it mean to "pick a real number"?

Name: Anonymous 2012-02-16 6:46


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    const char *s = argv[0];

    if (!(s && *s))
        return EXIT_FAILURE;

    while (++s) {
        FILE *f;
        if (!(f = fopen(s, "r")))
            return EXIT_FAILURE;
        {
            int c;
            while ((c = fgetc(f)) != EOF)
                putchar(c);
        }
        fclose(f);
    }

    return EXIT_SUCCESS;
}

untested

Name: Anonymous 2012-02-16 7:54

>>11
What's the mantissa for that number?

Name: Anonymous 2012-02-16 9:42

Name: Anonymous 2012-02-16 16:05

>>10
That's not actually true.

Name: Anonymous 2012-02-16 16:10

#include <stdio.h>
#include <string.h>

int main (int argc, char **argv) {
    int i;
    char files=0, c;
    FILE *f;
    for (i=1; i<argc; i++) {
        if (strcmp(argv[i], "-u")) {
            files=1;
            if(!(f=fopen(argv[i], "r"))) return 1;
            while((c=getc(f)) != EOF) putchar(c);
            fclose(f);
        }
    }
    if (!files) while ((c=getchar()) != EOF) putchar(c);
    return 0;
}

Name: Anonymous 2012-02-16 16:33

>>16
Can you enumerate the possible inputs it doesn't fail on?

Name: Anonymous 2012-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.hs 2012-02-24 5:59

main = do
    args <- getArgs
    map (\x -> readFile x >>= putStr) args


. . . Did someone say elegant?

Name: Anonymous 2012-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;
}

Name: Anonymous 2012-02-24 6:29

dubs.c
return 'em;

Name: Anonymous 2012-02-24 7:27

>>20
Except that's neither elegant, nor efficient.

Name: Anonymous 2012-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.

Name: Anonymous 2012-02-24 7:43

>>24
Elegant =/= dense.

Name: Anonymous 2012-02-24 8:05

>>21
One function call per byte is [b][i]SLOW AS FUCK[/i][/b]

Name: Anonymous 2012-02-24 8:25

>>26
EXPERT BBCODE PROGRAMMER

Name: Anonymous 2012-02-24 10:58

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

Name: Anonymous 2012-02-24 11:06

>>28
Yeah, they could've had better semantics for tuples at the type/kind level. Maybe a future version will clean up that rust spot.

Nobody actually uses big tuples anyway, because records are just better even if they're still shit.

Name: Anonymous 2012-02-24 11:11

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

Name: Anonymous 2012-02-24 11:12

>>29
You have no idea how programming languages work you no talent bitch.

Name: Anonymous 2012-02-24 11:16

>>11
The probability of the number being rational is 0.

Name: Anonymous 2012-02-24 11:18

>>30
No academics care about Haskell, only retarded children do.

Name: Anonymous 2012-02-24 11:37

>>32
And yet it happens...

Name: Anonymous 2012-02-24 12:08

>>34

It doesn't. (Think again.)

Name: Anonymous 2012-02-24 12:25

>>35
As we would say in statistics, the event "number is rational" happens almost never.

Name: Anonymous 2012-02-24 12:44

>>36

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: Anonymous 2012-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: Anonymous 2012-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.

Name: Anonymous 2012-02-24 15:34

This is pathetic.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List