Live data from Hacker News

A Regular Expression Matcher (2007)

cs.princeton.edu

21–30 of 36 posts

Re: A Regular Expression Matcher (2007)

#21
post #6

Earlier quoted context omitted.

> (It's also a good example of how pointer-arithmetic and nul-terminated strings should be used, but the less said about that, the better). Why the less said the better? I'm always disappointed when people say C is bad at string manipulation. The "character at a time, no allocations needed, stop when you hit the end" style demonstrated here and elsewhere have always resonated deeply with me.

> I'm always disappointed when people say C is bad at string manipulation. The "character at a time, no allocations needed, stop when you hit the end" style demonstrated here and elsewhere have always resonated deeply with me. The main reason is that C doesn't really offer many primitives for string manipulation beyond pointer manipulation. All you really get is the stuff in `string.h`, which isn't much, and most of…

strncat() is not like strncpy() - it always nul-terminates the result.

I think your strlen() issue is a bit overblown. Either you get the string from a function that explicitly produces valid strings, in which case you know that it's a valid string already; or you get it from a raw bunch of bytes which tends to come with a size attached, giving you all the information you need to either check if it's a valid string or append a nul-terminator yourself.

Re: A Regular Expression Matcher (2007)

#22

Earlier quoted context omitted.

Roghly speaking, I don't want to start a flame war by defending pointer-arith. The haters are right that languages could use other, safer features (like array slicing). But if it is how your language does things, then use it, and use it well -- as in this example. Also I find counted strings preferable for most tasks, but nul-terminated have the advantage of working so nicely with the ptr++ operation. There was real…

> Also I find counted strings preferable for most tasks, but nul-terminated have the advantage of working so nicely with the ptr++ operation. Is this: while (foo != '\0') { *bar++ = *foo++; } really that much nicer than this: while (i != len) { bar[i++] = foo[i++]; } ? Or even this: for (; i != len; i++) { bar[i] = foo[i]; } ? Don't do this, though: while (i != len) { bar[i] = foo[i++]; } (that's the road to undefine…

"Is this: while (foo != '\0') { bar++ = foo++; } really that much nicer than this: while (i != len) { bar[i++] = foo[i++]; }"

Not visually, but the latter increments i twice in every loop :-). It also typically uses an extra register and requires an explicit 'compare with zero'. Both mattered more 40+ years ago.

Re: A Regular Expression Matcher (2007)

#23
post #6

Earlier quoted context omitted.

> (It's also a good example of how pointer-arithmetic and nul-terminated strings should be used, but the less said about that, the better). Why the less said the better? I'm always disappointed when people say C is bad at string manipulation. The "character at a time, no allocations needed, stop when you hit the end" style demonstrated here and elsewhere have always resonated deeply with me.

> I'm always disappointed when people say C is bad at string manipulation. The "character at a time, no allocations needed, stop when you hit the end" style demonstrated here and elsewhere have always resonated deeply with me. The main reason is that C doesn't really offer many primitives for string manipulation beyond pointer manipulation. All you really get is the stuff in `string.h`, which isn't much, and most of…

The issue of strtok() being horrible hack is easily overcame by using str(c)spn() (and optionally bunch of pointer arithmetic).

Re: A Regular Expression Matcher (2007)

#24
post #12
post #5

I found I didn't hate, loathe and detest unbraced blocks any less when it's Rob Pike code if(x) { do_y();} 2 characters, no vertical space difference. Unbraced blocks only feature is they introduce bugs - they have no legitimate use. But man do you feel like a tough, macho- man "I'm such a hard man I leave my blocks un-braced." Is there a list of languages that repeated this C idiocy (an optimization of syntax for th…

I keep one-line blocks unbraced when possible and my reasoning is definitely not to feel like a tough macho man. It's more like a mild form of OCD where any syntax that's not necessary just bothers me if I don't omit it.

I'm with you on that.

The one line version isn't prone to goto fail, and to me reads very nicely.

    if (x == 1) return;
The two line version, however, I avoid like the plague.

    if (x == 1)
        return;

Re: A Regular Expression Matcher (2007)

#25
post #22

Earlier quoted context omitted.

> Also I find counted strings preferable for most tasks, but nul-terminated have the advantage of working so nicely with the ptr++ operation. Is this: while (foo != '\0') { *bar++ = *foo++; } really that much nicer than this: while (i != len) { bar[i++] = foo[i++]; } ? Or even this: for (; i != len; i++) { bar[i] = foo[i]; } ? Don't do this, though: while (i != len) { bar[i] = foo[i++]; } (that's the road to undefine…

"Is this: while (foo != '\0') { bar++ = foo++; } really that much nicer than this: while (i != len) { bar[i++] = foo[i++]; }" Not visually, but the latter increments i twice in every loop :-). It also typically uses an extra register and requires an explicit 'compare with zero'. Both mattered more 40+ years ago.

> the latter increments i twice in every loop :-).

D'oh! Good catch. That's what I get for coding without testing at 3am... Just realized `foo != '\0'` should be `* foo != '\0'`, too. Derp.

> It also typically uses an extra register and requires an explicit 'compare with zero'.

Okay, I see the extra register, but I'm lost on any extra comparisons versus the pointer-arithmetic version. The pointer version still has to test for the nul character anyway, right?

> Both mattered more 40+ years ago.

Indeed, but I'm talking about today. We can now afford the safety that comes with using explicit lengths rather than sentinels. (I'm inclined to think Dennis Ritchie could've afforded it, too, considering that Pascal (among others) was using explicit lengths for strings (and indeed all arrays) around the same time C was invented, and did so on similar hardware to boot. Bounds checking is pretty damn cheap, all things considered, even on a PDP-11 (the PDP-10, while not exactly a predecessor to the PDP-11, ran TeX written in WEB / Pascal, and was favored by some Lisp hackers as practically a Lisp machine (in fact, Lisp was the first thing DEC brought up on the PDP-10, or so I'm told...), so I think it could afford bounds checking, at least).

Re: A Regular Expression Matcher (2007)

#26
post #21

Earlier quoted context omitted.

> I'm always disappointed when people say C is bad at string manipulation. The "character at a time, no allocations needed, stop when you hit the end" style demonstrated here and elsewhere have always resonated deeply with me. The main reason is that C doesn't really offer many primitives for string manipulation beyond pointer manipulation. All you really get is the stuff in `string.h`, which isn't much, and most of…

strncat() is not like strncpy() - it always nul-terminates the result. I think your strlen() issue is a bit overblown. Either you get the string from a function that explicitly produces valid strings, in which case you know that it's a valid string already; or you get it from a raw bunch of bytes which tends to come with a size attached, giving you all the information you need to either check if it's a valid string o…

> strncat() is not like strncpy() - it always nul-terminates the result.

Yes, you're right. That's what I get for trying to speed-read the C standard at 3am...

> I think your strlen() issue is a bit overblown. Either you get the string from a function that explicitly produces valid strings, in which case you know that it's a valid string already; or you get it from a raw bunch of bytes which tends to come with a size attached, giving you all the information you need to either check if it's a valid string or append a nul-terminator yourself.

Usually, yes, but neither of those things are guaranteed, unfortunately, and thus we wind up with the perennial buffer overflow exploit.

Re: A Regular Expression Matcher (2007)

#27
post #23

Earlier quoted context omitted.

> I'm always disappointed when people say C is bad at string manipulation. The "character at a time, no allocations needed, stop when you hit the end" style demonstrated here and elsewhere have always resonated deeply with me. The main reason is that C doesn't really offer many primitives for string manipulation beyond pointer manipulation. All you really get is the stuff in `string.h`, which isn't much, and most of…

The issue of strtok() being horrible hack is easily overcame by using str(c)spn() (and optionally bunch of pointer arithmetic).

Of course. All of the issues with C's string library can be overcome rather easily, if only because it's so very basic.

Re: A Regular Expression Matcher (2007)

#29
post #5

I found I didn't hate, loathe and detest unbraced blocks any less when it's Rob Pike code if(x) { do_y();} 2 characters, no vertical space difference. Unbraced blocks only feature is they introduce bugs - they have no legitimate use. But man do you feel like a tough, macho- man "I'm such a hard man I leave my blocks un-braced." Is there a list of languages that repeated this C idiocy (an optimization of syntax for th…

Syntactic noise matters. You don't notice how much it costs until you're used to a lots-of-small-functions style in a language where that's possible.

I prefer consistency in the opposite direction, like I have in Scala: all constructs can be written as expressions. Function body? Expression. Try/catch body? Expression. Loop body? Expression. If you want to put a bunch of statements in rather than an expression, then you put them in braces. (But most of the time there's a better way to express what you wanted).

Post reply on HN