Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Efficency and the standard library

56 views
Skip to first unread message

Seebs

unread,
Feb 10, 2010, 2:25:54 PM2/10/10
to
This may have gotten buried given that it started in a Nilges thread,
but it's actually pretty interesting.

There was some discussion of algorithms to perform the task:
Inputs: target string, replacement string, original string
Output: a newly-allocated string containing the original
string with each copy of the target string replaced with the
replacement string.

Here's a hunk of mine:

for (count = 0, t = strstr(target, in); t && *t; t = strstr(t, in)) {
++count;
t += inlen;
}

Here's a hunk of another one:

> ptrIndex1 = strMaster;
> while(*ptrIndex1)
> {
> ptrIndex0 = ptrIndex1;
> while (-1)
> {
> for(;
> *ptrIndex1 && *ptrIndex1 != *strTarget;
> ptrIndex1++);
> for(ptrIndex2 = strTarget, ptrIndex3 = ptrIndex1;
> *ptrIndex3
> &&
> *ptrIndex2
> &&
> *ptrIndex3 == *ptrIndex2;
> ptrIndex3++, ptrIndex2++);
> if (!*ptrIndex2) break;
> ptrIndex1 = ptrIndex3;
> if (!*ptrIndex3) break;
> }

These hunks are essentially performing the same part of the core loop;
find the next occurrence of the target string in the original string.

The second one was written by Edward Nilges ("spinoza1111"). He offers
in its defense the assertion that it's the "best" algorithm. (Nevermind
that it's got a bug; the bug could be fixed easily.)

My thinking:

The first is better, not because it's less buggy (that could be fixed), but
because it's simpler to understand. It may, or may not, be less efficient.
However, efficiency will vary widely with input characteristics; for some
cases, the arguable inefficiencies may be completely irrelevant, while in
others, they'd be significant.

But you should always write the simpler one first, and wait until you've
profiled the code and verified that there's a bottleneck, and you know where
it is, before trying to optimize. You may, or may not, be able to outperform
a given library's implementation of strstr(). If you have unusual inputs,
you have a pretty good shot at it... But it may not be worth it. The
complicated example has had at least one bug identified, and there may be
others. It's extremely hard to read, partially because of the poor
naming, and partially because of the counter-idiomatic usage. But mostly,
it's a lot more work to write and maintain, and for no known benefit.

It's good to think a little about efficiency, but write for clarity and
correctness first, so you have a known-working program to check your
results if you later need to modify it for speed.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Moi

unread,
Feb 10, 2010, 3:16:05 PM2/10/10
to
On Wed, 10 Feb 2010 19:25:54 +0000, Seebs wrote:

> This may have gotten buried given that it started in a Nilges thread,
> but it's actually pretty interesting.
>
> There was some discussion of algorithms to perform the task:
> Inputs: target string, replacement string, original string Output: a
> newly-allocated string containing the original
> string with each copy of the target string replaced with the
> replacement string.
>
> Here's a hunk of mine:
>
> for (count = 0, t = strstr(target, in); t && *t; t = strstr(t,
> in)) {
> ++count;
> t += inlen;
> }
>

Of course yours is more readable.
Personally, I prefer not to use one letter variable names (three letter names are
more grepable, also for the eyes). Also I dont like for(;;) statements that are too wide
(and with repeating subexpressions). But it's all a matter of taste, of course.

I'd prefer:


for (count = 0, tmp=target; tmp = strstr(tmp, in); ) {
if ( !*tmp) break;
count++;
tmp += inlen;
...
}


My own strstr() loop:

nhit = 0;
for (tail = haystack; src = strstr(tail, needle); tail = src + needle_len) {
nhit++;
...
}

, which uses one variable too many, but that will be used later on.

AvK

Dann Corbit

unread,
Feb 10, 2010, 3:54:41 PM2/10/10
to
In article <slrnhn628c.o3u...@guild.seebs.net>, usenet-
nos...@seebs.net says...

For a standard library, the *most* important thing is correctness. IOW,
a bsearch() function that is blazing fast but fails if there are more
than 2 billion items is not as good as one that is only half as fast but
works with anything up to size_t (-1) number of elements.

Assuming correctness, then effeciency should be the next decider. An
interesting project would be to take a collection of all public C
libraries and do the following:
1. Exhaustively test for correctness
2. Analyze for efficiency
3. Choose best of breed from the above analysis. It could also be a
hybrid (e.g. a decider function chooses the best algorithm based on
conditions).

Here is a list of some compilers (most of these come with source code)
that could be used as a starting point:

Directory of c:\compiler
06/03/2009 11:38 AM <DIR> bscc
01/21/2010 04:16 PM <DIR> clang-2.6
01/21/2010 04:35 PM <DIR> commoncpp2-1.7.3
01/13/2010 01:13 PM <DIR> coreutils-8.4
10/16/2009 05:39 PM <DIR> ctool_2.12
10/16/2009 12:39 PM <DIR> fog
06/04/2009 11:52 AM <DIR> g95-0.92
06/04/2009 11:58 AM <DIR> gcc-4.4.0
10/16/2009 05:58 PM <DIR> gcc-4.4.2
01/21/2010 04:39 PM <DIR> gcc-4.4.3
10/16/2009 05:59 PM <DIR> ladsoft
10/16/2009 05:59 PM <DIR> lcc
10/16/2009 06:00 PM <DIR> llvm
01/21/2010 04:18 PM <DIR> llvm-2.6
01/21/2010 04:19 PM <DIR> llvm-gcc4.2-2.6.source
11/30/2008 08:00 AM <DIR> open64-4.2.1-0
10/16/2009 06:06 PM <DIR> OW18src
01/21/2010 04:18 PM <DIR> owdaily
06/04/2009 11:38 AM <DIR> tendra
01/21/2010 04:35 PM <DIR> ucommon-2.0.8
06/03/2009 02:49 PM <DIR> vmkit-0.25
06/03/2009 12:24 PM <DIR> watcom
01/21/2010 04:00 PM <DIR> x86_open64-4.2.3


Ben Pfaff

unread,
Feb 10, 2010, 4:12:16 PM2/10/10
to
Dann Corbit <dco...@connx.com> writes:

> For a standard library, the *most* important thing is correctness. IOW,
> a bsearch() function that is blazing fast but fails if there are more
> than 2 billion items is not as good as one that is only half as fast but
> works with anything up to size_t (-1) number of elements.

If the former bsearch() implementation is on a system that
doesn't support more than 2 billion bytes of contiguous data, I'm
not worried about it.
--
"The expression isn't unclear *at all* and only an expert could actually
have doubts about it"
--Dan Pop

Phred Phungus

unread,
Feb 10, 2010, 7:29:52 PM2/10/10
to
Ben Pfaff wrote:
> Dann Corbit <dco...@connx.com> writes:
>
>> For a standard library, the *most* important thing is correctness. IOW,
>> a bsearch() function that is blazing fast but fails if there are more
>> than 2 billion items is not as good as one that is only half as fast but
>> works with anything up to size_t (-1) number of elements.
>
> If the former bsearch() implementation is on a system that
> doesn't support more than 2 billion bytes of contiguous data, I'm
> not worried about it.

Why?
--

Ben Pfaff

unread,
Feb 10, 2010, 7:37:13 PM2/10/10
to
Phred Phungus <Ph...@example.invalid> writes:

Because the bsearch() function cannot exceed a limit of 2 billion
items on an implementation that limits objects to 2 billion bytes
or less.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}

Ben Bacarisse

unread,
Feb 10, 2010, 8:05:27 PM2/10/10
to
Seebs <usenet...@seebs.net> writes:

I don't think you can dismiss the bugs so easily. I would argue that
it is not a coincidence that the more complex code has more bugs. I
can't write code that looks like spinoza1111's code and get it right.
I *have* to write simpler code, broken into simple functions, or I have
no chance of getting it to be correct.

For example, the latest improvement introduced another bug[1] and I
don't think that is simple carelessness. Without a re-write I suspect
almost any change is as likely to introduce a bug as fix one (I tried
to see where the error was, but I gave up). If I was paid to fix it,
I'd simply start again and it would end a up as I have already posted,
though to mirror the behaviour I'd now have to add some argument
checking.

<snip>

[1] Apparently when the target string is not present in the source
string: e.g. replace("a", "x", "b").

--
Ben.

Dann Corbit

unread,
Feb 10, 2010, 8:18:49 PM2/10/10
to
In article <87ocjwo...@blp.benpfaff.org>, b...@cs.stanford.edu
says...

>
> Phred Phungus <Ph...@example.invalid> writes:
>
> > Ben Pfaff wrote:
> >> Dann Corbit <dco...@connx.com> writes:
> >>
> >>> For a standard library, the *most* important thing is correctness.
> >>> IOW, a bsearch() function that is blazing fast but fails if there
> >>> are more than 2 billion items is not as good as one that is only
> >>> half as fast but works with anything up to size_t (-1) number of
> >>> elements.
> >>
> >> If the former bsearch() implementation is on a system that
> >> doesn't support more than 2 billion bytes of contiguous data, I'm
> >> not worried about it.
> >
> > Why?
>
> Because the bsearch() function cannot exceed a limit of 2 billion
> items on an implementation that limits objects to 2 billion bytes
> or less.


If we are talking about constructing a best of breed library system for
the C language, then the distinction is of enormous importance.

While I agree it is not relevant for the original implementation, it is
for an implementation where we are trying to pick and choose the best
possible routines.

P.S.
The former case is still a bug waiting to happen.

Even if the former implementation is a toaster IC, 40 years in the
future, our toaster ICs will have 50 GB RAM on board.

Seebs

unread,
Feb 10, 2010, 8:46:29 PM2/10/10
to
On 2010-02-11, Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
> I don't think you can dismiss the bugs so easily. I would argue that
> it is not a coincidence that the more complex code has more bugs. I
> can't write code that looks like spinoza1111's code and get it right.
> I *have* to write simpler code, broken into simple functions, or I have
> no chance of getting it to be correct.

You may be right on this. Certainly, this kind of thing is one of the
major reasons that I sometimes rewrite things a few times until I am
sure I can understand the logic just by looking at it. If I have to
think it through, usually that means something is wrong, or the problem
is extremely hard.

> For example, the latest improvement introduced another bug[1] and I
> don't think that is simple carelessness. Without a re-write I suspect
> almost any change is as likely to introduce a bug as fix one (I tried
> to see where the error was, but I gave up). If I was paid to fix it,
> I'd simply start again and it would end a up as I have already posted,
> though to mirror the behaviour I'd now have to add some argument
> checking.

I think it would be interesting to start from his code and see whether it
can be fixed by cleanups and refactoring. I bet it could, although it'd
certainly take longer than just writing one from scratch.

But, e.g., starting by using names a little better than "ptrIndex1" and
the like would make it a ton simpler.

Peter Nilsson

unread,
Feb 10, 2010, 9:07:59 PM2/10/10
to
Seebs <usenet-nos...@seebs.net> wrote:
> There was some discussion of algorithms to perform the task:
>   Inputs:  target string, replacement string, original string
>   Output:  a newly-allocated string containing the original
>         string with each copy of the target string replaced
> with the replacement string.
>
> Here's a hunk of mine:
>
>   for (count = 0, t = strstr(target, in); t && *t;
> t = strstr(t, in)) {

Why are you seemingly scanning the target string for occurances
of 'in', which I would presume to be original 'input' string?

>                 ++count;
>                 t += inlen;
>         }

What if the string being scanned for is empty? If the string
to be scanned is non-empty, this will produce an infinite loop.

--
Peter

Seebs

unread,
Feb 10, 2010, 9:30:23 PM2/10/10
to
On 2010-02-11, Peter Nilsson <ai...@acay.com.au> wrote:
>> � for (count = 0, t = strstr(target, in); t && *t;
>> t = strstr(t, in)) {

> Why are you seemingly scanning the target string for occurances
> of 'in', which I would presume to be original 'input' string?

"in", "out", "original".

> What if the string being scanned for is empty? If the string
> to be scanned is non-empty, this will produce an infinite loop.

This was indeed observed, which is why the error checking at the
beginning of the function is now modified to reject a 0-length
thing-to-replace.

Eric Sosman

unread,
Feb 10, 2010, 9:46:41 PM2/10/10
to
On 2/10/2010 9:30 PM, Seebs wrote:
> On 2010-02-11, Peter Nilsson<ai...@acay.com.au> wrote:
>>> for (count = 0, t = strstr(target, in); t&& *t;

>>> t = strstr(t, in)) {
>
>> Why are you seemingly scanning the target string for occurances
>> of 'in', which I would presume to be original 'input' string?
>
> "in", "out", "original".
>
>> What if the string being scanned for is empty? If the string
>> to be scanned is non-empty, this will produce an infinite loop.
>
> This was indeed observed, which is why the error checking at the
> beginning of the function is now modified to reject a 0-length
> thing-to-replace.

... which is what I imagined the `*t' test in your fragment
was supposed to catch. If zero-length targets are rejected
earlier, I'm somehow missing the purpose of the `*t'.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Phred Phungus

unread,
Feb 11, 2010, 12:34:56 AM2/11/10
to

That's a lot of computer power for something that requires almost none.
--
fred

Richard

unread,
Feb 11, 2010, 1:52:21 AM2/11/10
to
Seebs <usenet...@seebs.net> writes:

Total nonsense.

The better one is the one that runs more efficiently and works. So assuming
the bug ix fixed and its more efficient then other is better. Its called
a function. You dont need to know whats in it.

io_x

unread,
Feb 11, 2010, 3:09:21 AM2/11/10
to

"Dann Corbit" <dco...@connx.com> ha scritto nel messaggio
news:MPG.25dcbceb3...@news.eternal-september.org...

for a standard library function
the *most* important thing is the easy to use
and the error handling well think

bugs could be detect and correct
one indeciprable assembly for a miracle
can be correct and run well

but for the not the easy to use
and the poor hadling of errors
all you have no way of correct them

Mark

unread,
Feb 11, 2010, 3:37:40 AM2/11/10
to
Richard wrote:
> Total nonsense.
>
> The better one is the one that runs more efficiently and works. So
> assuming the bug ix fixed and its more efficient then other is
> better. Its called a function. You dont need to know whats in it.

The one who will maintain this and other functions, needs to know what's in
it.

--
Mark

Nick Keighley

unread,
Feb 11, 2010, 4:01:16 AM2/11/10
to
On 11 Feb, 01:05, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Seebs <usenet-nos...@seebs.net> writes:

"I now suggest that we confine ourselves to the design and
implementation of intellectually manageable programs." Dijkstra

Nick Keighley

unread,
Feb 11, 2010, 4:12:59 AM2/11/10
to

yes. If strstr() didn't exist it would be necessary to invent it. The
use of appropriate abstractions simplifies the code.

We once had a system that manipulated messages. Messages were linked
lists of memory blocks. Queues were linked lists of messages. Since
the same pointers were used for both purposes a queue was also a list
of memory blocks.

The code needed to free (return to a free list) all the memory blocks
of the messages that came before a particular message type. Two pages
of tangled code needed to find the block before the first block of the
target message followed by direct manipulation of queue head and tail
pointer and the free list pointer. The blocks also had to be marked as
free (they had some associated data). After I found my third bug I
wrote:

while (not empty (queue) and queue_head.message_type != target)
{
msg = remove_msg (queue)
free_msg (msg)
}

(pseudo code)

As my version was shorter, simpler and more correct it was adopted.
Why deal with three things at once when it can be delegated else
where? The code wanted to manipulate messages not memory blocks.

Nick Keighley

unread,
Feb 11, 2010, 4:17:24 AM2/11/10
to
On 11 Feb, 06:52, Richard <rgrd...@gmail.com> wrote:
> Seebs <usenet-nos...@seebs.net> writes:

> > There was some discussion of algorithms to perform [some] task:

[simple code]

and

[complex code]

<snip>

> > The first is better, not because it's less buggy (that could be fixed), but
> > because it's simpler to understand.  It may, or may not, be less
> > efficient.
>
> Total nonsense.
>
> The better one is the one that runs more efficiently and works.

how do we demonstrate that it works?

> So assuming
> the bug ix fixed and its more efficient then other is better. Its called
> a function. You dont need to know whats in it.

"There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult."
-- C.A.R. Hoare

Richard Tobin

unread,
Feb 11, 2010, 7:47:32 AM2/11/10
to
In article <slrnhn628c.o3u...@guild.seebs.net>,
Seebs <usenet...@seebs.net> wrote:

>But you should always write the simpler one first, and wait until you've
>profiled the code and verified that there's a bottleneck, and you know where
>it is, before trying to optimize.

But wouldn't that be Extreme Programming?

(cf http://groups.google.com/group/comp.lang.c/msg/89ba3ef6554c9810?hl=en)

-- Richard
--
Please remember to mention me / in tapes you leave behind.

Seebs

unread,
Feb 11, 2010, 8:58:16 AM2/11/10
to
On 2010-02-11, Richard Tobin <ric...@cogsci.ed.ac.uk> wrote:
> In article <slrnhn628c.o3u...@guild.seebs.net>,
> Seebs <usenet...@seebs.net> wrote:
>>But you should always write the simpler one first, and wait until you've
>>profiled the code and verified that there's a bottleneck, and you know where
>>it is, before trying to optimize.

> But wouldn't that be Extreme Programming?

Only if you have two people do it at once, I think? :)

John Bode

unread,
Feb 11, 2010, 10:22:59 AM2/11/10
to
On Feb 11, 2:09 am, "io_x" <a...@b.c.invalid> wrote:
> "Dann Corbit" <dcor...@connx.com> ha scritto nel messaggionews:MPG.25dcbceb3...@news.eternal-september.org...
>

[snip]

>
> > For a standard library, the *most* important thing is correctness.  IOW,
>
> for a standard library function
> the *most* important thing is the easy to use
> and the error handling well think
>

It doesn't matter how easy to it is to use if it gives you the wrong
answer.
It doesn't matter how well it handles errors if it gives you the wrong
answer.
It doesn't matter how fast it is if it gives you the wrong answer.
It doesn't matter how much memory it uses if it gives you the wrong
answer.

Correctness comes first. Then we can argue about everything else.

Dann Corbit

unread,
Feb 11, 2010, 2:49:56 PM2/11/10
to
In article <367d44ff-3e74-464c-a816-e8280fb262e6
@a32g2000yqm.googlegroups.com>, jfbod...@gmail.com says...

>
> On Feb 11, 2:09ï¿œam, "io_x" <a...@b.c.invalid> wrote:
> > "Dann Corbit" <dcor...@connx.com> ha scritto nel messaggionews:MPG.25dcbceb3...@news.eternal-september.org...
> >
>
> [snip]
>
> >
> > > For a standard library, the *most* important thing is correctness. ï¿œIOW,

> >
> > for a standard library function
> > the *most* important thing is the easy to use
> > and the error handling well think
> >
>
> It doesn't matter how easy to it is to use if it gives you the wrong
> answer.
> It doesn't matter how well it handles errors if it gives you the wrong
> answer.
> It doesn't matter how fast it is if it gives you the wrong answer.
> It doesn't matter how much memory it uses if it gives you the wrong
> answer.
>
> Correctness comes first. Then we can argue about everything else.

Besides which, we don't get to change ease of use. The interface and
documentation are already fully specified.

io_x

unread,
Feb 11, 2010, 3:02:15 PM2/11/10
to

"John Bode" <jfbod...@gmail.com> ha scritto nel messaggio
news:367d44ff-3e74-464c...@a32g2000yqm.googlegroups.com...

[snip]

#first is the idea that is good (and make all easy)
#after correct pariticulars (like litte bugs etc)


io_x

unread,
Feb 11, 2010, 3:08:58 PM2/11/10
to

"Nick Keighley" <nick_keigh...@hotmail.com> ha scritto nel messaggio
news:1fc6e498-5e85-4499...@y33g2000yqb.googlegroups.com...

On 11 Feb, 01:05, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Seebs <usenet-nos...@seebs.net> writes:

> I don't think you can dismiss the bugs so easily. I would argue that
> it is not a coincidence that the more complex code has more bugs. I
> can't write code that looks like spinoza1111's code and get it right.
> I *have* to write simpler code, broken into simple functions, or I have
> no chance of getting it to be correct.

"I now suggest that we confine ourselves to the design and
implementation of intellectually manageable programs." Dijkstra

#yes that is the way
#that i not follow

io_x

unread,
Feb 11, 2010, 3:10:27 PM2/11/10
to

"Nick Keighley" <nick_keigh...@hotmail.com> ha scritto nel messaggio
news:1fc6e498-5e85-4499...@y33g2000yqb.googlegroups.com...
On 11 Feb, 01:05, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Seebs <usenet-nos...@seebs.net> writes:

> I don't think you can dismiss the bugs so easily. I would argue that
> it is not a coincidence that the more complex code has more bugs. I
> can't write code that looks like spinoza1111's code and get it right.
> I *have* to write simpler code, broken into simple functions, or I have
> no chance of getting it to be correct.

"I now suggest that we confine ourselves to the design and
implementation of intellectually manageable programs." Dijkstra

#yes that is the way
#that i not follow: possible i write code because i like miracles

Michael Foukarakis

unread,
Feb 12, 2010, 4:53:12 AM2/12/10
to
On Feb 11, 2:47 pm, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
> In article <slrnhn628c.o3u.usenet-nos...@guild.seebs.net>,

>
> Seebs  <usenet-nos...@seebs.net> wrote:
> >But you should always write the simpler one first, and wait until you've
> >profiled the code and verified that there's a bottleneck, and you know where
> >it is, before trying to optimize.
>
> But wouldn't that be Extreme Programming?
>
> (cfhttp://groups.google.com/group/comp.lang.c/msg/89ba3ef6554c9810?hl=en)

Is that a Bad Thing™?

io_x

unread,
Feb 12, 2010, 10:11:01 AM2/12/10
to

"io_x" <a...@b.c.invalid> ha scritto nel messaggio
news:4b74623a$0$1127$4faf...@reader3.news.tin.it...

>
> "Nick Keighley" <nick_keigh...@hotmail.com> ha scritto nel messaggio
> news:1fc6e498-5e85-4499...@y33g2000yqb.googlegroups.com...
> On 11 Feb, 01:05, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> Seebs <usenet-nos...@seebs.net> writes:
>
>> I don't think you can dismiss the bugs so easily. I would argue that
>> it is not a coincidence that the more complex code has more bugs. I
>> can't write code that looks like spinoza1111's code and get it right.
>> I *have* to write simpler code, broken into simple functions, or I have
>> no chance of getting it to be correct.
>
> "I now suggest that we confine ourselves to the design and
> implementation of intellectually manageable programs." Dijkstra
>
> #yes that is the way
> #that i not follow: possible i write code because i like miracles

#yes i follow it but not every times

spinoza1111

unread,
Feb 12, 2010, 12:00:26 PM2/12/10
to

Don't lie, and don't try to bring me down to your low level. When you
posted this code, the bug had been fixed.

You are incredibly dishonest. You were dishonest when you advanced
your career by trying to destroy Herb Schildt, and here, on Feb 11,
you posted an OLD version of the code that contained the bug that that
the search is resumed after the end of the partial match, missing
overlapping strings.

I found, reported and fixed this bug on Feb 10 and on that date you
acknowledged that you had not found it. Also on that date, I made a
code improvement that works based on insight provided by the bug:
taking the first occurrence of the handle after the start of a partial
match as the restart point.

You have dishonestly presented the above code as my latest version in
order to dishonestly recover your reputation for competence, but you
are both incompetent and dishonest.
>
> My thinking:


>
> The first is better, not because it's less buggy (that could be fixed), but

You continually post solutions with bugs: you do not fix your crap:
and yet you have the nerve to disrespect others based on their bugs.

> because it's simpler to understand.  It may, or may not, be less efficient.

> However, efficiency will vary widely with input characteristics; for some
> cases, the arguable inefficiencies may be completely irrelevant, while in
> others, they'd be significant.
>

> But you should always write the simpler one first, and wait until you've
> profiled the code and verified that there's a bottleneck, and you know where

> it is, before trying to optimize.  You may, or may not, be able to outperform
> a given library's implementation of strstr().  If you have unusual inputs,
> you have a pretty good shot at it... But it may not be worth it.  The
> complicated example has had at least one bug identified, and there may be
> others.  It's extremely hard to read, partially because of the poor
> naming, and partially because of the counter-idiomatic usage.  But mostly,
> it's a lot more work to write and maintain, and for no known benefit.
>
> It's good to think a little about efficiency, but write for clarity and
> correctness first, so you have a known-working program to check your
> results if you later need to modify it for speed.

But: your code, as you concede, isn't working!

What a jerk!
>
> -s
> --
> Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

spinoza1111

unread,
Feb 12, 2010, 12:10:36 PM2/12/10
to
On Feb 11, 9:05 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> can't write code that looks likespinoza1111'scode and get it right.

> I *have* to write simpler code, broken into simple functions, or I have
> no chance of getting it to be correct.
>
> For example, the latest improvement introduced another bug[1] and I
> don't think that is simple carelessness.  Without a re-write I suspect
> almost any change is as likely to introduce a bug as fix one (I tried
> to see where the error was, but I gave up).  If I was paid to fix it,
> I'd simply start again and it would end a up as I have already posted,
> though to mirror the behaviour I'd now have to add some argument
> checking.
>
> <snip>
>
> [1] Apparently when the target string is not present in the source
> string: e.g. replace("a", "x", "b").

I have returned to this little project following my sabbatical to let
other people post their views.

Good call.

Replace "x" by "b" in "a"
Expect "a":
"ab"
Replacements expected: 0: replacements: 1
Assertion failed

I am fixing the problem, now, because unlike Seebach, I fix my bugs.
It's 1:09 AM 13 Feb.

Gung hey fat choi.
>
> --
> Ben.

spinoza1111

unread,
Feb 12, 2010, 1:46:47 PM2/12/10
to
On Feb 11, 9:05 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> can't write code that looks likespinoza1111'scode and get it right.

> I *have* to write simpler code, broken into simple functions, or I have
> no chance of getting it to be correct.
>
> For example, the latest improvement introduced another bug[1] and I
> don't think that is simple carelessness.  Without a re-write I suspect
> almost any change is as likely to introduce a bug as fix one (I tried
> to see where the error was, but I gave up).  If I was paid to fix it,
> I'd simply start again and it would end a up as I have already posted,
> though to mirror the behaviour I'd now have to add some argument
> checking.
>
> <snip>
>
> [1] Apparently when the target string is not present in the source
> string: e.g. replace("a", "x", "b").
>
> --
> Ben.

It took me about an hour to fix this because of some blind alleys. See
the Change Record for 13 Feb for the explanation of the bug, a failure
to anticipate that there could be a situation when the main scan
pointer (ptrIndex1) and the main target pointer (ptrIndex2) both point
to Nul but the strings do not match.

In addition, I discovered that there are cases when I initialize the
secondary scan pointer ptrIndex3 to one past the Nul that terminates
the master string, and this has also been fixed.

The purpose of my style and approach is to reduce the bug rate
exponentially going forward. I don't post code while saying "it has a
bug, but it's easy to fix". This was Peter Seebach's initial mistake:
he posted a crappy solution to replacing %s that used a character scan
that fails when a percent occurs in the input, admitting the bug
without bothering to fix it.

This is why I have retained so many tests, and why I wrote a TESTER
macro, and why I formatted the code more carefully than most little
code monkeys care to format their code.

This is the arrogant programmer who expects others to clean up his
messes for him (and lies about people to get his way, I might add).

Having said all this, I am not completely happy with my solution. This
is because I have no assurance that there might be other cases where
it fails, and this in turn is because it's just code, not theory. In
terms of CS theory, it's doing two things at once: finding strings,
and replacing them. As I have said, it arbitrarily goes left to right
and doesn't handle overlapping hits in the way some applications might
require replace("banana", "ana", "xxx") to yield bxxxxx.

[In rereading Cormen's Algorithms the other night on string matching,
which treats the problem separate from match/replace for solid
theoretical reasons, I noticed that one of his students brought this
to his attention.]

Programmers who backstab and lie, who mock others who fix their bugs
for having the bugs, while grinning about their own, and who present
code with bugs that they won't fix, create buggy solutions out of
dishonesty. They helped to cause the credit crisis, because in many
cases, securitized mortgages and their derivative contracts were never
examined for loops such that one derivative referred to itself through
a chain. It increasingly appears that bugs in software lie at the
bottom of the Toyota recall.

Dijkstra is right. Programming IS too hard for Republicans and other
liars (Peter Seebach is on record as a Bush supporter, at least in
2000).

Here is the latest version, followed by its console output.

// ***************************************************************
// * *
// * replace() demo *
// * *
// * Demonstrates how to replace non-NUL-defined strings in C *
// * using a simple function, and bypassing string.h. *
// * *
// * C H A N G E R E C O R D --------------------------------- *
// * DATE PROGRAMMER DESCRIPTION OF CHANGE *
// * -------- ---------- --------------------------------- *
// * 02 07 10 Nilges Version 1.0 *
// * *
// * 02 07 10 Nilges Bug: partial matches not handled *
// * correctly: need to iterate search *
// * for match. *
// * *
// * 02 07 10 Nilges 1. Santosh suggested tests *
// * 2. Heathfield put the boot in re *
// * including malloc *
// * *
// * 02 07 10 Nilges 1. Remove string.h use and code *
// * strlen by hand *
// * 2. Add comment block and comments*
// * inline. *
// * 3. free() storage *
// * 4. Use macro for testing *
// * 5. Bug: calculation of *
// * lngNewLength used incorrect *
// * index (intIndex3 instead of 2)*
// * which caused a memory leak. *
// * *
// * 02 07 10 Nilges 1. Bug: Ike Naar test failed. *
// * At end of scan loop, main *
// * string pointer was not *
// * correctly updated from index3 *
// * *
// * 02 07 10 Nilges Added new Santosh test *
// * *
// * 02 07 10 Nilges Added new Ike Naar test *
// * *
// * 02 08 10 Nilges 1. Added some new comments *
// * 2. Make "check for a complete *
// * match "structured" by means *
// * of a tested assignment *
// * 3. Get rid of "replace at end" *
// * evilness: the only time this *
// * flag is meaningful is in the *
// * LAST segment. *
// * 4. Return replace count *
// * 5. TESTER macro assertion added *
// * *
// * 02 10 10 Nilges 1. Bug fix: in a partial match, *
// * the main scan index is set to *
// * one past the end, which misses*
// * full matches that start *
// * between the first character of*
// * the partial match and its end.*
// * *
// * No longer updating the main *
// * scan index (ptrIndex1) to the *
// * point of partial match *
// * failure: setting it one past *
// * the first character of the *
// * partial match. *
// * *
// * 2. Line up expected & actual *
// * results per excellent *
// * suggestion (who made this?) *
// * *
// * 3. After a partial match, update *
// * the main handle search index *
// * (ptrIndex1) to the first *
// * occurrence of the handle *
// * character after the start of *
// * the partial match, or to the *
// * index of the unmatched char. *
// * *
// * 021310 Nilges Bug: failed to handle a one-char *
// * replace (of a by x in b) since *
// * we set ptrIndex2 to point to NUL *
// * which made it appear that there *
// * was a match. When the main index *
// * to the master string (ptrIndex1) *
// * goes off the end of a cliff, we *
// * needed to break out of the search *
// * loop. *
// * *
// * This also entailed setting the *
// * target index ptrIndex2 to 0 at the*
// * beginning of each search so that *
// * it is not erroneously used to *
// * indicate that there's an insert *
// * needed at the end. *
// * *
// * I have also added additional tests*
// * to verify that the code works *
// * when the string and target end *
// * at the same time. *
// * ----------------------------------------------------------- *
// * *
// * "In the near future we shall have to live with the *
// * superstition that programming is 'so easy that even a *
// * Republican can do it!'" *
// * *
// * - E. W. Dijkstra *
// * *
// * *
// ***************************************************************
#include <stdio.h>
#include <stdlib.h>
// ***** Segmentation *****
struct TYPsegmentstruct
{ char * strSegment;
long lngSegmentLength;
struct TYPsegmentstruct * ptrNext; };
// ---------------------------------------------------------------
// Calculate string length
//
//
long strLength(char *strInstring)
{
char *ptrInstring;
for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
return ptrInstring - strInstring;
}

// ---------------------------------------------------------------
// Replace target by replacement string in master string
//
//
// Caution: the string returned by this function should be freed.
//
//
char * replace(char * strMaster,
char * strTarget,
char * strReplacement,
long * ptrReplacements)
{
char * ptrIndex0;
char * ptrIndex1;
char * ptrIndex2;
char * ptrIndex3;
char * ptrIndex4;
char * strNew;
char * strNewStart;
long lngNewLength;
long lngCount;
long lngReplacementLength;
struct TYPsegmentstruct * ptrSegmentStructStarts;
struct TYPsegmentstruct * ptrSegmentStruct;
struct TYPsegmentstruct * ptrSegmentStructPrev;
lngReplacementLength = strLength(strReplacement);
if (!*strTarget)
{
printf("Error in calling replace(): target can't be null");
abort();
}
ptrIndex1 = strMaster;
ptrSegmentStructPrev = 0;
lngNewLength = 0;
*ptrReplacements = 0;
while(*ptrIndex1)
{
ptrIndex0 = ptrIndex1;
ptrIndex2 = 0;
while (-1)
{
// --- Check for (one character) handle


for(;
*ptrIndex1 && *ptrIndex1 != *strTarget;
ptrIndex1++);

if (!*ptrIndex1) break;
// --- Check for complete match while remembering the
// --- last position of the handle
ptrIndex4 = 0;
for(ptrIndex2 = strTarget + 1,
ptrIndex3 = ptrIndex1 + 1;


*ptrIndex3
&&
*ptrIndex2
&&
*ptrIndex3 == *ptrIndex2;
ptrIndex3++, ptrIndex2++)
{

if (*ptrIndex3 == *strTarget
&&
ptrIndex4 == 0) ptrIndex4 = ptrIndex3;
}
// End test: check complete match, update main ptr past
// partial match while checking for end of loop
if ((!*ptrIndex2 ? ((*ptrReplacements)++, -1) : 0)
||
(!*ptrIndex3 ? (ptrIndex1 = ptrIndex3, -1) : 0))
break;
// Update the main search pointer
ptrIndex1 = (ptrIndex4 == 0 ? ptrIndex3 : ptrIndex4);
}
// --- Create new segment
if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;
ptrSegmentStruct->ptrNext = 0;
if (ptrSegmentStructPrev != 0)
ptrSegmentStructPrev->ptrNext = ptrSegmentStruct;
else
ptrSegmentStructStarts = ptrSegmentStruct;
ptrSegmentStructPrev = ptrSegmentStruct;
// --- Update mallocation length
lngNewLength += ptrSegmentStruct->lngSegmentLength +
(ptrIndex2 && !*ptrIndex2
?
lngReplacementLength
:
0);
// --- Get past end of target string & iterate
if (*ptrIndex1) ptrIndex1 = ptrIndex3;
}
// --- Allocate just enough storage for the new string
if (!(strNewStart = malloc(lngNewLength + 1))) abort();
// --- Build the new string whilst freeing the list
strNew = strNewStart;
ptrSegmentStruct = ptrSegmentStructStarts;
while (ptrSegmentStruct)
{
for (ptrIndex1 = ptrSegmentStruct->strSegment,
lngCount = 0;
lngCount < ptrSegmentStruct->lngSegmentLength;
ptrIndex1++, lngCount++, strNew++)
*strNew = *ptrIndex1;
if (ptrSegmentStruct->ptrNext
||
ptrIndex2 != 0 && !*ptrIndex2)
for (ptrIndex1 = strReplacement;
*ptrIndex1;
ptrIndex1++, ++strNew)
*strNew = *ptrIndex1;
ptrSegmentStructPrev = ptrSegmentStruct;
ptrSegmentStruct = ptrSegmentStruct->ptrNext;
free(ptrSegmentStructPrev);
}
*strNew = '\0';
return strNewStart;
}

// ---------------------------------------------------------------
// Statement-format test macro
//
//
#define TESTER(resultPtr, master, target, replacement, expected,
expectedReplacements, replacements) \
{ \
printf("Replace \"%s\" by \"%s\" in \"%s\"\n", \
(target), (replacement), (master)); \
printf("Expect \"%s\":\n \"%s\"\n", \
(expected), \
resultPtr = replace((master), \
(target), \
(replacement), \
&(replacements))); \
printf("Replacements expected: %d: replacements: %d\n", \
(expectedReplacements), \
(replacements)); \
if (!(strLength(resultPtr) \
== \
strLength(master) \
+ \
(strLength(replacement)-strLength(target)) \
* \
replacements)) \
printf("Assertion failed\n"); \
printf("\n\n"); \
free(resultPtr); \
}

// ---------------------------------------------------------------
// Main procedure
//
//
int main()
{
char *ptrResult;
long lngReplacements;
printf("\nReplace\n\n\n");
TESTER(ptrResult,
"1111123bbb1111123bbb11123bb11111231111112111111123",
"111123",
"ono",
"1onobbb1onobbb11123bb1ono1111112111ono",
4,
lngReplacements)
TESTER(ptrResult,
"bbb1111123bbbbb",
"111123",
"ono",
"bbb1onobbbbb",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid error",
"stupid error",
"miracle",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid error",
"stupid",
"miracle",
"a miracle error",
1,
lngReplacements)
TESTER(ptrResult,
"the stupid error",
"the stupid error",
"a miracle",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"the miracle",
"the",
"a",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"a miraclsnirpKamunkle",
"snirpKamunkle",
"e",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"a miraclesnirpKamunkle",
"a miracle",
"",
"snirpKamunkle",
1,
lngReplacements)
TESTER(ptrResult,
" a miraclesnirpKamunkle",
"a miracle",
"",
" snirpKamunkle",
1,
lngReplacements)
TESTER(ptrResult,
" a miraclesnirpKamunklea miraclea miracle",
"a miracle",
"",
" snirpKamunkle",
3,
lngReplacements)
TESTER(ptrResult,
"a miracle a miraclesnirpKamunkle a Miraclea miraclea
miracle",
"a miracle",
"",
" snirpKamunkle a Miracle",
4,
lngReplacements)
TESTER(ptrResult,
"a stupid errord",
"stupid error",
"miracle",
"a miracled",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid errod",
"stupid error",
"miracle",
"a stupid errod",
0,
lngReplacements)
TESTER(ptrResult,
"a sstupid error",
"stupid error",
"miracle",
"a smiracle",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid errorstupid error",
"stupid error",
"miracle",
"a miraclemiracle",
2,
lngReplacements)
TESTER(ptrResult,
"a stupid error stupiderror",
"stupid error",
"miracle",
"a miracle stupiderror",
1,
lngReplacements)
TESTER(ptrResult,
"bbbbbbbbbb",
"b",
"a",
"aaaaaaaaaa",
10,
lngReplacements)
TESTER(ptrResult,
"In the halls of R'yleh great %s lies dreaming",
"%s",
"Cthulu",
"In the halls of R'yleh great Cthulu lies dreaming",
1,
lngReplacements)
TESTER(ptrResult,
"%s%s%s%s%s%s",
"%s",
"Cthulu",
"CthuluCthuluCthuluCthuluCthuluCthulu",
6,
lngReplacements)
TESTER(ptrResult,
"banana",
"ana",
"oat",
"boatna",
1,
lngReplacements)
TESTER(ptrResult,
" a stupid errorstupid errorHeystupid errors",
"stupid error",
"+",
" a ++Hey+s",
3,
lngReplacements)
TESTER(ptrResult,
"foo barfoo barf",
"foo bar",
"bas",
"basbasf",
2,
lngReplacements)
TESTER(ptrResult,
"abab",
"ba",
"ba",
"abab",
1,
lngReplacements)
TESTER(ptrResult,
"abab",
"bab",
"boop",
"aboop",
1,
lngReplacements)
TESTER(ptrResult,
"banana",
"ana",
"ono",
"bonona",
1,
lngReplacements)
TESTER(ptrResult,
"a",
"x",
"b",
"a",
0,
lngReplacements)
TESTER(ptrResult,
"x",
"x",
"b",
"b",
1,
lngReplacements)
TESTER(ptrResult,
"egregious",
"egregious",
"egregious",
"egregious",
1,
lngReplacements)
TESTER(ptrResult,
"egregious",
"egregious",
"x",
"x",
1,
lngReplacements)
printf("\n\nTesting complete: check output carefully: \"Assertion
failed\" should not occur!\n\n");
return 0;
}


Replace


Replace "111123" by "ono" in
"1111123bbb1111123bbb11123bb11111231111112111111123"
Expect "1onobbb1onobbb11123bb1ono1111112111ono":
"1onobbb1onobbb11123bb1ono1111112111ono"
Replacements expected: 4: replacements: 4


Replace "111123" by "ono" in "bbb1111123bbbbb"
Expect "bbb1onobbbbb":
"bbb1onobbbbb"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "miracle" in "a stupid error"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "stupid" by "miracle" in "a stupid error"
Expect "a miracle error":
"a miracle error"
Replacements expected: 1: replacements: 1


Replace "the stupid error" by "a miracle" in "the stupid error"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "the" by "a" in "the miracle"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "snirpKamunkle" by "e" in "a miraclsnirpKamunkle"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "a miracle" by "" in "a miraclesnirpKamunkle"
Expect "snirpKamunkle":
"snirpKamunkle"
Replacements expected: 1: replacements: 1


Replace "a miracle" by "" in " a miraclesnirpKamunkle"
Expect " snirpKamunkle":
" snirpKamunkle"
Replacements expected: 1: replacements: 1


Replace "a miracle" by "" in " a miraclesnirpKamunklea miraclea
miracle"
Expect " snirpKamunkle":
" snirpKamunkle"
Replacements expected: 3: replacements: 3


Replace "a miracle" by "" in "a miracle a miraclesnirpKamunkle a
Miraclea miraclea miracle"
Expect " snirpKamunkle a Miracle":
" snirpKamunkle a Miracle"
Replacements expected: 4: replacements: 4


Replace "stupid error" by "miracle" in "a stupid errord"
Expect "a miracled":
"a miracled"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "miracle" in "a stupid errod"
Expect "a stupid errod":
"a stupid errod"
Replacements expected: 0: replacements: 0


Replace "stupid error" by "miracle" in "a sstupid error"
Expect "a smiracle":
"a smiracle"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "miracle" in "a stupid errorstupid error"
Expect "a miraclemiracle":
"a miraclemiracle"
Replacements expected: 2: replacements: 2


Replace "stupid error" by "miracle" in "a stupid error stupiderror"
Expect "a miracle stupiderror":
"a miracle stupiderror"
Replacements expected: 1: replacements: 1


Replace "b" by "a" in "bbbbbbbbbb"
Expect "aaaaaaaaaa":
"aaaaaaaaaa"
Replacements expected: 10: replacements: 10


Replace "%s" by "Cthulu" in "In the halls of R'yleh great %s lies
dreaming"
Expect "In the halls of R'yleh great Cthulu lies dreaming":
"In the halls of R'yleh great Cthulu lies dreaming"
Replacements expected: 1: replacements: 1


Replace "%s" by "Cthulu" in "%s%s%s%s%s%s"
Expect "CthuluCthuluCthuluCthuluCthuluCthulu":
"CthuluCthuluCthuluCthuluCthuluCthulu"
Replacements expected: 6: replacements: 6


Replace "ana" by "oat" in "banana"
Expect "boatna":
"boatna"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "+" in " a stupid errorstupid errorHeystupid
errors"
Expect " a ++Hey+s":
" a ++Hey+s"
Replacements expected: 3: replacements: 3


Replace "foo bar" by "bas" in "foo barfoo barf"
Expect "basbasf":
"basbasf"
Replacements expected: 2: replacements: 2


Replace "ba" by "ba" in "abab"
Expect "abab":
"abab"
Replacements expected: 1: replacements: 1


Replace "bab" by "boop" in "abab"
Expect "aboop":
"aboop"
Replacements expected: 1: replacements: 1


Replace "ana" by "ono" in "banana"
Expect "bonona":
"bonona"
Replacements expected: 1: replacements: 1


Replace "x" by "b" in "a"
Expect "a":
"a"

Replacements expected: 0: replacements: 0


Replace "x" by "b" in "x"
Expect "b":
"b"
Replacements expected: 1: replacements: 1


Replace "egregious" by "egregious" in "egregious"
Expect "egregious":
"egregious"
Replacements expected: 1: replacements: 1


Replace "egregious" by "x" in "egregious"
Expect "x":
"x"
Replacements expected: 1: replacements: 1


Testing complete: check output carefully: "Assertion failed" should
not occur!

spinoza1111

unread,
Feb 12, 2010, 1:48:38 PM2/12/10
to
On Feb 11, 9:46 am, Seebs <usenet-nos...@seebs.net> wrote:

> On 2010-02-11, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>
> > I don't think you can dismiss the bugs so easily.  I would argue that
> > it is not a coincidence that the more complex code has more bugs.  I
> > can't write code that looks likespinoza1111'scode and get it right.

> > I *have* to write simpler code, broken into simple functions, or I have
> > no chance of getting it to be correct.
>
> You may be right on this.  Certainly, this kind of thing is one of the
> major reasons that I sometimes rewrite things a few times until I am
> sure I can understand the logic just by looking at it.  If I have to
> think it through, usually that means something is wrong, or the problem
> is extremely hard.
>
> > For example, the latest improvement introduced another bug[1] and I
> > don't think that is simple carelessness.  Without a re-write I suspect
> > almost any change is as likely to introduce a bug as fix one (I tried
> > to see where the error was, but I gave up).  If I was paid to fix it,
> > I'd simply start again and it would end a up as I have already posted,
> > though to mirror the behaviour I'd now have to add some argument
> > checking.
>
> I think it would be interesting to start from his code and see whether it
> can be fixed by cleanups and refactoring.  I bet it could, although it'd
> certainly take longer than just writing one from scratch.

Well, unlike your original bug of scanning for % in two places as
ersatz for finding the string %s, it would be a simple matter for you
to use a modern editor to get rid of my Hungarian. And you cannot seem
to solve the problem from scratch without creating bugs that you won't
fix.


>
> But, e.g., starting by using names a little better than "ptrIndex1" and
> the like would make it a ton simpler.
>
> -s
> --

spinoza1111

unread,
Feb 12, 2010, 1:53:48 PM2/12/10
to
On Feb 11, 5:01 pm, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
> > can't write code that looks likespinoza1111'scode and get it right.

> > I *have* to write simpler code, broken into simple functions, or I have
> > no chance of getting it to be correct.
>
> "I now suggest that we confine ourselves to the design and
> implementation of intellectually manageable programs." Dijkstra

Amen, brother.

Dijkstra would say that we needed to disambiguate the two goals, and
that the unexpected complexity of "find and replace" results from the
fact that there are two things going on.

Perhaps we really need a string finder and a replacer which would
encapsulate left to right, right to left, and what to do on overlap.

However, the traditional way to do this can be slow, since it involves
creating a "table" of occurrences.

But two independent processes, a source and a sink, would handle the
problems nicely.

spinoza1111

unread,
Feb 12, 2010, 1:56:19 PM2/12/10
to

True, which is why I've responded to each bug report. But note that in
many industrial programming environments, where programming is a pure
cost center and creativity isn't wanted, responding to bugs can be
renarrated as having a lot of bugs.

This is why Peter admits bugs...but doesn't fix them.

Anand Hariharan

unread,
Feb 12, 2010, 1:57:45 PM2/12/10
to


Correctness is to do with the implementation. As a function in the
standard library, it is important to get its interface 'right' (which
relates to ease of use and error handling).

spinoza1111

unread,
Feb 12, 2010, 1:59:40 PM2/12/10
to
On Feb 12, 5:53 pm, Michael Foukarakis <electricde...@gmail.com>
wrote:

Towards the end of my own programming career (I left the field to
become a teacher), I had very good experience with Extreme Programming
in Pairs. Surprisingly, the embodied humanity of the two people
working together, along with a little professionalism, helps even
enemies work on code together. I could probably even work with
Seebach, after I got finished slapping him around. Just
kidding...about the bitch slap.

spinoza1111

unread,
Feb 12, 2010, 2:36:56 PM2/12/10
to
> For example, the latest improvement introduced another bug[1] and I

For the record, the bug was always there. My changes using the
extensive regression tests tend in my experience not to introduce new
bugs.

> don't think that is simple carelessness.  Without a re-write I suspect
> almost any change is as likely to introduce a bug as fix one (I tried
> to see where the error was, but I gave up).  If I was paid to fix it,

Then you did not understand the code. I agree that because it fuses
two different functions (find target and replace target) for
efficiency and the hell of it, it is a hard piece of code (and note
that no other solution I've seen adheres to my self-imposed rule of
not using string.h, yet most or all of the other solutions have bugs
that are announced but not fixed).

I also agree that reading C is hard. But if anyone could have
understood the code, you could have.


> I'd simply start again and it would end a up as I have already posted,
> though to mirror the behaviour I'd now have to add some argument
> checking.


...and not use string.h. I recall that you did. Please correct me if I
am wrong.


>
> <snip>
>
> [1] Apparently when the target string is not present in the source
> string: e.g. replace("a", "x", "b").
>

> --
> Ben.

Eric Sosman

unread,
Feb 12, 2010, 6:06:03 PM2/12/10
to

The rightness or wrongness of the interface is not the
implementation's to decide: It must implement the interface(s)
the governing standard(s) describe. An implementation is *not*
at liberty to say "The fact that the FILE* argument is first
for fprintf() and last for fputs() is ugly; let's change fputs()
so the FILE* comes first and thereby improve the interface."
An implementation is *not* allowed to have strcat() return a
pointer to the output's terminating '\0' instead of to its
start, even though the latter would be more helpful. And so
on: the standard dictates the interface, and the implementors
get no say in the matter. (Some of us remember the pre-ANSI days
when implementors exercised their imagination more liberally; I
for one do not ever wish to return to that state of affairs.)

... which is not to say that I'm in love with the library as
it exists; the "bazaar" generates lots of annoying quirks. But
that's The Way Things Are, and we learn to cope. Implementors,
too, learn to cope. And not to invent, not in this domain.

--
Eric Sosman
eso...@ieee-dot-org.invalid

spinoza1111

unread,
Feb 13, 2010, 1:04:13 AM2/13/10
to

This is an example of subservience to things (and ideas) which I find
limiting.

It's like the nonsense that started at Bell Northern Research three
years after I started and the incompetents came in.

Everyone divided themselves by tribes not defined by passion and
ability (which had created the two man tribe of Whitfield Diffie and
Bob Gaskins that invented Powerpoint) but by loyalty either to DEC or
IBM (this was the early 1980s).

Or more precisely:

We had fed the heart on fantasies,
The heart's grown brutal from the fare;
More substance in our enmities
Than in our love;

(WB Yeats, The Stare's Nest by My Window).

That is, the defects in the apparatus "loved" meant that the "love"
was merely a dislike of the other tribe.

This has devolved to the headhunter logic: that if an applicant has a
PhD in computer science and has implemented an OS for his thesis in C+
+, but the job requires C, she's not "qualified"...because the
headhunter (with some sort of crap business degree) can't put her into
an authoritarian box.

I'm programming in C at a somewhat higher level than anyone else in
this discussion, with all due humility. Nobody else has posted a
solution to the actual problem (do replace without string.h and fix
the bugs, don't stare at them), as far as I've seen. This despite the
fact that technically and in a unique way, I'm a newbie, having not
used C since 1991.

Learning a programming language per se (which is usually combined with
learning programming) is pretty trivial. In 1991, it was RTFM (reading
the fucking manual). Today, you use online help, intellisense and the
Internet to get up to speed, or back up. You make silly errors, but a
real man is unafraid to make silly errors (as opposed to many here).

What's amazing being that one can dip in almost anywhere in a semi-
readable and gloomy book by Theodore Adorno, a midcentury musicologist/
philosopher/sociologist who worked at a rather low level white collar
job, and got fired for trying to do it effectively:

I.Q. – The modes of conduct appropriate to the most progressive
technical state of development are not limited to the sectors, in
which they are actually promoted. Thus thinking submits to the social
supervision of its services not only where it is forced to do so by
its occupation, but comes to resembles such in its entire complexion.
Because thought has been well-nigh inverted into the solution of tasks
assigned to it, what is not assigned is also dealt with according to
the schema of the task. Thought, having lost its autonomy, no longer
trusts itself to comprehend something real for its own sake, in
freedom. This it leaves, with respectful illusion, to the highest-
paid, and makes itself measurable for this. It tends to behave, for
its own part, as if it had to unceasingly portray its usefulness. Even
where there is no nutshell to crack, thinking turns into training [in
English in original] for some sort of exercise or other.

What is "real"? It's not using "obeying the rules of the C standard"
as an excuse for not fixing bugs. And given that many of the "annoying
quirks" of the existing libraries are real bugs or primitive
limitations imposed by older technology, it seems to be that you DO
have to invent.
> --
> Eric Sosman
> esos...@ieee-dot-org.invalid

spinoza1111

unread,
Feb 13, 2010, 4:25:27 AM2/13/10
to
On Feb 13, 2:46 am, spinoza1111 <spinoza1...@yahoo.com> wrote:
...code...

I noticed that in the latest (13 Feb) version of the code, with the
fix to the one-character replace found by Ben B, there were some file
nits: two long lines split and blanks at end of continued macro lines.

Let's see if I can get rid of these problems.

Also, I misspoke. The failure to handle Ben's example was caused by an
earlier change.

Here is the latest code, without the console output.

miracleamiracle",

spinoza1111

unread,
Feb 13, 2010, 5:30:53 AM2/13/10
to
On Feb 13, 5:25 pm, spinoza1111 <spinoza1...@yahoo.com> wrote:

...latest code...

Most posters will probably know that in downloading the code you
probably must:

1. Remove all spaces after the continuation markers in the TESTER
macro (at least on the Microsoft compiler: isn't this a bug that the
backslash may not be followed by a space, or was this horse puckey
blessed by the standard?)

2. Rejoin all lines split past position 67 if this is what your
browser does:

2.1 The TESTER header
2.2 The test of "a miracle a miraclesnirpKamunkle a Miraclea
miracleamiracle": note that in the latest post, I screwed up the
repair of this line which is why you should get ONE unexpected result
in your test of the latest code. Sensible and well-intentioned
developers will be able to figure this one out on their own, although
Heathfield will probably start foaming at the mouth
2.3 The last printf

At this point the code still does what appears to be unnecessary work
in the form of examining partial matches that occur starting to the
left of another partial match. This is because it notes only the one-
character "handle" of the left-partial match.

However, we know that

* No match can contain a match inside of it because it is
impossible for a proper substring of a string to match the containing
string, where a "proper" substring of X, X', is one of length(X)-n
where n>0. In simple English, a string cannot contain itself as a
proper substring. I think.

* Therefore, if we find the character handle of the target
inside a partial or complete occurrence of the target, this is an
overlapping string starting at the handle.

It seemed like a good idea, perhaps because I am evading the issue of
Boyer, Moore, Knuth, Pratt, Morris and Snoid, this afternoon to put in
a subsearch for the n-character overlapping target inside the match
loop. But this proved to complexify the code both conceptually and in
the sense that the target matcher had to contain extra instructions:
"do we have a potential overlap?" and "is it matching as well as the
main scan?"

Buys you nothing. You might as well check the left overlap in the next
cycle of the loop.

I believe I have possibly arrived at the most efficient solution
possible without auxiliary tables, because my solution appears to
examine pairs of characters the least amount of times needed. Wow. But
that's one of those beautiful theories forever being set upon by
ruffians in the form of facts.


In view of the face that NO OTHER POSTER (to my knowledge) has met the
requirements (code a string replace function without string.h usage) I
hereby declare victory, and award myself the Golden Spinoza Order of
Purity and Truth har har.

Seriously, I have demonstrated, I believe, that Republicans can't code
worth dick, but they can (if Peter Seebach is still a Republican) say
"there is a bug in my code but I'm fucked if I'll fix it", and they
sure can backstab and lie. That is: there is an entire programming
world-view, a Gestalt, that is complete malarkey and normalized
deviance. It consists of the inchoate saws and maxims that have
accumulated over time, that have sifted down from on-high from capable
early developers, but which have become little more than a cargo
cult.

My code is hard to read, it is said (on dit). In a sense, it is. I
find it hard to read at times myself.

An entire story exists in the cargo cult of the programmer who is in
some versions of the story "too clever by half" and in others only
thinks he is, and who writes an enormous program that nobody can
figure out. The social function of the story is to normalize
differences in ability, and to cover up the fact that many companies
try to solve ill-defined and very hard problems with computers, often
in order to exploit their workers or cheat customers. It omits the
existence of real code written by ordinary members of the white collar
proletariat which solved in an unsung fashion a hard problem...such as
the assembler for the 8K IBM 1401 that was written by a Univ of Chi
graduate student that put the IBM assembler to shame.

When looking for work in the 1990s, I answered an ad from Rockwell-
Wescom, a telecom manufacturer in Chicago. During my interview, the
manager said "some guy many years ago figured out how to use our call
data to reconstruct calls by simulating the PBX: he was pretty
strange." I said, "that was me". I'd become a legend of the dreamtime.
I didn't get a job because, the manager said, I was "too good to be
true". There had to be something wrong with a guy who'd solved a
problem nobody else could solve but was looking for work in his
forties.

Whereas at a shipping conference in 2003 I was greeted with
recognition by the staff of a shipbuilding firm for whom I'd created a
key program in the 1980s. This was because their culture was one of
openness and trust, not myth, and it's important that at the
conference, they said that they weren't bothering to bid for work in
Iraq. It was an ethical firm, of the sort that is in my experience
rare.

Code in some instance might look challenging because the problem is
actually a bit hard. Likewise it was hard for NASA engineers to solve
the problem of O-ring temperatures in cold temperatures in the
Challenger space shuttle, and later for them to solve the problem of
foam insulation dropping off Columbia at launch.

"They say it couldn't be done. So, I didn't do it."

In a post-Enlightenment culture of real science that has sifted down
to low-level technicians distinguished only by their conformity,
passive-aggression, frightened political conservatism (or passive-
aggressive "libertarianism") and/or religious Fundamentalism, the
former science (including Dijkstra's misinterpreted admonitions
concerning simplicity and "the humble programmer") become a cargo cult
of excuses for normalized deviance.

In a recent collection of writings on popular music by my fat pal
Theodore Adorno, he sets out the contrast starkly between classical
and popular music, and this is applicable to programming.

Popular music, he wrote, seems free and liberating, but in actuality
is almost always oversimplified in structure (and this is still true
of pop music years after he wrote it). The dissonances and syncopation
rely for their effect, he wrote, on the fact that for the listener
they are not actual artistic and standalone statements, but instead
sardonic POINTERS (references) back to classical music, light
classical music, and more traditional pop music.

The pop composer, even Irving Berlin or Copland, relies for his effect
on a backreference which says inside the music "listen, I flatted that
note, but you can if you like normalize my deviance by treating what I
said as unserious".

Consider the difference between Phillip Glass or Ygor Stravinsky on
the one hand, and Alban Berg on the other. The audience, according to
a 1980s Time magazine article about Glass, happily "sighed" when
Glass's cheap backreferences to the most innocuous classical music
with an easy-listening rock beat started to drone. Likewise, the
anxious bourgeois applauded Stravinsky (and Picasso) in the 1920s when
they reverted to classical models by means of snarky backreferences
with just enough dissonance to make the audience feel hip.

Whereas Beethoven meant to write the entire symphony in such a way
that ANY change would damage the whole (whereas my formatting and
naming conventions are not something I can willingly discard). (I
really felt for Tom Hulce's Amadeus in the eponymous movie when he was
told to discard notes by the Emperor).

That is, the division is between serious and unserious in programming
as well as music (PJ Plauger's phrase applies: programming on
purpose).

A Pop culture, a cargo cult and culture, creates people like Seebach,
who lie and backstab as standard procedure, allows them to claim that
the bad is good, by formulaic protocol-statements and shibboleths that
have the same function as dissonance in Pop music: saying "oh and by
the way I don't look for %s" is a gesture possible only in a culture
sodden with Pop crap created to make money.

This isn't to say that there couldn't be "serious" Pop music, such as
Robert Johnson's blues, which Adorno knew nothing about. But note that
Johnson wasn't commercially successful. Instead, rich men like Jagger
and McCartney stole what he did. Like Copland and Berlin, they relied
for their best effects on a form of plagiarism that mocks its source.

Tim Streater

unread,
Feb 13, 2010, 5:43:54 AM2/13/10
to
On 13/02/2010 10:30, spinoza1111 wrote:

> My code is hard to read, it is said (on dit). In a sense, it is. I
> find it hard to read at times myself.

Then it's shitty code, pure and simple.

--
Tim

"That the freedom of speech and debates or proceedings in Parliament
ought not to be impeached or questioned in any court or place out of
Parliament"

Bill of Rights 1689

io_x

unread,
Feb 13, 2010, 6:05:12 AM2/13/10
to

"spinoza1111" <spino...@yahoo.com> ha scritto nel messaggio
news:45109f35-05da-46a8...@p13g2000pre.googlegroups.com...

I can not be agree on your way of build test function
like a macro: that is indebuggable.
Macro for me are for build one language or for doing little
substitution like in "P" ---> "printf"

this is my propose: write only when find one error
--------------------------------
#define P printf
#define R return

// origin has to came from malloc memory
int tester(char* origin, char* whatSost, char* sost, char* expected)
{char *p;
unsigned len;
int i;

if(origin==0||whatSost==0||sost==0||expected==0)
R 0;
p=Replace(&len, origin, whatSost, sost);
if(p==0) R 0;
if(Strcmp(expected, p)!=0 || len!=Strlen(p))
{P("I find one error:\n");
P("Origin=%s|WhatS=%s|Sost=%s\n", origin, whatSost, sost);
P("Expect \"%s\":\nResult \"%s\"\n", expected, p);
P("lenResult=%u strlenResult=%u\n", len, Strlen(p));
Free(p);
R 0;
}
Free(p);
R 1;
}

// ---------------------------------------------------------------
// test for Replace() function
//
int test1(void)
{ unsigned r;
P("\n\nTest1\n");
r=1;
r*=tester("a stupid error","stupid error","miracle","a miracle");
r*=tester("a stupid error","stupid","miracle","a miracle error");
r*=tester("the stupid error","the stupid error","a miracle",
"a miracle");
r*=tester("the miracle","the","a","a miracle");
r*=tester("a miraclsnirpKamunkle","snirpKamunkle","e",
"a miracle");
r*=tester("a miraclesnirpKamunkle","a miracle",
"","snirpKamunkle");
r*=tester(" a miraclesnirpKamunkle","a miracle",
""," snirpKamunkle");
r*=tester(" a miraclesnirpKamunklea miraclea miracle","a miracle",
""," snirpKamunkle");
r*=tester("a miracle a miraclesnirpKamunkle a Miraclea miraclea miracle",
"a miracle",""," snirpKamunkle a Miracle");
r*=tester("a stupid errord","stupid error","miracle","a miracled");
r*=tester("a stupid errod","stupid error","miracle","a stupid errod");
r*=tester("a sstupid error","stupid error","miracle","a smiracle");
r*=tester("a stupid errorstupid error","stupid error","miracle",
"a miraclemiracle");
r*=tester("a stupid error stupiderror","stupid error","miracle",
"a miracle stupiderror");
r*=tester("bbbbbbbbbb","b","a","aaaaaaaaaa");
r*=tester("In the halls of R'yleh great %s lies dreaming","%s",
"Cthulu","In the halls of R'yleh great Cthulu lies dreaming");
r*=tester("%s%s%s%s%s%s","%s","Cthulu",
"CthuluCthuluCthuluCthuluCthuluCthulu");
r*=tester("banana","ana","oat","boatna");
r*=tester(" a stupid errorstupid errorHeystupid errors","stupid error",
"+"," a ++Hey+s");
r*=tester("foo barfoo barf","foo bar","bas","basbasf");
r*=tester("abab","ba","ba","abab");
r*=tester("a", "a", "b", "b");

if(r==0) {P("Test 1: Some error occurs\a\n\n"); R 0;}
else P("Test 1: Find No error\n\n");
R 1;
}


Richard Heathfield

unread,
Feb 13, 2010, 6:22:56 AM2/13/10
to
spinoza1111 wrote:
<snip>

I see you've ditched malloc.h, so here are my next two observations:

> // Calculate string length
> //
> //
> long strLength(char *strInstring)
> {
> char *ptrInstring;
> for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
> return ptrInstring - strInstring;
> }

Simpler, and slightly more informative to the caller:

long strLength(const char *s)
{
long len = 0;
while(*s++) ++len;
return len;
}

Other suggested improvements: (a) use an unsigned type, such as unsigned
long (strings might have 0 length, but they can never be negatively
long); and (b) drop the function completely, in favour of strlen.

<snip>

> if (!*strTarget)
> {
> printf("Error in calling replace(): target can't be null");
> abort();

If you intend this to be a general purpose solution, calling abort() is
not a good idea.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

spinoza1111

unread,
Feb 13, 2010, 6:53:01 AM2/13/10
to
On Feb 13, 6:43 pm, Tim Streater <timstrea...@waitrose.com> wrote:
> On 13/02/2010 10:30,spinoza1111wrote:

>
> > My code is hard to read, it is said (on dit). In a sense, it is. I
> > find it hard to read at times myself.
>
> Then it's shitty code, pure and simple.

That is the common view. I regard it as self-indulgent. Who says you
can read code?

spinoza1111

unread,
Feb 13, 2010, 7:20:19 AM2/13/10
to
On Feb 13, 7:22 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> spinoza1111wrote:

>
> <snip>
>
> I see you've ditched malloc.h, so here are my next two observations:

"When everything is ended, you come." - Shakespeare, Henry IV part 2

...dishonestly, like Falstaff, seeking glory. I find it hard to
believe that you've been keeping grave observations in reserve, since
you found no bugs, and would have been as my arch-enemy happy to do so
(stylistic observations about pseudo-portability don't count, and
there were several juicy bugs, none of which you were able to find).


>
> > // Calculate string length
> > //
> > //
> > long strLength(char *strInstring)
> > {
> >     char *ptrInstring;
> >     for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
> >     return ptrInstring - strInstring;
> > }
>
> Simpler, and slightly more informative to the caller:
>
> long strLength(const char *s)
> {
>    long len = 0;
>    while(*s++) ++len;
>    return len;
>
> }

I'm massively underwhelmed. It's "simpler" only in having fewer
characters in the source code, and this isn't what we mean by
simplicity; mathematics isn't "simple and readable" in the way we
want. Your code saves one assignment: I'll alert the media.

Integrating the increment of s with the test is what you would call
"confusing code" if anyone other than you'd written it, because you're
a narcissist. It defeats what purpose there is in the C for loop,
which was to disambiguate the three parts of a loop. It did so poorly,
but your use manages to make a bad situation worse.

If you can write "len", you can write "length". "len" could be
anything.

Initializing len in its declaration-definition will not even compile
on some C compilers. I thought you wrote portable code. Oh well.

OK, how many errors do we have in your code, if we use your own thug's
standard for errors as "I don't like it?"

Three.


>
> Other suggested improvements: (a) use an unsigned type, such as unsigned
> long (strings might have 0 length, but they can never be negatively
> long); and (b) drop the function completely, in favour of strlen.

Oh, I dunno. Some strings of nonsense (such as yours) should never
have been typed and have what we might call negative entropy, and we
could represent this as a negative string length.

>
> <snip>
>
> >     if (!*strTarget)
> >     {
> >         printf("Error in calling replace(): target can't be null");
> >         abort();
>
> If you intend this to be a general purpose solution, calling abort() is
> not a good idea.

Yes. Monkey and typewriter, but yes. However, you may have noticed if
you were awake that the code is "packaged" as a proof of concept (the
concept being "writing a replace even outside the string library is
not rocket science, but it is too hard for Republicans and Limey
sods").

And Lo! Heathfield labors mightily to stay inside the Game:
But the combat is already over, to each side's shame or fame:
The shadows lengthen on the pitch, he cries play up for me
And so the Combatants turn once more to their game of reading C.
The crowd is hush'd, and expectant Pall falls upon one and all
And then the mighty Heathfield upon the Gods doth cry his call
And show us his solution, alas, 'tis...Trivi-all.
He's missed the point, the boat, the bus, and the London train
If this were not so funny it would give the Gentle pain:
He's rolled offside off the Pitch and onto the green grass
To tell me how to write a string length function, Lord, what an Ass!
In tones of grave and pompous Preaching he groans Admonishment:
Expecting us his Flock to receive him with Astonishment:
But alas in the remains of a day so drear there is silence in the
Crowd:
And then a Titter, then a Chortle, third a Guf-faw, then both long and
Loud
Resounds the Laughter of the Gods which dismays all Philistines
From Hill, to Dale, to Glen, to Pale, are hearden its load Screams:
And so it is, and was, and ever it shall be cried
That Heathfield has struck out and has kicked the ball, offside.

Oh, that was Lofty.

Richard

unread,
Feb 13, 2010, 7:23:23 AM2/13/10
to
Tim Streater <timst...@waitrose.com> writes:

> On 13/02/2010 10:30, spinoza1111 wrote:
>
>> My code is hard to read, it is said (on dit). In a sense, it is. I
>> find it hard to read at times myself.
>
> Then it's shitty code, pure and simple.

Some of the best code I have dealt with turned out to need a while to
acclimatise to.

One should NEVER program to the lowest common denominator such as Bill
Cunningham for example.

There appears to be some strange opinion here that ALL code is
constantly being read by hundreds of people as the brilliance of your
output is ported and modded to 1000s of platforms and new projects. It
isn't. Far better to have a small routine complex but EFFICIENT that
"easy to read" and a dog. Complex? Comment it.

--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c

Richard

unread,
Feb 13, 2010, 7:18:06 AM2/13/10
to
Richard Heathfield <r...@see.sig.invalid> writes:

> spinoza1111 wrote:
> <snip>
>
> I see you've ditched malloc.h, so here are my next two observations:
>
>> // Calculate string length
>> //
>> //
>> long strLength(char *strInstring)
>> {
>> char *ptrInstring;
>> for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
>> return ptrInstring - strInstring;
>> }
>
> Simpler, and slightly more informative to the caller:
>
> long strLength(const char *s)
> {
> long len = 0;
> while(*s++) ++len;
> return len;
> }

An unnecessary increment on every loop. Potentially expensive for long
blocks. Nilges might be faster in many cases.

spinoza1111

unread,
Feb 13, 2010, 7:35:07 AM2/13/10
to
On Feb 13, 8:18 pm, Richard <rgrd...@gmail.com> wrote:
> Richard Heathfield <r...@see.sig.invalid> writes:
> >spinoza1111wrote:

> > <snip>
>
> > I see you've ditched malloc.h, so here are my next two observations:
>
> >> // Calculate string length
> >> //
> >> //
> >> long strLength(char *strInstring)
> >> {
> >>     char *ptrInstring;
> >>     for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
> >>     return ptrInstring - strInstring;
> >> }
>
> > Simpler, and slightly more informative to the caller:
>
> > long strLength(const char *s)
> > {
> >    long len = 0;
> >    while(*s++) ++len;
> >    return len;
> > }
>
> An unnecessary increment on every loop. Potentially expensive for long
> blocks. Nilges might be faster in many cases.

Whoa, missed that. Thanks for pointing this out. The count is four.
There is no joy, I am certain, in Mudville.

spinoza1111

unread,
Feb 13, 2010, 7:39:24 AM2/13/10
to
On Feb 13, 8:23 pm, Richard <rgrd...@gmail.com> wrote:
> Tim Streater <timstrea...@waitrose.com> writes:
> > On 13/02/2010 10:30,spinoza1111wrote:

>
> >> My code is hard to read, it is said (on dit). In a sense, it is. I
> >> find it hard to read at times myself.
>
> > Then it's shitty code, pure and simple.
>
> Some of the best code I have dealt with turned out to need a while to
> acclimatise to.
>
> One should NEVER program to the lowest common denominator such as Bill
> Cunningham for example.
>
> There appears to be some strange opinion here that ALL code is
> constantly being read by hundreds of people as the brilliance of your
> output is ported and modded to 1000s of platforms and new projects. It
> isn't. Far better to have a small routine complex but EFFICIENT that
> "easy to read" and a dog. Complex? Comment it.

"Wisdom crieth without; she uttereth her voice in the streets: She
crieth in the chief place of concourse, in the openings of the gates:
in the city she uttereth her words, saying, How long, ye simple ones,
will ye love simplicity?"

spinoza1111

unread,
Feb 13, 2010, 7:59:36 AM2/13/10
to

Looking over some of the other "solutions" to the problem, I note that
some use memcpy unnecessarily.

Whereas here is what I do when I need to create a segment block:

if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;
ptrSegmentStruct->ptrNext = 0;

Not being burdened with "tools" like memcpy that in many ways want to
think for me, I here am as slick as I can be, for I insert a pointer
to the segment start and its length, whereas other alternate solutions
might do extra mem copies, perhaps into the structure, because "it is
good to use tools and unsafe to reinvent the wheel" and other nursery
maxims of the programming cargo cult.

Of course, to cash-out the final string, we do have to do memory
moves:

for (ptrIndex1 = ptrSegmentStruct->strSegment,
lngCount = 0;
lngCount < ptrSegmentStruct->lngSegmentLength;
ptrIndex1++, lngCount++, strNew++)
*strNew = *ptrIndex1;
if (ptrSegmentStruct->ptrNext
||
ptrIndex2 != 0 && !*ptrIndex2)
for (ptrIndex1 = strReplacement;
*ptrIndex1;
ptrIndex1++, ++strNew)
*strNew = *ptrIndex1;

Oh I didn't use memcpy. Hey wait a minute, did I remember to put a Nul
at the end?

Whew:

*strNew = '\0';
return strNewStart;

In fact, if you have my structure and the replacement string, this
data assembly constitutes a virtual new string which in a large and
integrated program could become a space-saving way to represent a
class of similar strings.

Note that while purporting to do our thinking for us, "tools" let us
down (an English officer in September 1914 defined a "battle" as "that
which takes place at the juncture of two different maps"). memcpy
could lull us into forgetting to add the Nul. Not using it keeps us
awake. More generally, "reinventing the wheel" defines us as men, homo
faber, and are we not men.

spinoza1111

unread,
Feb 13, 2010, 8:35:55 AM2/13/10
to
On Feb 13, 6:43 pm, Tim Streater <timstrea...@waitrose.com> wrote:
> On 13/02/2010 10:30,spinoza1111wrote:
>
> > My code is hard to read, it is said (on dit). In a sense, it is. I
> > find it hard to read at times myself.
>
> Then it's shitty code, pure and simple.

He had bought a large map representing the sea,
Without the least vestige of land:
And the crew were much pleased when they found it to be
A map they could all understand.

"What's the good of Mercator's North Poles and Equators,
Tropics, Zones, and Meridian Lines?"
So the Bellman would cry: and the crew would reply
"They are merely conventional signs!

"Other maps are such shapes, with their islands and capes!
But we've got our brave Captain to thank:"
(So the crew would protest) "that he's bought us the best--
A perfect and absolute blank!"

(Lewis Carroll, The Hunting of the Snark)

Tim Streater

unread,
Feb 13, 2010, 9:21:55 AM2/13/10
to
On 13/02/2010 11:53, spinoza1111 wrote:
> On Feb 13, 6:43 pm, Tim Streater<timstrea...@waitrose.com> wrote:
>> On 13/02/2010 10:30,spinoza1111wrote:
>>
>>> My code is hard to read, it is said (on dit). In a sense, it is. I
>>> find it hard to read at times myself.
>>
>> Then it's shitty code, pure and simple.
>
> That is the common view. I regard it as self-indulgent. Who says you
> can read code?

The fact that I can write it. The fact that I am (purely for my own
amusement) nearly done with writing an e-mail user-agent (not in C and
not likely to be seen off my own Mac). The fact that at SLAC more than
20 years ago, I wrote a software package (30k lines of C) to control and
gather statistics from a number of similar digital switches, running on
a MicroVAX. Some parts of the code ran on other VAXes (VMS) and IBM
mainframes under VM/CMS.

To do this we:

1) Used the Xerox suite of network protocols (IP not then being in the
ascendency).

2) Adapted a commercial threads microkernel (written in C) to run under
VMS and VM/CMS (note: we had no portability issues with the C). We had
to write a small amount of assembler for each host type (and fix a
number of bugs we found inside VM/CMS, mostly to do with timer handling).

Note also that all the C code written for this project was re-entrant (a
feature heavily used in the project). And we had no problems with that
either.

I could also throw in the assets database and associated front end (not
written in C) done at my last employer before retiring, but I can't be
bothered.

I might also point out that I was with each of my three employers for 15
years and left each voluntarily.

So, all in all, I think it can be said that I can read code.

Seebs

unread,
Feb 13, 2010, 11:21:24 AM2/13/10
to
On 2010-02-13, Tim Streater <timst...@waitrose.com> wrote:
> On 13/02/2010 10:30, spinoza1111 wrote:
>> My code is hard to read, it is said (on dit). In a sense, it is. I
>> find it hard to read at times myself.

> Then it's shitty code, pure and simple.

Pretty much. Why did multiple attempts at getting the Nilges string
replacement code debugged fail after hours of effort? Because it was hard
to read. Code which is hard to read is hard to maintain. Code which is
hard to maintain will start buggy. It will remain buggy despite debugging
efforts. It will become buggy whenever feature work needs to be done.

This ties in some to the debate about "software engineering". What would
people think of someone who claimed to be an "engineer", but who designed
bridges so elaborately complicated that no one could figure out which parts
were load-bearing?

This is why I don't take Nilges seriously when he rants about the design
of C. He's demonstrated conclusively that he has no clue about competent
design, and someone who can't build even simple programs correctly is not
qualified to comment on any programming language.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net

spinoza1111

unread,
Feb 13, 2010, 12:22:35 PM2/13/10
to
On Feb 14, 12:21 am, Seebs <usenet-nos...@seebs.net> wrote:

> On 2010-02-13, Tim Streater <timstrea...@waitrose.com> wrote:
>
> > On 13/02/2010 10:30,spinoza1111wrote:
> >> My code is hard to read, it is said (on dit). In a sense, it is. I
> >> find it hard to read at times myself.
> > Then it's shitty code, pure and simple.
>
> Pretty much.  Why did multiple attempts at getting the Nilges string
> replacement code debugged fail after hours of effort?  Because it was hard

You're lying: the console output from the current version is at the
end of this response. Also, the next time you start a thread using the
word "efficiency", use a dictionary.

You and Richard Heathfield need to LEAVE. This is because you both
have a track record of LYING in this and other newsgroups because you
are using them DISHONESTLY to advance yourself in a profession for
which you are not qualified.

> to read.  Code which is hard to read is hard to maintain.  Code which is
> hard to maintain will start buggy.  It will remain buggy despite debugging
> efforts.  It will become buggy whenever feature work needs to be done.
>
> This ties in some to the debate about "software engineering".  What would
> people think of someone who claimed to be an "engineer", but who designed
> bridges so elaborately complicated that no one could figure out which parts
> were load-bearing?

I don't claim to be an engineer. Do you, oh finder and sender on of
bugs who could not find the bugs in my code? If I were your manager, I
would in fact be very concerned that you could not do so when to do so
would have scored the points you so pathetically try to score here.

Software engineering is "how to program if you cannot", as Dijkstra
has said. You might need it. I don't. But you are by no stretch of the
imagination, an "engineer". Real engineers don't lie, because in
genuine engineering jobs, as opposed to computing jobs which in many
cases constitute welfare for white males, you lie like you do, you GO
TO JAIL.

>
> This is why I don't take Nilges seriously when he rants about the design
> of C.  He's demonstrated conclusively that he has no clue about competent
> design, and someone who can't build even simple programs correctly is not
> qualified to comment on any programming language.

You're lying. This thread in fact makes me very glad that I am no
longer a programmer, for commencing with the election of Reagan, I saw
the entry of people like you destroy workgroups and companies. I saw
the hiring of unqualified people (some with psychology in place of
compsci degrees, and, worse, zero interest in autodidactic computer
science) destroy the Mountain View site of Bell Northern Research.
Structured walkthroughs became savage and inane by turns, unqualified
people took trips and junkets, and around Christmas of 1985, while I
was working late on a 24 bit version of the SL.1 compiler, a holiday
party in another part of the building was ending in property damage
and drunken fistfights.

I saw people like you (including self-hating homosexuals) destroy
Catapult Software Training's Chicago office with your type of lies, as
well.

For let us not speak falsely now the hour is much too late.

You're lying. The code I posted and in which I have fixed all problems
reported to date has worked better than anything you've posted, and
YOU NEVER FIXED the %s bug that was in the code that started this
discussion! The other code samples you posted contained bugs, but your
rule seems to be "my mistakes must be forgiven, the 'heap' is a DOS
term, but if anyone I don't like, or need to ass-kiss, makes a
mistake, I'll be on his errors like a fly on shit".

Anyone here can go to the code a few posts above and download it,
compile and run it to get the following console output to verify that
you are lying, as you lied maliciously and libelously about Herb
Schildt, damaging his reputation in order to create a dishonest
impression that you are a qualified programmer, which YOU ARE NOT.

I have carefully documented how the Google Groups browser may make
minor modifications which a competent technician, WHICH YOU ARE NOT,
can fix them. Whereas you created a new thread, misspelling its title,
that started with a lie and here, continues with a lie. The code you
posted is crap and doesn't solve the problem which was to do the
replace() without using string.h.

You talk about "software quality" in the corporate register which must
of necessity take ownership of the term while not ever admitting that
the speaker-writer may not know his ass from a hole in the ground.
This is the register of people who do not know their trade and who are
complete frauds.

Whereas I am discussing a real programming problem, and working with
the real professionals here, like Ike Naar, Santosh, IO_x, and
Bacarisse, I have been able AS INTENDED to debug collaboratively
showing twerps like you (who isn't, apparently, trusted to actually
code real software at his job) how it's done. I've got the code into
the state it's in, no thanks to you, where it does, I believe, the
minimal amount of work without requiring the tables that more advanced
algorithms require.

This display of competence and professionalism, by someone returning
to C after almost 20 years, along with the competence and
professionalism of Naar, Santosh, et al., has exposed you and you are
lashing out with lies, Lash Larue.

The jig is up.


Replace


Replace "%s" by "Cthulu" in "In the halls of R'yleh great %s lies
dreaming"
Expect "In the halls of R'yleh great Cthulu lies dreaming":


"In the halls of R'yleh great Cthulu lies dreaming"

Replacements expected: 1: replacements: 1


Replace "%s" by "Cthulu" in "%s%s%s%s%s%s"
Expect "CthuluCthuluCthuluCthuluCthuluCthulu":
"CthuluCthuluCthuluCthuluCthuluCthulu"
Replacements expected: 6: replacements: 6


Replace "ana" by "oat" in "banana"
Expect "boatna":
"boatna"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "+" in " a stupid errorstupid errorHeystupid
errors"

spinoza1111

unread,
Feb 13, 2010, 12:36:34 PM2/13/10
to
On Feb 13, 10:21 pm, Tim Streater <timstrea...@waitrose.com> wrote:
> On 13/02/2010 11:53,spinoza1111wrote:

Doesn't follow, at all. In fact, many programmers have attention-
hyperactivity disorder that makes them prefer to write new code rather
than make the longer, more focused, and more empathic effort to read,
tolerate, connect-with and finally understand The Code of the Other.

When I started in programming, in fact, I was struck by the sheer
number of nervous disorders and tics of my coworkers, although they
were a refreshing change of pace from my own. I was especially struck
by how many programmers seemed to have math anxiety. I taught a C
class in 1990: one commenter said "he uses too much math", which was
just nuts if you ask me.

Most famously Larry Ellison, the CEO of Oracle, had by his own account
AHD and by his own account succeeded at a famously difficult Fortran
class at the University of Illinois because as opposed to other
"boring" classes, he could focus for short but sharp amounts of time
on writing new code, which then as now is the focus in university
programming courses. I had the same experience at roughly the same
time, writing a bug free machine language program as my first program
ever on a freezing night at Northwestern's library.

But I found it harder to tolerate The Code of the Other, in my case
because the first Code of the Other I encountered was genuinely poor
code. I had to cultivate the skill at Bell Northern Research where I
inherited a mass of compilers and tools, that were written by
extremely bright people in Ottawa (celebrated in a book, now out of
print, called Knights of the New Technology).

This is why I have always been skeptical of the unprovable claim that
code (or English text) is "hard to read", which is phrased as an
innate property of the text, and not of the relation of the reader to
the text. It is based on a primitive, lower middle class, almost
magical "theory" of the text in which the text, like the Bible of the
fundamentalist, must give a singular answer, in the style and
shibboleths of the reader, and if it does not, then it's the author's
fault.

In fine, I really don't care that you've been a faithful employee of
three firms and written a lotta code. That may be admirable, and
thanks for sharing, but it doesn't make you an authority on software
readability.

Message has been deleted

Ben Bacarisse

unread,
Feb 13, 2010, 12:59:01 PM2/13/10
to
Richard <rgr...@gmail.com> writes:

> Tim Streater <timst...@waitrose.com> writes:
>
>> On 13/02/2010 10:30, spinoza1111 wrote:
>>
>>> My code is hard to read, it is said (on dit). In a sense, it is. I
>>> find it hard to read at times myself.
>>
>> Then it's shitty code, pure and simple.
>
> Some of the best code I have dealt with turned out to need a while to
> acclimatise to.
>
> One should NEVER program to the lowest common denominator such as Bill
> Cunningham for example.
>
> There appears to be some strange opinion here that ALL code is
> constantly being read by hundreds of people as the brilliance of your
> output is ported and modded to 1000s of platforms and new projects. It
> isn't. Far better to have a small routine complex but EFFICIENT that
> "easy to read" and a dog. Complex? Comment it.

All code has at least one important reader -- the author. What odds
do you give that version 11 of this code (if I've counted correctly) is
finally bug free?

--
Ben.

Richard Heathfield

unread,
Feb 13, 2010, 1:15:17 PM2/13/10
to
spinoza1111 wrote:
> On Feb 13, 7:22 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>> spinoza1111wrote:
>>
>> <snip>
>>
>> I see you've ditched malloc.h, so here are my next two observations:
>
> "When everything is ended, you come." - Shakespeare, Henry IV part 2

Yeah. And at *this* point, when you think you've fixed it all up just
so, it's still easy to suggest improvements in your code.

>
> ....dishonestly, like Falstaff, seeking glory.

The glory involved in pointing out improvements in your code is about at
the same level as the glory involved in peeling a banana.

> I find it hard to
> believe that you've been keeping grave observations in reserve,

And indeed I haven't. When I saw a copy of the code that demonstrated
you'd learned from my first observation, I looked at the code
sufficiently closely to find a couple more observations. If you show any
sign of learning from those, I'll offer some more. But I don't save them
up. Experience teaches me that you are not a quick learner.

> since you found no bugs,

I haven't looked yet.

> and would have been as my arch-enemy

I'm not your arch-enemy. You are.

> happy to do so
> (stylistic observations about pseudo-portability don't count, and
> there were several juicy bugs, none of which you were able to find).

<shrug> I didn't look.

Now let's see if you were paying attention.

>>> // Calculate string length
>>> //
>>> //
>>> long strLength(char *strInstring)
>>> {
>>> char *ptrInstring;
>>> for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
>>> return ptrInstring - strInstring;
>>> }
>> Simpler, and slightly more informative to the caller:
>>
>> long strLength(const char *s)
>> {
>> long len = 0;
>> while(*s++) ++len;
>> return len;
>>
>> }
>
> I'm massively underwhelmed.

Yeah, I know.


> It's "simpler" only in having fewer
> characters in the source code,

I should have realised that its lack of verbosity would appear to you to
be a weakness rather than a strength.


> and this isn't what we mean by
> simplicity; mathematics isn't "simple and readable" in the way we
> want. Your code saves one assignment: I'll alert the media.

Good programming is made up of many good decisions.

> Integrating the increment of s with the test is what you would call
> "confusing code" if anyone other than you'd written it,

No, it's a standard C idiom. You'll find it in K&R, for example.

> because you're a narcissist.

Ah, you've been taught another new word. Here's yet another: projection.

> It defeats what purpose there is in the C for loop,
> which was to disambiguate the three parts of a loop. It did so poorly,
> but your use manages to make a bad situation worse.

But I didn't even use a for loop! It's not necessary here.

> If you can write "len", you can write "length". "len" could be
> anything.

It could, for example, be length.

> Initializing len in its declaration-definition will not even compile
> on some C compilers.

Rubbish. Any conforming implementation is required to support
initialisation syntax.

> I thought you wrote portable code. Oh well.

I do. You don't know what it means.

<nonsense snipped>

Richard Heathfield

unread,
Feb 13, 2010, 1:17:35 PM2/13/10
to
spinoza1111 wrote:
> On Feb 13, 8:18 pm, Richard <rgrd...@gmail.com> wrote:
>> Richard Heathfield <r...@see.sig.invalid> writes:
>>> spinoza1111wrote:
>>> <snip>
>>> I see you've ditched malloc.h, so here are my next two observations:
>>>> // Calculate string length
>>>> //
>>>> //
>>>> long strLength(char *strInstring)
>>>> {
>>>> char *ptrInstring;
>>>> for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
>>>> return ptrInstring - strInstring;
>>>> }
>>> Simpler, and slightly more informative to the caller:
>>> long strLength(const char *s)
>>> {
>>> long len = 0;
>>> while(*s++) ++len;
>>> return len;
>>> }
>> An unnecessary increment on every loop. Potentially expensive for long
>> blocks. Nilges might be faster in many cases.
>
> Whoa, missed that.

You also missed my advice (upthread) to ditch the function completely
and use the standard library, which will wipe the floor with both versions.

> Thanks for pointing this out. The count is four.

Don't believe everything you read.

Richard Heathfield

unread,
Feb 13, 2010, 1:21:04 PM2/13/10
to
Tim Streater wrote:
> On 13/02/2010 11:53, spinoza1111 wrote:
>> On Feb 13, 6:43 pm, Tim Streater<timstrea...@waitrose.com> wrote:
>>> On 13/02/2010 10:30,spinoza1111wrote:
>>>
>>>> My code is hard to read, it is said (on dit). In a sense, it is. I
>>>> find it hard to read at times myself.
>>>
>>> Then it's shitty code, pure and simple.
>>
>> That is the common view. I regard it as self-indulgent. Who says you
>> can read code?
>
> The fact that I can write it.

I doubt whether anyone would question it, other than spinoza1111 and the
trolls, and their opinion is of no moment.

<snip>

Seebs

unread,
Feb 13, 2010, 1:17:06 PM2/13/10
to
On 2010-02-13, Ben Bacarisse <ben.u...@bsb.me.uk> wrote:

> Richard <rgr...@gmail.com> writes:
>> There appears to be some strange opinion here that ALL code is
>> constantly being read by hundreds of people as the brilliance of your
>> output is ported and modded to 1000s of platforms and new projects. It
>> isn't. Far better to have a small routine complex but EFFICIENT that
>> "easy to read" and a dog. Complex? Comment it.

> All code has at least one important reader -- the author. What odds
> do you give that version 11 of this code (if I've counted correctly) is
> finally bug free?

The assumption that efficient code must be hard to read, or that efficiency
is likely to make code hard to read, is unsupported.

The problem with the Nilges string replace program is largely that the design
is gratuitously complicated. However, simply choosing remotely reasonable
names for the ptrIndex* variables would probably have addressed a great deal
of it. If you're constantly flipping back to see what something points to,
that suggests that you're doing it wrong.

Furthermore, the performance of his algorithm is likely to be unbelievably
bad, because on most systems, the overhead of malloc/free pairs is noticably
larger than the overhead of searching an entire string several times. So it's
not even actually efficient.

In general, you should write things for clarity first. Once you have
something which clearly works and is well-understood and tested, THEN it
is time to start thinking about such questions as "is it fast enough". If
not, then you profile to find out where the time goes. THEN you see whether
it's time to rewrite something.

But even if you're writing for efficiency, it's not usually necessary to
write unclear code. Contrary to popular belief, the execution time of code
is not harmed by indentation, decent variable naming conventions, or the
like. On modern compilers, intermediate variables are likely free too, so
writing for clarity by, say, giving a name to a particular intermediate
value, doesn't usually hurt performance.

As is usually the case, "Richard" (no last name) is apparently trolling,
stupid, or both.

Seebs

unread,
Feb 13, 2010, 1:19:56 PM2/13/10
to
On 2010-02-13, Richard Heathfield <r...@see.sig.invalid> wrote:
> spinoza1111 wrote:
>> On Feb 13, 8:18 pm, Richard <rgrd...@gmail.com> wrote:
>>> Richard Heathfield <r...@see.sig.invalid> writes:
>>>> Simpler, and slightly more informative to the caller:
>>>> long strLength(const char *s)
>>>> {
>>>> long len = 0;
>>>> while(*s++) ++len;
>>>> return len;
>>>> }

>>> An unnecessary increment on every loop. Potentially expensive for long
>>> blocks. Nilges might be faster in many cases.

>> Whoa, missed that.

> You also missed my advice (upthread) to ditch the function completely
> and use the standard library, which will wipe the floor with both versions.

Typically, yes.

That said, I do like the idiom
size_t lenstr(char *string) {
char *end = string;
while (*end++)
;
return end - string;
}

Not that it's likely to make a noticeable difference. Or that it's likely
worth it when obviously the standard library one will be fine.

Richard Heathfield

unread,
Feb 13, 2010, 1:25:55 PM2/13/10
to
Stefan Ram wrote:
> Richard Heathfield <r...@see.sig.invalid> writes:
>> long strLength(const char *s)
>
> ISO C 90 might contain a provision stating that:
>
> �The implementation may further restrict the
> significance of an external name (an identifier that has
> external linkage) to six characters and may ignore
> distinctions of alphabetical case for such names�.
>
> (This text was copied from a draft, but I remember
> having read this in the ANSI document, too.)

Yes, it's a lousy name. And it's a lousy function, too. He needs strlen.
He's just too stupid to realise it.

Keith Thompson

unread,
Feb 13, 2010, 3:09:47 PM2/13/10
to
Seebs <usenet...@seebs.net> writes:
[...]

> That said, I do like the idiom
> size_t lenstr(char *string) {
> char *end = string;
> while (*end++)
> ;
> return end - string;
> }
>
> Not that it's likely to make a noticeable difference. Or that it's likely
> worth it when obviously the standard library one will be fine.

Note that ``end - string'' yields a value of type ptrdiff_t, a signed
type which very likely can't represent all values of type size_t.

This is unlikely to be an issue in practice. On typical 32-bit
systems, problems show up only for strings longer than 2 gigabytes,
and even then the properties of 2's-complement arithmetic are likely
to result in the correct answer anyway.

But all this analysis, resulting in the conclusion that it will
almost certainly work properly, becomes unnecessary if you just
use strlen().

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Phil Carmody

unread,
Feb 13, 2010, 6:03:31 PM2/13/10
to
Seebs <usenet...@seebs.net> writes:
> On 2010-02-13, Richard Heathfield <r...@see.sig.invalid> wrote:
>> spinoza1111 wrote:
>>> On Feb 13, 8:18 pm, Richard <rgrd...@gmail.com> wrote:
>>>> Richard Heathfield <r...@see.sig.invalid> writes:
>>>>> Simpler, and slightly more informative to the caller:
>>>>> long strLength(const char *s)
>>>>> {
>>>>> long len = 0;
>>>>> while(*s++) ++len;
>>>>> return len;
>>>>> }
>>>> An unnecessary increment on every loop. Potentially expensive for long
>>>> blocks. Nilges might be faster in many cases.
>
>>> Whoa, missed that.
>
>> You also missed my advice (upthread) to ditch the function completely
>> and use the standard library, which will wipe the floor with both versions.
>
> Typically, yes.
>
> That said, I do like the idiom
> size_t lenstr(char *string) {
> char *end = string;
> while (*end++)
> ;
> return end - string;
> }
>
> Not that it's likely to make a noticeable difference. Or that it's likely
> worth it when obviously the standard library one will be fine.

You ran straight into the fencepost. And can we have more const,
pretty please?

Phil, who uses strlen().
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1

Richard Harter

unread,
Feb 13, 2010, 6:05:12 PM2/13/10
to
On Sat, 13 Feb 2010 01:25:27 -0800 (PST), spinoza1111
<spino...@yahoo.com> wrote:

>On Feb 13, 2:46=A0am, spinoza1111 <spinoza1...@yahoo.com> wrote:
>...code...
>
>I noticed that in the latest (13 Feb) version of the code, with the
>fix to the one-character replace found by Ben B, there were some file
>nits: two long lines split and blanks at end of continued macro lines.
>
>Let's see if I can get rid of these problems.
>
>Also, I misspoke. The failure to handle Ben's example was caused by an
>earlier change.
>
>Here is the latest code, without the console output.
>

I have no particular interest in this programming challenge,
though I do find some of the commentary amusing. I thought it
might be of interest to do a code review. The following is not
an endorsement or a condemnation of the code. Rather it is an
informal account of code features that are problematic.

Notes on the Nilges code:

(1) At no point is there a comprehensive specification. A fair
number of corner cases are left up in the air. These include
overlapping targets, and empty targets. There is no statement
of error handling strategy.

(2) There are instances of failure to protect against
dereferencing null pointers. Thus in function strLength the for
loop will dereference a null pointer if argument strInstring is
a null pointer. Similarly function replace checks strTarget but
not strMaster. ptrIndex1 is initialized to strMaster. The
while loop, while(*ptrIndex1), will dereference a null pointer
if strMaster is null.

The test cases do not check for null arguments nor all instances
of empty strings.

(3) The TESTER macro is cumbersome and should be replaced by a
function.

(4) It would be better if the test cases were moved to a
separate file - the plan would be for the main function to read
the test cases from from the test cases file and then compare
the actual test results with the expected test results.

(5) The comments are inadequate. The existing comments read
more like coding notes written on the spur of the moment to
remind the coder about what was going on. There is no statement
of the algorithm being used; the comments often reference
concepts that are not explained. For example, there is no
precise definition of segment nor of handle.

(6) The commenting format is not well chosen. The comments
break into the code and vice versa.

(7) The code author uses a bizarre, idiosyncratic, and long
winded variant of Hungarian notation. It's his privilege.
Unfortunately the long names used are not informative. For
example, the ptrIndex* variables. What on earth are they, and
what are their invariants? The only way to know what they are
is play computer, walk through the code, and reconstruct what
the coder's intent was.

Then there are the ptrSegmentStruct variables. One has a suffix
of Starts, one of Prev, and one is without a suffix. Since the
key idea of the implementation is to generate a linked list of
segments, each (except possibly the last) being terminated by
the target string, it turns out that the ptrSegmentStructStarts
refers to the list head, ptrSegmentStruct refers to the current
pointer into the list, and ptrSegmentStructPrev refers to the
previous pointer into the list. Or perhaps not.

(8) The scheme of allocating space for each segment is mildly
inefficient, but is much better than reallocing space for the
output string. In any case it is doubtful that execution
efficiency is among the objectives of this exercise.

(9) In some places the code is overly complex. A case in point
is:


lngNewLength += ptrSegmentStruct->lngSegmentLength +
(ptrIndex2 && !*ptrIndex2
?
lngReplacementLength
:
0);

There are several other instances of unnecessary complexity.
The updating of the never defined Index variables is a case in
point.

(10) Only one of strNew, strNewStart is needed.

(11) In conclusion, it is difficult to determine whether the
code works correctly because the design is not spelled out, the
variables are not properly documention, the testing framework is
inadequate, and the baroque nomeclature and coding complicate
analysis.

Richard Harter, c...@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
Infinity is one of those things that keep philosophers busy when they
could be more profitably spending their time weeding their garden.

Chris M. Thomasson

unread,
Feb 13, 2010, 6:23:29 PM2/13/10
to
"Seebs" <usenet...@seebs.net> wrote in message
news:slrnhndrhg.3ec...@guild.seebs.net...

[...]

> That said, I do like the idiom
> size_t lenstr(char *string) {
> char *end = string;
> while (*end++)
> ;
> return end - string;
> }
>
> Not that it's likely to make a noticeable difference. Or that it's likely
> worth it when obviously the standard library one will be fine.

I believe that you have a bug in that code Seebs. Perhaps you meant
something like this instead:
_____________________________________________________
size_t
xstrlen(char const* string)
{
char const* end = string;
while (*end) ++end;
return end - string;
}
_____________________________________________________


?

Seebs

unread,
Feb 13, 2010, 6:35:51 PM2/13/10
to
On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
> I believe that you have a bug in that code Seebs.

Extremely likely.

This is one of the reasons I rely on the standard library -- my success rate
in avoiding fencepost errors is slightly *less* than chance. I'm not actually
very good at this stuff, which is why I spend so much time thinking about how
to do it better.

bartc

unread,
Feb 13, 2010, 8:10:53 PM2/13/10
to

"Seebs" <usenet...@seebs.net> wrote in message
news:slrnhn628c.o3u...@guild.seebs.net...
> This may have gotten buried given that it started in a Nilges thread,
> but it's actually pretty interesting.
>
> There was some discussion of algorithms to perform the task:
> Inputs: target string, replacement string, original string
> Output: a newly-allocated string containing the original
> string with each copy of the target string replaced with the
> replacement string.
>
> Here's a hunk of mine:
>
> for (count = 0, t = strstr(target, in); t && *t; t = strstr(t, in))
> {
> ++count;
> t += inlen;
> }
>
> Here's a hunk of another one:
>
>> ptrIndex1 = strMaster;
>> while(*ptrIndex1)

>
> These hunks are essentially performing the same part of the core loop;
> find the next occurrence of the target string in the original string.

I've looked at both. The first is easier on the eye, but I still can't
figure out what it does. You say, it finds the *next* occurence of the
target, why a loop then?

> The second one was written by Edward Nilges ("spinoza1111"). He offers
> in its defense the assertion that it's the "best" algorithm. (Nevermind
> that it's got a bug; the bug could be fixed easily.)

You can't really compare these (assuming they really do do the same thing);
your code uses some presumably tried and tested library function (strstr) to
do the tricky part, so you're comparing a *call* to that function to an
experimental *implementation* of it. That doesn't sound fair..

> it is, before trying to optimize. You may, or may not, be able to
> outperform
> a given library's implementation of strstr().

The efficiency varies. On my lccwin32 and DMC compilers, the time to find an
"A" string, in a string consisting entirely of As, seems to depend on the
length of the string it's searching (perhaps it's doing a strlen() first?).
On gcc it's instant.

(I came across the problem in a related function strchr(), in Malcolm's
Minibasic program, where it had the effect, on large input files, of slowing
down the interpreter from 80K lines per second to about 2K. Replacing the
strchr() call with one line of custom code (I think it was just looking for
next EOL), fixed that.)

--
Bartc

Joe Wright

unread,
Feb 13, 2010, 8:40:12 PM2/13/10
to
Seebs wrote:
> On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
>> I believe that you have a bug in that code Seebs.
>
> Extremely likely.
>
> This is one of the reasons I rely on the standard library -- my success rate
> in avoiding fencepost errors is slightly *less* than chance. I'm not actually
> very good at this stuff, which is why I spend so much time thinking about how
> to do it better.
>
> -s

The humility is a good touch. You can use mine.

size_t Strlen(char *s)
{
size_t l = 0;
if (s) while (*s++) l++;
return l;
}

--
Joe Wright
"If you rob Peter to pay Paul you can depend on the support of Paul."

Seebs

unread,
Feb 13, 2010, 9:02:21 PM2/13/10
to
On 2010-02-14, bartc <ba...@freeuk.com> wrote:
> I've looked at both. The first is easier on the eye, but I still can't
> figure out what it does. You say, it finds the *next* occurence of the
> target, why a loop then?

Because it finds the next occurrence repeatedly until there's no more.

> You can't really compare these (assuming they really do do the same thing);
> your code uses some presumably tried and tested library function (strstr) to
> do the tricky part, so you're comparing a *call* to that function to an
> experimental *implementation* of it. That doesn't sound fair..

I think it's extremely fair, because it highlights the flaw in his "I
refuse to use the library functions" attitude.

Agreed that there are cases where there's reasons not to do that.

spinoza1111

unread,
Feb 13, 2010, 11:20:25 PM2/13/10
to
On Feb 14, 1:59 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

> Richard <rgrd...@gmail.com> writes:
> > Tim Streater <timstrea...@waitrose.com> writes:
>
> >> On 13/02/2010 10:30,spinoza1111wrote:
>
> >>> My code is hard to read, it is said (on dit). In a sense, it is. I
> >>> find it hard to read at times myself.
>
> >> Then it's shitty code, pure and simple.
>
> > Some of the best code I have dealt with turned out to need a while to
> > acclimatise to.
>
> > One should NEVER program to the lowest common denominator such as Bill
> > Cunningham for example.
>
> > There appears to be some strange opinion here that ALL code is
> > constantly being read by hundreds of people as the brilliance of your
> > output is ported and modded to 1000s of platforms and new projects. It
> > isn't. Far better to have a small routine complex but EFFICIENT that
> > "easy to read" and a dog. Complex? Comment it.
>
> All code has at least one important reader -- the author.  What odds
> do you give that version 11 of this code (if I've counted correctly) is
> finally bug free?

This isn't a game, Ben. We can play that stupid game with any code if
the game is to target people, Richard posted a technical foul with s+
+.

However, I am not going to waste your time arguing that my code is
"readable". It's not one I can win if you can't really read code and,
like most programmers I've met, are in fact underqualified. I don't
think you are, but I do think many people here are.

So perhaps the code is unreadable...to you.
>
> --
> Ben.

Phred Phungus

unread,
Feb 13, 2010, 11:37:08 PM2/13/10
to
Joe Wright wrote:
> Seebs wrote:
>> On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
>>> I believe that you have a bug in that code Seebs.
>>
>> Extremely likely.
>>
>> This is one of the reasons I rely on the standard library -- my
>> success rate
>> in avoiding fencepost errors is slightly *less* than chance. I'm not
>> actually
>> very good at this stuff, which is why I spend so much time thinking
>> about how
>> to do it better.
>>
>> -s
>
> The humility is a good touch. You can use mine.
>
> size_t Strlen(char *s)
> {
> size_t l = 0;
> if (s) while (*s++) l++;
> return l;
> }
>

So this is your home-rolled strlen?
--
fred

spinoza1111

unread,
Feb 13, 2010, 11:41:10 PM2/13/10
to
On Feb 14, 2:15 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> spinoza1111wrote:
> > On Feb 13, 7:22 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> >> spinoza1111wrote:
>
> >> <snip>
>
> >> I see you've ditched malloc.h, so here are my next two observations:
>
> > "When everything is ended, you come." - Shakespeare, Henry IV part 2
>
> Yeah. And at *this* point, when you think you've fixed it all up just
> so, it's still easy to suggest improvements in your code.
>
>
>
> > ....dishonestly, like Falstaff, seeking glory.
>
> The glory involved in pointing out improvements in your code is about at
> the same level as the glory involved in peeling a banana.

You have suggested no useful improvements.


>
> > I find it hard to
> > believe that you've been keeping grave observations in reserve,
>
> And indeed I haven't. When I saw a copy of the code that demonstrated
> you'd learned from my first observation, I looked at the code
> sufficiently closely to find a couple more observations. If you show any
> sign of learning from those, I'll offer some more. But I don't save them
> up. Experience teaches me that you are not a quick learner.

You're not a teacher. Your Maoist game is to replace teachers with
shouting and slogans. We've seen evidence of your deep incompetence
elsethread, for a programmer with a proper education in computer
science would NEVER copy unpredictable elements into a linked list; a
properly educated programmer would have used a linked list of
pointers. And yet you published this error, which is far more serious
than a typographical error or even a software bug, and far worse than
any of Schildt's typos.

>
>  > since you found no bugs,
>
> I haven't looked yet.

Lazy bastard, aren't you. Or perhaps the code is "unreadable" despite
all the work I've done? You know, I discovered a long time ago that
there are two types of people who like to call either texts or code
"unreadable":

* Stupid people employed at positions for which they are not, in
reality, qualified

* Criminals who find the law unreadable in hopes of copping a plea of
plausible deniability

>
>  > and would have been as my arch-enemy
>
> I'm not your arch-enemy. You are.

"He's his own worst enemy" is a bully's catchphrase.


>
> > happy to do so
> > (stylistic observations about pseudo-portability don't count, and
> > there were several juicy bugs, none of which you were able to find).
>
> <shrug> I didn't look.

<The Finger> So why are you commenting at all, not having done your
homework?


>
> Now let's see if you were paying attention.
>
>
>
>
>
> >>> // Calculate string length
> >>> //
> >>> //
> >>> long strLength(char *strInstring)
> >>> {
> >>>     char *ptrInstring;
> >>>     for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
> >>>     return ptrInstring - strInstring;
> >>> }
> >> Simpler, and slightly more informative to the caller:
>
> >> long strLength(const char *s)
> >> {
> >>    long len = 0;
> >>    while(*s++) ++len;
> >>    return len;
>
> >> }
>
> > I'm massively underwhelmed.
>
> Yeah, I know.
>
> > It's "simpler" only in having fewer
> > characters in the source code,
>
> I should have realised that its lack of verbosity would appear to you to
> be a weakness rather than a strength.
>
> > and this isn't what we mean by
> > simplicity; mathematics isn't "simple and readable" in the way we
> > want. Your code saves one assignment: I'll alert the media.
>
> Good programming is made up of many good decisions.

Incompetent programmers love nursery saws:
It saves them the agony of thought.
Incompetent programmers regress to childhood's laws
A land in which "is" becomes "ought".

>
> > Integrating the increment of s with the test is what you would call
> > "confusing code" if anyone other than you'd written it,
>
> No, it's a standard C idiom. You'll find it in K&R, for example.

Had C been a success as a programming language, an artifact not meant
to be a human language but instead to be at a midpoint between human
language and mathematical formalism, it wouldn't need idiomatic
expressions, and because of its idiotic idioms (including not only pre
and post increment and decrement but also sprintf) years later C was
exposed as unstandardizable and non-deterministic mess.

>
> > because you're a narcissist.
>
> Ah, you've been taught another new word. Here's yet another: projection.
>
> > It defeats what purpose there is in the C for loop,
> > which was to disambiguate the three parts of a loop. It did so poorly,
> > but your use manages to make a bad situation worse.
>
> But I didn't even use a for loop! It's not necessary here.

Yes, it is. Competent programmers do not use the while when the actual
problem is for-like:

* A for-like loop problem may be defined as one in which the
variables referenced in the loop are not changed by the loop
* A while-like loop problem may be defined as one in which they
change

You used a while when to express the underlying logic a competent
programmer (one interested in "readability" not to slobs but to other
competent programmers) would have used a for.

>
> > If you can write "len", you can write "length". "len" could be
> > anything.
>
> It could, for example, be length.

But it's not, Len.

>
> > Initializing len in its declaration-definition will not even compile
> > on some C compilers.
>
> Rubbish. Any conforming implementation is required to support
> initialisation syntax.

Here you go again with fraudulent talk, the sort of bullshit that will
land you in court. Because, of course, you know that there are
multiple standards.

>
>  > I thought you wrote portable code. Oh well.
>
> I do. You don't know what it means.

What an asshole. Your code can't be pasted and run into common older
implementations. When another's code fails this simple test, you
condemn their competence, but you're supposed to get away with this
shit.

spinoza1111

unread,
Feb 13, 2010, 11:43:50 PM2/13/10
to
On Feb 14, 2:17 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> spinoza1111wrote:
> > On Feb 13, 8:18 pm, Richard <rgrd...@gmail.com> wrote:
> >> Richard Heathfield <r...@see.sig.invalid> writes:
> >>> spinoza1111wrote:
> >>> <snip>
> >>> I see you've ditched malloc.h, so here are my next two observations:
> >>>> // Calculate string length
> >>>> //
> >>>> //
> >>>> long strLength(char *strInstring)
> >>>> {
> >>>>     char *ptrInstring;
> >>>>     for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
> >>>>     return ptrInstring - strInstring;
> >>>> }
> >>> Simpler, and slightly more informative to the caller:
> >>> long strLength(const char *s)
> >>> {
> >>>    long len = 0;
> >>>    while(*s++) ++len;
> >>>    return len;
> >>> }
> >> An unnecessary increment on every loop. Potentially expensive for long
> >> blocks. Nilges might be faster in many cases.
>
> > Whoa, missed that.
>
> You also missed my advice (upthread) to ditch the function completely
> and use the standard library, which will wipe the floor with both versions.

Another sign of incompetence you manifest is the unpleasant use of
anthropomorphic terminology to refer to the possibility that you will
use physical violence, from shoving to calling security to something
more serious, to win.

Joe Wright

unread,
Feb 14, 2010, 12:04:11 AM2/14/10
to

Yes Fred, it is. Note it is null pointer safe. Anything else?

spinoza1111

unread,
Feb 14, 2010, 12:45:54 AM2/14/10
to
On Feb 14, 2:17 am, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-13, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

>
> > Richard <rgrd...@gmail.com> writes:
> >> There appears to be some strange opinion here that ALL code is
> >> constantly being read by hundreds of people as the brilliance of your
> >> output is ported and modded to 1000s of platforms and new projects. It
> >> isn't. Far better to have a small routine complex but EFFICIENT that
> >> "easy to read" and a dog. Complex? Comment it.
> > All code has at least one important reader -- the author.  What odds
> > do you give that version 11 of this code (if I've counted correctly) is
> > finally bug free?
>
> The assumption that efficient code must be hard to read, or that efficiency
> is likely to make code hard to read, is unsupported.

Nobody's trying to be efficient. Instead, the goal was to produce, in
a language unfriendly towards encapsulation, an encapsulation. The
practical reason for this was actually to make it easy for a
participant in this discussion to execute some very basic steps so
that she or he could evaluate the code, and either find bugs or verify
that it worked for the accumulating range of test cases, leading to
agreement that the code will work for all cases in the absence of a
formal proof.

Of course, incompetent programmers (like you and Richard) prefer
"snippets" such as your initial example of how not to find %s. As in
Adorno's analysis of Pop music, the snippet *genre* allows you to
weasel out of your mistakes in the same way the conventions of Pop
music allow the musician to suck.

In more vivid terms, I'm conducting a symphony whereas you're a garage
band. It's easier for you to appear "correct" ... to morons. I might
sound like "the Depaul University Symphony" that used in the 1990s to
practice in a space in the old Woolworth's building; their version of
Beethoven's Seventh Symphony sounded like a crowd of musicians pursued
by a bear: but the fact remains, I'm doing something of a different,
and more difficult, *genre*, than your *genre*, which is that of the
corporate drone.

>
> The problem with the Nilges string replace program is largely that the design
> is gratuitously complicated.

We already know this. If you'd read Cormen's algorithms, you'd know
that "find and replace" is two separate problems that should ideally
be factored. However, in the so-called real world, this sort of
pragmatic problem occurs all the time: I can well imagine (having had
thirty years of experience) a situation which demands an unfactored
solution and the absence of string.h: stranger things have happened.

Applied computer science is an unsung and lonely business. Most
corporate "programmers" avoid it, preferring to sit around mocking
other people, because in fact, they are either (like you) uneducated
or poorly auto-didacted in comp sci, or educated in purely theoretical
matters.

Therefore, I set myself to solve the problem of "find and replace no
string.H" in response to your incompetent %s solution, and decided to
work collaboratively by submitting preliminary versions. Some of us
are unafraid of submitting preliminary versions and some of us fix
bugs, rather than mention them with a shit-eating grin as you did wrt
%s.

 
> However, simply choosing remotely reasonable
> names for the ptrIndex* variables would probably have addressed a great deal
> of it.  If you're constantly flipping back to see what something points to,
> that suggests that you're doing it wrong.

Actually, the naming convention makes a beautiful distinction between
unchanging string pointers and work pointers, if I do say so myself.
And I do.

>
> Furthermore, the performance of his algorithm is likely to be unbelievably
> bad, because on most systems, the overhead of malloc/free pairs is noticably
> larger than the overhead of searching an entire string several times.  So it's
> not even actually efficient.

You have no evidence for this, and you can't even reason about it
properly; characteristic of incompetent corporate programmers being
the irresponsible use of mathematical terminology without the ability
to do the math.

In fact, we segment the string in my solution into a linked list of
segments:

// ***** Segmentation *****
struct TYPsegmentstruct
{ char * strSegment;
long lngSegmentLength;
struct TYPsegmentstruct * ptrNext; };

Note on Nilges Magyar notation: TYP means "global to the compilation
unit because upper case AND a user-defined type". Instances of TYP are
USR if global or usr if local.

Where m is the number of matches there are in fact m mallocations and
m frees to create and destroy a linked list of segments between
matches. This may be a performance hit, but note that unlike the case
of Richard's "C Unleashed" solution (in which a linked list of
TYPlongAndHorrible can blow up), we can express the worst case
mathematically:

replace("xxxxx ... xxx", "x", "y")

We can then add this to our accumulating "data base" of test cases:

Replace "x" by "y" in "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Expect "yyyyyyyyyyyyyyyyyyyyyyyyyyyy":
"yyyyyyyyyyyyyyyyyyyyyyyyyyyy"
Replacements expected: 28: replacements: 28

We then step through the code for this instance to confirm a
performance bug: for the above example, 28 segments are created each
of zero length.

Although this bug is "only" performance-related, it is in fact a
showstopper for long strings. I'm obliged to you in a quantum/
infinitesimal sense, for you've drawn our attention to this issue,
puke face.

Its solution is elegant: it is to in some way mark the linked list to
show "a run of two or more zero-length segments occurs." The most
elegant way to do this is to sign TYPsegmentstruct.lngSegmentLength
negative.

It means that in the first loop, when we arrive at the malloc, we need
to:

* Check for a previous segment: this will be a nonzero
ptrSegmentStruct
* See if it has a zero or negative length
* If it does:
+ And if the latest segment is zero length, decrement
+ And the latest segment is not zero length, create a new zero
length segment
* If it doesn't, create a segment
* If no previous segment exists, create a segment
* In the assembly loop, skip all linked list nodes with zero or
negative segment lengths

I shall add this change. Your job is to ponder whether there's a risk
that this will add another bug, or whether this is itself buggy.

Oh Finder of Bugs at your day job,
Who can't find the bugs in this code,
Oh Misser of Bugs, oh Elmer, oh Fudd
I hope this isn't too much of a load.

Your garbage, in other words, can be useful in a structured
walkthrough chaired by someone, like me, who's not afraid of you.

Mock on, mock on, Voltaire, Rousseau;
Mock on, mock on; 'tis all in vain!
You throw the sand against the wind,
And the wind blows it back again.

William Blake

"Children are different. Garbage in, food out." - Ted Nelson

>
> In general, you should write things for clarity first.  Once you have
> something which clearly works and is well-understood and tested, THEN it
> is time to start thinking about such questions as "is it fast enough".  If
> not, then you profile to find out where the time goes.  THEN you see whether
> it's time to rewrite something.

Corporatese, for you have no clear idea of clarity apart from pure
phenomena which are private to you. What seems clear is clear. You are
not qualified to speak of mathematical clarity: you've given no
evidence of being able to do math (your ability to disrupt civilized
conversation about mathematics doesn't count).


>
> But even if you're writing for efficiency, it's not usually necessary to
> write unclear code.  Contrary to popular belief, the execution time of code
> is not harmed by indentation, decent variable naming conventions, or the
> like.  On modern compilers, intermediate variables are likely free too, so
> writing for clarity by, say, giving a name to a particular intermediate
> value, doesn't usually hurt performance.
>
> As is usually the case, "Richard" (no last name) is apparently trolling,
> stupid, or both.

And note how corporatese allows the sudden shift into racist bullying,
as is the case in real corporations. A Bell Northern Research coworker
who did an install at Northern Telecom in North Carolina noticed how
smoothly, smoothly-spoken NT managers and techs would change their
language in a break room that happened to have a glass window onto the
cafeteria. As soon as they were confident that there were no African
Americans or women present, they would immediately shift from
corporate platitudes to crude remarks about the African American
secretaries in the cafeteria.

I have said before: "troll" is a racist word, and used inaccurately
when the target posts with sincerity, as does Richard.

You and Heathfield can't stand it that there's a growing mass of
posters and lurkers who want you to cease your nonsense.
>
> -s
> --
> Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

spinoza1111

unread,
Feb 14, 2010, 1:01:03 AM2/14/10
to
On Feb 14, 2:19 am, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-13, Richard Heathfield <r...@see.sig.invalid> wrote:
>
> >spinoza1111wrote:
> >> On Feb 13, 8:18 pm, Richard <rgrd...@gmail.com> wrote:
> >>> Richard Heathfield <r...@see.sig.invalid> writes:
> >>>> Simpler, and slightly more informative to the caller:
> >>>> long strLength(const char *s)
> >>>> {
> >>>>    long len = 0;
> >>>>    while(*s++) ++len;
> >>>>    return len;
> >>>> }
> >>> An unnecessary increment on every loop. Potentially expensive for long
> >>> blocks. Nilges might be faster in many cases.
> >> Whoa, missed that.
> > You also missed my advice (upthread) to ditch the function completely
> > and use the standard library, which will wipe the floor with both versions.
>
> Typically, yes.
>
> That said, I do like the idiom
>         size_t lenstr(char *string) {
>                 char *end = string;
>                 while (*end++)
>                         ;
>                 return end - string;
>         }
>
Doesn't even compile on a "standard" compiler that doesn't support
initialization in decaration.

Contains a major bug. end is postincremented when *end == NUL,
therefore your code gives and off by one answer. This is obvious.

Confirming this on the Microsoft compiler in STANDARD C mode:

char *string;
char *end;
string = "123";
end = string;
while(*end++);
printf("%d\n", end - string);

This prints 4.

How DARE you. How DARE you attack Schildt et al. for bugs as if you
never made stupid mistakes? How DARE you call people "trolls" and
"morons" for making less serious mistakes?

Does your incompetence, hypocrisy and narcissism know no upper bound?

> Not that it's likely to make a noticeable difference.  Or that it's likely
> worth it when obviously the standard library one will be fine.
>
> -s
> --

spinoza1111

unread,
Feb 14, 2010, 1:07:29 AM2/14/10
to
On Feb 14, 4:09 am, Keith Thompson <ks...@mib.org> wrote:

Kenny McCormack, thou should'st be here at this hour:
For Kiki is in finest Form, posting pompously and sour:
Exhibiting ersatz Learning, and utter Pedantry:
He concludes, after "all this analysis" that "almost certainly"
That "it" (Seebie's shit) will yeah right..."work properly".
But for "123" Seebie's code grinds out to the amazement of the Crowd
The number...the number...FOUR, to dismay that is loud.
Whilst we the putative Trolls do dance amidst burning Tyres
Laughing our hairy Asses off at the doom of Pedantry's pretentious
spires!

spinoza1111

unread,
Feb 14, 2010, 1:10:53 AM2/14/10
to
On Feb 14, 7:03 am, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
wrote:

He sure did. I was hoping as I went chronologically through the thread
to find someone who could find the bug before I woke up here in Asia,
but I posted my own correction before looking at replies to Seebie. It
looks like you may have, but you should have had the cojones to
describe the bug, taking the risk like a man that you may misdescribe
the bug. It's called Habermas' communicative reason and a common
search for TRUTH.
>
> Phil, who uses strlen().

Sensible chap.

Ed, who uses C Sharp.

spinoza1111

unread,
Feb 14, 2010, 1:12:29 AM2/14/10
to
On Feb 14, 7:05 am, c...@tiac.net (Richard Harter) wrote:
> On Sat, 13 Feb 2010 01:25:27 -0800 (PST),spinoza1111
>
> <spinoza1...@yahoo.com> wrote:
> Richard Harter, c...@tiac.nethttp://home.tiac.net/~cri,http://www.varinoma.com

> Infinity is one of those things that keep philosophers busy when they
> could be more profitably spending their time weeding their garden.

Looks great, and it looks like I need to review this carefully. I am
in my morning "pass" through many responses, including responses to
Seebach's latest brain fart. I will review your comments later.

spinoza1111

unread,
Feb 14, 2010, 1:13:04 AM2/14/10
to
On Feb 14, 7:23 am, "Chris M. Thomasson" <n...@spam.invalid> wrote:
> "Seebs" <usenet-nos...@seebs.net> wrote in message

Good call, Chris.

spinoza1111

unread,
Feb 14, 2010, 1:17:10 AM2/14/10
to
On Feb 14, 7:35 am, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
>
> > I believe that you have a bug in that code Seebs.
>
> Extremely likely.
>
> This is one of the reasons I rely on the standard library -- my success rate
> in avoiding fencepost errors is slightly *less* than chance.  I'm not actually
> very good at this stuff, which is why I spend so much time thinking about how
> to do it better.

No argument there, none whatsoever. But lemme ask you a question.
Where the fuck do you get off criticising people who are, if not
perfect, better than you? People like Schildt?

And why do suppose I started posting my own (vastly more challenging)
solution early when I knew it might have bugs, being self-confident
enough to risk exposure?

It's because REAL programming, as opposed to some bureaucratic job
finding other people's bugs, is humbling and challenging, and REAL
code review happens outside the language game of capitalism.

Read Habermas. And get a clue.
>
> -s
> --

spinoza1111

unread,
Feb 14, 2010, 1:27:07 AM2/14/10
to
On Feb 14, 9:10 am, "bartc" <ba...@freeuk.com> wrote:
> "Seebs" <usenet-nos...@seebs.net> wrote in message

English public school rules apply to this fight, Bart: cf. Flashman's
savaging of Tom Brown in Tom Brown's Schooldays. Which is why it's so
much fun to win, as I am winning, despite Seebie's Flashman-like
behavior. He can't get a simple strlen replace right, yet dares to
attack my much more sophisticated and challenging solution and
Schildt.

I would prefer a Habermasian-civil structured walkthrough. However, we
live in a barbaric capitalism in which there are no holds barred. It's
Extreme Fighting. But:

Hasta la victoria siempre! - Ernesto Che Guevara

En cadenas vivir es vivir
En afrenta y oprobio sumido,
Del clarín escuchad el sonido;
¡A las armas, valientes, corred! - La Bayamesa


>
> > it is, before trying to optimize.  You may, or may not, be able to
> > outperform
> > a given library's implementation of strstr().
>
> The efficiency varies. On my lccwin32 and DMC compilers, the time to find an
> "A" string, in a string consisting entirely of As, seems to depend on the
> length of the string it's searching (perhaps it's doing a strlen() first?).
> On gcc it's instant.
>
> (I came across the problem in a related function strchr(), in Malcolm's
> Minibasic program, where it had the effect, on large input files, of slowing
> down the interpreter from 80K lines per second to about 2K. Replacing the
> strchr() call with one line of custom code (I think it was just looking for
> next EOL), fixed that.)

Sounds like you have real applied comp sci chops.

>
> --
> Bartc

spinoza1111

unread,
Feb 14, 2010, 1:31:57 AM2/14/10
to
On Feb 14, 9:40 am, Joe Wright <joewwri...@comcast.net> wrote:
> Seebs wrote:
> > On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
> >> I believe that you have a bug in that code Seebs.
>
> > Extremely likely.
>
> > This is one of the reasons I rely on the standard library -- my success rate
> > in avoiding fencepost errors is slightly *less* than chance.  I'm not actually
> > very good at this stuff, which is why I spend so much time thinking about how
> > to do it better.
>
> > -s
>
> The humility is a good touch. You can use mine.

No, it is not. It is the humility of Dickens' Uriah Heep, for it is an
"humility" unlinked to the charitable willingness to REFRAIN from
posting unwarranted attacks on Schildt and others, an "humility"
linked instead to utter malice, directed at what Seebie considers safe
targets.

Dijkstra's essay "The Humble Programmer" was in my direct experience
misused. It was transformed into a call on programmers to be
subservient to corporate authority right at the end of the Sixties,
when the authority of property was in question world-wide. But
Dijkstra meant nothing of the sort.

spinoza1111

unread,
Feb 14, 2010, 1:42:21 AM2/14/10
to
On Feb 14, 10:02 am, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-02-14, bartc <ba...@freeuk.com> wrote:
>
> > I've looked at both. The first is easier on the eye, but I still can't
> > figure out what it does. You say, it finds the *next* occurence of the
> > target, why a loop then?
>
> Because it finds the next occurrence repeatedly until there's no more.
>
> > You can't really compare these (assuming they really do do the same thing);
> > your code uses some presumably tried and tested library function (strstr) to
> > do the tricky part, so you're comparing a *call* to that function to an
> > experimental *implementation* of it. That doesn't sound fair..
>
> I think it's extremely fair, because it highlights the flaw in his "I
> refuse to use the library functions" attitude.

This is a false caricature. Were I to use C, I'd use what library
functions were safe. But I would create my own string library.

However, the corporate language game is to transform responsible adult
thought into a childish "attitude".

So, I have a Bad Attitude. I actually want to do a good job. Quite
frankly, based on my thirty years I don't think you do, in a
standalone, independent sense, anything like a good job in your chosen
profession, but this doesn't matter. Managers design organizations so
that errors are hopefully factored out, and in the social machine so
created, a person who can by himself do a complete good job is in fact
a "square peg in a round hole".

However, this reality is concealed from today's programmers, owing to
the fact that capitalism is a basically inhuman system despite its
good parts. People want to be *homo faber*, man the toolmaker, and
they don't want to do a small piece of a job only to see their work
corrected and criticised by people who can't themselves do the same
work.

Therefore a Pop culture pervades in programming shops: the delusion
that each male member (where the shop must usually exclude women in
order for the illusion to work) is "rilly" a proud and independent
professional when in fact he's the type of programmer who can't get a
strlen right, finds well-formatted code "unreadable" simply by virtue
of the pains taken by the formatter, the merest thought of which makes
our boy's butt hurt in that it's a reminder of a lost humanity, and
who finds correct grammar of complexity > low n "verbose".

>
> Agreed that there are cases where there's reasons not to do that.

"There are", not "there's", Grammar Guy.
>
> -s
> --

spinoza1111

unread,
Feb 14, 2010, 2:22:30 AM2/14/10
to
OK, I implemented and tested (in about 25 minutes if you want to know)
the above-described solution to the "showstopper performance bug" that
Seebach more or less found.

This was the creation of many zero-length TYPsegmentstruct occurrences
when there are multiple adjacent hits. This code implements the plan
above.

The same cautions (make sure your browser doesn't split two lines, the
TESTER header and the final printf, at position 67 or whatever: make
sure it doesn't add a blank to the end of the TESTER macro
continuation lines) apply.

As before, a complete regression test is included.

"Oh yes. In Europe a much larger fraction of the population can write.
People in America have really suffered from the combination of TV,
which makes reading superfluous, and the telephone. A few years ago I
was at CalTech and that is a hiqh quality place and everybody
recommends it because the students are so bright. A graduate confessed
to me—no he did not confess, he just stated it, that he did not care
about his writing, since he was preparing himself for an industrial
career. Poor industry!" - Edsger Dijkstra, 1985

"You talk like a fag, and you're shit's all fucked up." - Idiocracy,
Mike Judge, 2005

// ***************************************************************
// * *
// * replace() demo *
// * *
// * Demonstrates how to replace non-NUL-defined strings in C *
// * using a simple function, and bypassing string.h. *
// * *
// * C H A N G E R E C O R D --------------------------------- *
// * DATE PROGRAMMER DESCRIPTION OF CHANGE *
// * -------- ---------- --------------------------------- *
// * 02 07 10 Nilges Version 1.0 *
// * *
// * 02 07 10 Nilges Bug: partial matches not handled *
// * correctly: need to iterate search *
// * for match. *
// * *
// * 02 07 10 Nilges 1. Santosh suggested tests *
// * 2. Heathfield put the boot in re *
// * including malloc *
// * *
// * 02 07 10 Nilges 1. Remove string.h use and code *
// * strlen by hand *
// * 2. Add comment block and comments*
// * inline. *
// * 3. free() storage *
// * 4. Use macro for testing *
// * 5. Bug: calculation of *
// * lngNewLength used incorrect *
// * index (intIndex3 instead of 2)*
// * which caused a memory leak. *
// * *
// * 02 07 10 Nilges 1. Bug: Ike Naar test failed. *
// * At end of scan loop, main *
// * string pointer was not *
// * correctly updated from index3 *
// * *
// * 02 07 10 Nilges Added new Santosh test *
// * *
// * 02 07 10 Nilges Added new Ike Naar test *
// * *
// * 02 08 10 Nilges 1. Added some new comments *
// * 2. Make "check for a complete *
// * match "structured" by means *
// * of a tested assignment *
// * 3. Get rid of "replace at end" *
// * evilness: the only time this *
// * flag is meaningful is in the *
// * LAST segment. *
// * 4. Return replace count *
// * 5. TESTER macro assertion added *
// * *
// * 02 10 10 Nilges 1. Bug fix: in a partial match, *
// * the main scan index is set to *
// * one past the end, which misses*
// * full matches that start *
// * between the first character of*
// * the partial match and its end.*
// * *
// * No longer updating the main *
// * scan index (ptrIndex1) to the *
// * point of partial match *
// * failure: setting it one past *
// * the first character of the *
// * partial match. *
// * *
// * 2. Line up expected & actual *
// * results per excellent *
// * suggestion (who made this?) *
// * *
// * 3. After a partial match, update *
// * the main handle search index *
// * (ptrIndex1) to the first *
// * occurrence of the handle *
// * character after the start of *
// * the partial match, or to the *
// * index of the unmatched char. *
// * *
// * 021310 Nilges Bug: failed to handle a one-char *
// * replace (of a by x in b) since *
// * we set ptrIndex2 to point to NUL *
// * which made it appear that there *
// * was a match. When the main index *
// * to the master string (ptrIndex1) *
// * goes off the end of a cliff, we *
// * needed to break out of the search *
// * loop. *
// * *
// * This also entailed setting the *
// * target index ptrIndex2 to 0 at the*
// * beginning of each search so that *
// * it is not erroneously used to *
// * indicate that there's an insert *
// * needed at the end. *
// * *
// * I have also added additional tests*
// * to verify that the code works *
// * when the string and target end *
// * at the same time. *
// * *
// * 02 14 10 Nilges This version detects zero length *
// * segments and merges them *
// * ----------------------------------------------------------- *
// * *
// * "In the near future we shall have to live with the *
// * superstition that programming is 'so easy that even a *
// * Republican can do it!'" *
// * *
// * - E. W. Dijkstra *
// * *
// * *
// ***************************************************************
#include <stdio.h>
#include <stdlib.h>

// ***** Segmentation *****
struct TYPsegmentstruct
{ char * strSegment;
long lngSegmentLength;
struct TYPsegmentstruct * ptrNext; };

// ---------------------------------------------------------------


// Calculate string length
//
//
long strLength(char *strInstring)
{
char *ptrInstring;
for (ptrInstring = strInstring; *ptrInstring; ptrInstring++);
return ptrInstring - strInstring;
}

// ---------------------------------------------------------------
// Replace target by replacement string in master string
//
//
// Caution: the string returned by this function should be freed.
//
//
char * replace(char * strMaster,
char * strTarget,
char * strReplacement,
long * ptrReplacements)
{
char * ptrIndex0;
char * ptrIndex1;
char * ptrIndex2;
char * ptrIndex3;
char * ptrIndex4;
char * strNew;
char * strNewStart;
long lngNewLength;
long lngCount;
long lngReplacementLength;
struct TYPsegmentstruct * ptrSegmentStructStarts;
struct TYPsegmentstruct * ptrSegmentStruct;
struct TYPsegmentstruct * ptrSegmentStructPrev;
lngReplacementLength = strLength(strReplacement);
if (!*strTarget)
{
printf("Error in calling replace(): target can't be null");
abort();
}
ptrIndex1 = strMaster;
ptrSegmentStruct = 0;
ptrSegmentStructPrev = 0;
lngNewLength = 0;
*ptrReplacements = 0;
while(*ptrIndex1)
{
ptrIndex0 = ptrIndex1;
ptrIndex2 = 0;
while (-1)
{
// --- Check for (one character) handle
for(;
*ptrIndex1 && *ptrIndex1 != *strTarget;
ptrIndex1++);
if (!*ptrIndex1) break;
// --- Check for complete match while remembering the
// --- last position of the handle
ptrIndex4 = 0;
for(ptrIndex2 = strTarget + 1,
ptrIndex3 = ptrIndex1 + 1;
*ptrIndex3
&&
*ptrIndex2
&&
*ptrIndex3 == *ptrIndex2;
ptrIndex3++, ptrIndex2++)
{
if (*ptrIndex3 == *strTarget
&&
ptrIndex4 == 0) ptrIndex4 = ptrIndex3;
}
// End test: check complete match, update main ptr past
// partial match while checking for end of loop
if ((!*ptrIndex2 ? ((*ptrReplacements)++, -1) : 0)
||
(!*ptrIndex3 ? (ptrIndex1 = ptrIndex3, -1) : 0))
break;
// Update the main search pointer
ptrIndex1 = (ptrIndex4 == 0 ? ptrIndex3 : ptrIndex4);
}
// --- Create new segment
if (ptrSegmentStruct != 0
&&
ptrSegmentStruct->lngSegmentLength <= 0
&&
ptrIndex1 == ptrIndex0)
{
// We don't want to create a lot of null segments
ptrSegmentStruct->lngSegmentLength--;
}
else
{
if (!(ptrSegmentStruct =
malloc(sizeof(struct TYPsegmentstruct))))
abort();
ptrSegmentStruct->strSegment = ptrIndex0;
ptrSegmentStruct->lngSegmentLength =
ptrIndex1 - ptrIndex0;
ptrSegmentStruct->ptrNext = 0;
if (ptrSegmentStructPrev != 0)
ptrSegmentStructPrev->ptrNext = ptrSegmentStruct;
else
ptrSegmentStructStarts = ptrSegmentStruct;
ptrSegmentStructPrev = ptrSegmentStruct;
}
// --- Update mallocation length
lngNewLength += (ptrSegmentStruct->lngSegmentLength <= 0
?
0
:
ptrSegmentStruct->lngSegmentLength)


+
(ptrIndex2 && !*ptrIndex2
?
lngReplacementLength
:
0);

// --- Get past end of target string & iterate
if (*ptrIndex1) ptrIndex1 = ptrIndex3;
}
// --- Allocate just enough storage for the new string
if (!(strNewStart = malloc(lngNewLength + 1))) abort();
// --- Build the new string whilst freeing the list
strNew = strNewStart;
ptrSegmentStruct = ptrSegmentStructStarts;
while (ptrSegmentStruct)
{
for (ptrIndex1 = ptrSegmentStruct->strSegment,
lngCount = 0;
lngCount < ptrSegmentStruct->lngSegmentLength;
ptrIndex1++, lngCount++, strNew++)
*strNew = *ptrIndex1;
if (ptrSegmentStruct->ptrNext
||
ptrIndex2 != 0 && !*ptrIndex2)
for (lngCount =
(ptrSegmentStruct->lngSegmentLength
>
0
?
1
:
-(ptrSegmentStruct->lngSegmentLength) + 1);
lngCount > 0;
lngCount--)
for (ptrIndex1 = strReplacement;
*ptrIndex1;
ptrIndex1++, ++strNew)
*strNew = *ptrIndex1;
ptrSegmentStructPrev = ptrSegmentStruct;
ptrSegmentStruct = ptrSegmentStruct->ptrNext;
free(ptrSegmentStructPrev);
}
*strNew = '\0';
return strNewStart;
}

// ---------------------------------------------------------------
// Statement-format test macro
//
//
#define TESTER(resultPtr, master, target, replacement, expected,
expectedReplacements, replacements) \
{ \
printf("Replace \"%s\" by \"%s\" in \"%s\"\n", \
(target), (replacement), (master)); \
printf("Expect \"%s\":\n \"%s\"\n", \
(expected), \
resultPtr = replace((master), \
(target), \
(replacement), \
&(replacements))); \
printf("Replacements expected: %d: replacements: %d\n", \
(expectedReplacements), \
(replacements)); \
if (!(strLength(resultPtr) \
== \
strLength(master) \
+ \
(strLength(replacement)-strLength(target)) \
* \
replacements)) \
printf("Assertion failed\n"); \
printf("\n\n"); \
free(resultPtr); \
}

// ---------------------------------------------------------------
// Main procedure
//
//
int main()
{
char *ptrResult;
long lngReplacements;
printf("\nReplace\n\n\n");
TESTER(ptrResult,
"xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"x",
"y",
"yyyyyyyyyyyyyyyyyyyyyyyyyyyy",
28,
lngReplacements)
TESTER(ptrResult,
"1111123bbb1111123bbb11123bb11111231111112111111123",
"111123",
"ono",
"1onobbb1onobbb11123bb1ono1111112111ono",
4,
lngReplacements)
TESTER(ptrResult,
"bbb1111123bbbbb",
"111123",
"ono",
"bbb1onobbbbb",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid error",
"stupid error",
"miracle",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid error",
"stupid",
"miracle",
"a miracle error",
1,
lngReplacements)
TESTER(ptrResult,
"the stupid error",
"the stupid error",
"a miracle",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"the miracle",
"the",
"a",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"a miraclsnirpKamunkle",
"snirpKamunkle",
"e",
"a miracle",
1,
lngReplacements)
TESTER(ptrResult,
"a miraclesnirpKamunkle",
"a miracle",
"",
"snirpKamunkle",
1,
lngReplacements)
TESTER(ptrResult,
" a miraclesnirpKamunkle",
"a miracle",
"",
" snirpKamunkle",
1,
lngReplacements)
TESTER(ptrResult,
" a miraclesnirpKamunklea miraclea miracle",
"a miracle",
"",
" snirpKamunkle",
3,
lngReplacements)
TESTER(ptrResult,
"a miracle a miraclesnirpKamunkle a Miraclea
miracleamiracle",
"a miracle",
"",
" snirpKamunkle a Miracle",
3,
lngReplacements)
TESTER(ptrResult,
"a stupid errord",
"stupid error",
"miracle",
"a miracled",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid errod",
"stupid error",
"miracle",
"a stupid errod",
0,
lngReplacements)
TESTER(ptrResult,
"a sstupid error",
"stupid error",
"miracle",
"a smiracle",
1,
lngReplacements)
TESTER(ptrResult,
"a stupid errorstupid error",
"stupid error",
"miracle",
"a miraclemiracle",
2,
lngReplacements)
TESTER(ptrResult,
"a stupid error stupiderror",
"stupid error",
"miracle",
"a miracle stupiderror",
1,
lngReplacements)
TESTER(ptrResult,
"bbbbbbbbbb",
"b",
"a",
"aaaaaaaaaa",
10,
lngReplacements)
TESTER(ptrResult,
"In the halls of R'yleh great %s lies dreaming",
"%s",
"Cthulu",
"In the halls of R'yleh great Cthulu lies dreaming",
1,
lngReplacements)
TESTER(ptrResult,
"%s%s%s%s%s%s",
"%s",
"Cthulu",
"CthuluCthuluCthuluCthuluCthuluCthulu",
6,
lngReplacements)
TESTER(ptrResult,
"banana",
"ana",
"oat",
"boatna",
1,
lngReplacements)
TESTER(ptrResult,
" a stupid errorstupid errorHeystupid errors",
"stupid error",
"+",
" a ++Hey+s",
3,
lngReplacements)
TESTER(ptrResult,
"foo barfoo barf",
"foo bar",
"bas",
"basbasf",
2,
lngReplacements)
TESTER(ptrResult,
"abab",
"ba",
"ba",
"abab",
1,
lngReplacements)
TESTER(ptrResult,
"abab",
"bab",
"boop",
"aboop",
1,
lngReplacements)
TESTER(ptrResult,
"banana",
"ana",
"ono",
"bonona",
1,
lngReplacements)
TESTER(ptrResult,
"a",
"x",
"b",
"a",
0,
lngReplacements)
TESTER(ptrResult,
"x",
"x",
"b",
"b",
1,
lngReplacements)
TESTER(ptrResult,
"egregious",
"egregious",
"egregious",
"egregious",
1,
lngReplacements)
TESTER(ptrResult,
"egregious",
"egregious",
"x",
"x",
1,
lngReplacements)
printf("\n\nTesting complete: check output carefully: \"Assertion
failed\" should not occur!\n\n");
return 0;
}


Replace


Replace "x" by "y" in "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Expect "yyyyyyyyyyyyyyyyyyyyyyyyyyyy":
"yyyyyyyyyyyyyyyyyyyyyyyyyyyy"
Replacements expected: 28: replacements: 28


Replace "111123" by "ono" in
"1111123bbb1111123bbb11123bb11111231111112111111123"
Expect "1onobbb1onobbb11123bb1ono1111112111ono":
"1onobbb1onobbb11123bb1ono1111112111ono"
Replacements expected: 4: replacements: 4


Replace "111123" by "ono" in "bbb1111123bbbbb"
Expect "bbb1onobbbbb":
"bbb1onobbbbb"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "miracle" in "a stupid error"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "stupid" by "miracle" in "a stupid error"
Expect "a miracle error":
"a miracle error"
Replacements expected: 1: replacements: 1


Replace "the stupid error" by "a miracle" in "the stupid error"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "the" by "a" in "the miracle"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "snirpKamunkle" by "e" in "a miraclsnirpKamunkle"
Expect "a miracle":
"a miracle"
Replacements expected: 1: replacements: 1


Replace "a miracle" by "" in "a miraclesnirpKamunkle"
Expect "snirpKamunkle":
"snirpKamunkle"
Replacements expected: 1: replacements: 1


Replace "a miracle" by "" in " a miraclesnirpKamunkle"
Expect " snirpKamunkle":
" snirpKamunkle"
Replacements expected: 1: replacements: 1


Replace "a miracle" by "" in " a miraclesnirpKamunklea miraclea
miracle"
Expect " snirpKamunkle":
" snirpKamunkle"
Replacements expected: 3: replacements: 3


Replace "a miracle" by "" in "a miracle a miraclesnirpKamunkle a
Miraclea miracleamiracle"
Expect " snirpKamunkle a Miracle":
" snirpKamunkle a Miracleamiracle"
Replacements expected: 3: replacements: 3


Replace "stupid error" by "miracle" in "a stupid errord"
Expect "a miracled":
"a miracled"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "miracle" in "a stupid errod"
Expect "a stupid errod":
"a stupid errod"
Replacements expected: 0: replacements: 0


Replace "stupid error" by "miracle" in "a sstupid error"
Expect "a smiracle":
"a smiracle"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "miracle" in "a stupid errorstupid error"
Expect "a miraclemiracle":
"a miraclemiracle"
Replacements expected: 2: replacements: 2


Replace "stupid error" by "miracle" in "a stupid error stupiderror"
Expect "a miracle stupiderror":
"a miracle stupiderror"
Replacements expected: 1: replacements: 1


Replace "b" by "a" in "bbbbbbbbbb"
Expect "aaaaaaaaaa":
"aaaaaaaaaa"
Replacements expected: 10: replacements: 10


Replace "%s" by "Cthulu" in "In the halls of R'yleh great %s lies
dreaming"
Expect "In the halls of R'yleh great Cthulu lies dreaming":
"In the halls of R'yleh great Cthulu lies dreaming"
Replacements expected: 1: replacements: 1


Replace "%s" by "Cthulu" in "%s%s%s%s%s%s"
Expect "CthuluCthuluCthuluCthuluCthuluCthulu":
"CthuluCthuluCthuluCthuluCthuluCthulu"
Replacements expected: 6: replacements: 6


Replace "ana" by "oat" in "banana"
Expect "boatna":
"boatna"
Replacements expected: 1: replacements: 1


Replace "stupid error" by "+" in " a stupid errorstupid errorHeystupid
errors"
Expect " a ++Hey+s":
" a ++Hey+s"
Replacements expected: 3: replacements: 3


Replace "foo bar" by "bas" in "foo barfoo barf"
Expect "basbasf":
"basbasf"
Replacements expected: 2: replacements: 2


Replace "ba" by "ba" in "abab"
Expect "abab":
"abab"
Replacements expected: 1: replacements: 1


Replace "bab" by "boop" in "abab"
Expect "aboop":
"aboop"
Replacements expected: 1: replacements: 1


Replace "ana" by "ono" in "banana"
Expect "bonona":
"bonona"
Replacements expected: 1: replacements: 1


Replace "x" by "b" in "a"
Expect "a":
"a"
Replacements expected: 0: replacements: 0


Replace "x" by "b" in "x"
Expect "b":
"b"
Replacements expected: 1: replacements: 1


Replace "egregious" by "egregious" in "egregious"
Expect "egregious":
"egregious"
Replacements expected: 1: replacements: 1


Replace "egregious" by "x" in "egregious"
Expect "x":
"x"
Replacements expected: 1: replacements: 1


Testing complete: check output carefully: "Assertion failed" should
not occur!

spinoza1111

unread,
Feb 14, 2010, 2:29:30 AM2/14/10
to
On Feb 14, 1:04 pm, Joe Wright <joewwri...@comcast.net> wrote:
> Phred Phungus wrote:
> > Joe Wright wrote:
> >> Seebs wrote:
> >>> On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
> >>>> I believe that you have a bug in that code Seebs.
>
> >>> Extremely likely.
>
> >>> This is one of the reasons I rely on the standard library -- my
> >>> success rate
> >>> in avoiding fencepost errors is slightly *less* than chance.  I'm not
> >>> actually
> >>> very good at this stuff, which is why I spend so much time thinking
> >>> about how
> >>> to do it better.
>
> >>> -s
>
> >> The humility is a good touch. You can use mine.
>
> >> size_t Strlen(char *s)
> >> {
> >>    size_t l = 0;
> >>    if (s) while (*s++) l++;
> >>    return l;
> >> }
>
> > So this is your home-rolled strlen?
>
> Yes Fred, it is. Note it is null pointer safe. Anything else?

While it appears to work, it has a showstopper of an error in style,
Joe. This is the use of "l" to mean "length" when in common fonts l
and 1 (the famous number) are different by only one pixel.

Hard to read, even if you can read, as opposed to the "unreadability"
of the aliterate.

But hey, what do I know. I write like a fag, and my shit's all fucked
up, right? Right...

spinoza1111

unread,
Feb 14, 2010, 2:31:44 AM2/14/10
to

Naw, on first reading, it don't look that great: a lot of pompous
windbaggery in the corporate genre. But I need to go out for a run
before I start torturing quite small animals. I will blow this out of
the water later.

Walter Banks

unread,
Feb 14, 2010, 2:36:45 AM2/14/10
to

spinoza1111 wrote:

> OK, I implemented and tested

> the above-described solution to the "showstopper performance bug" that
> Seebach more or less found.

The change list does not reflect this statement.

w..


--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

io_x

unread,
Feb 14, 2010, 2:51:03 AM2/14/10
to

"spinoza1111" ha scritto nel messaggio
news:06317ad6-cd11-48e7...@b9g2000pri.googlegroups.com...
On Feb 13, 2:46 am, spinoza1111 <spinoza1...@yahoo.com> wrote:
...code...

TESTER(ptrResult,
"a miracle a miraclesnirpKamunkle a Miraclea
miracleamiracle",
"a miracle",
"",
" snirpKamunkle a Miracle",

4,
lngReplacements)

i think it should be:

TESTER(ptrResult,
"a miracle a miraclesnirpKamunkle a Miraclea
miraclea miracle",

^^^^^^^^^^^^^^^^^^


"a miracle",
"",
" snirpKamunkle a Miracle",

4,
lngReplacements)
For the problem; i wrote the routine for doing that
in assembly using in that routine no string.h function

Richard Heathfield

unread,
Feb 14, 2010, 2:56:16 AM2/14/10
to
Joe Wright wrote:

<snip>

> size_t Strlen(char *s)
> {
> size_t l = 0;
> if (s) while (*s++) l++;
> return l;
> }

This, too, suffers (if that's the right word) from an unnecessary ++. It
also conflates "" and NULL. In a way that's fair enough, provided the
documentation says so (e.g. by warning that a null pointer parameter
invokes undefined behaviour). But we can separate them easily enough
without changing the interface, if we're prepared to think of (size_t)-1
as a sign that something went wrong - and we can eliminate that pesky
redundant ++ at the same time:

#include <stddef.h>
size_t sl(const char*s){size_t l=-1;if(s)do++l;while(s[l]);return l;}

You will note that, in the interests of readability, I have removed as
much whitespace as possible, since nobody can read whitespace.

Note for the terminally thick: DON'T use the above function or any of
the other silly attempts that have been posted in this silly thread. Use
strlen - the real one, the one in the standard library.

Richard Heathfield

unread,
Feb 14, 2010, 3:04:44 AM2/14/10
to
spinoza1111 wrote:
> On Feb 14, 2:15 am, Richard Heathfield <r...@see.sig.invalid> wrote:
>> spinoza1111wrote:
<snip>

>>
>>> ....dishonestly, like Falstaff, seeking glory.
>> The glory involved in pointing out improvements in your code is about at
>> the same level as the glory involved in peeling a banana.
>
> You have suggested no useful improvements.

I've already suggested removing a non-standard and unnecessary header,
and ditching a silly and unnecessary strlen replacement. Those are
useful suggestions.

<snip>

>> > since you found no bugs,
>>
>> I haven't looked yet.
>
> Lazy bastard, aren't you.

I spent many hours trying to educate you about C in large chunks. It's a
waste of time. You don't seem to be able to cope with more than one idea
at a time, and even then it sometimes takes you a few days to understand
it. I have better ways to spend my time.

Or perhaps the code is "unreadable" despite
> all the work I've done?

No, the code is hard to read *because* of all the work you've done
(including the work you did on the first draft).


> You know, I discovered a long time ago that
> there are two types of people who like to call either texts or code
> "unreadable":

s/two/three/
s/like to //
s/unreadable/harder than necessary to read/

>
> * Stupid people employed at positions for which they are not, in
> reality, qualified
>
> * Criminals who find the law unreadable in hopes of copping a plea of
> plausible deniability

* People who find themselves faced with code that is harder than
necessary to read.

<nonsense snipped>

>> > I thought you wrote portable code. Oh well.
>>
>> I do. You don't know what it means.
>
> What an asshole. Your code can't be pasted and run into common older
> implementations.

It can't be pasted into Fortran programs or APL programs either. So
what? I don't claim portability to non-standard implementations.

> When another's code fails this simple test, you
> condemn their competence,

Actually, no I don't do that. You may be mixing me up with someone else,
or your ignorance of C may have led you to misunderstand an article I've
written. Either is possible. Both is even more possible.

Richard Heathfield

unread,
Feb 14, 2010, 3:11:18 AM2/14/10
to
spinoza1111 wrote:
> On Feb 14, 2:19 am, Seebs <usenet-nos...@seebs.net> wrote:
<snip>

>>
>> That said, I do like the idiom
>> size_t lenstr(char *string) {
>> char *end = string;
>> while (*end++)
>> ;
>> return end - string;
>> }
>>
> Doesn't even compile on a "standard" compiler that doesn't support
> initialization in decaration.

That's a contradiction in terms. No such compiler exists.

<snip>

> How DARE you. How DARE you attack Schildt et al. for bugs as if you
> never made stupid mistakes?

Everybody makes stupid mistakes. Schildt is not immune from that, but
neither is anyone else. When professionals make stupid mistakes (and
yes, they do), they don't try to make the situation worse by denying or
covering up the mistake. Schildt's mistake, and it's one which he has
yet to acknowledge as far as I am aware, is that he has failed to
produce a comprehensive errata list for his C books.

io_x

unread,
Feb 14, 2010, 3:28:19 AM2/14/10
to

"Joe Wright" <joeww...@comcast.net> ha scritto nel messaggio
news:ZYadnWyQgfzoyerW...@giganews.com...

> Seebs wrote:
>> On 2010-02-13, Chris M. Thomasson <n...@spam.invalid> wrote:
>>> I believe that you have a bug in that code Seebs.
>>
>> Extremely likely.
>>
>> This is one of the reasons I rely on the standard library -- my success rate
>> in avoiding fencepost errors is slightly *less* than chance. I'm not
>> actually
>> very good at this stuff, which is why I spend so much time thinking about how
>> to do it better.
>>
>> -s
>
> The humility is a good touch. You can use mine.
>
> size_t Strlen(char *s)
> {
> size_t l = 0;
> if (s) while (*s++) l++;
> return l;
> }

good, with that it is easy to add error managment

// -1 on error


size_t Strlen(char *s)
{ size_t l = 0;
if (s) while (*s++)

{if(s==0) return (size_t)-1;
l++;
if(l==0) return (size_t)-1;

io_x

unread,
Feb 14, 2010, 3:28:49 AM2/14/10
to

"io_x" <a...@b.c.invalid> ha scritto nel messaggio
news:4b76856d$0$1102$4faf...@reader4.news.tin.it...
>
> "spinoza1111" <spino...@yahoo.com> ha scritto nel messaggio
> news:45109f35-05da-46a8...@p13g2000pre.googlegroups.com...
> I can not be agree on your way of build test function
> like a macro: that is indebuggable.
> Macro for me are for build one language or for doing little
> substitution like in "P" ---> "printf"
>
> this is my propose: write only when find one error
> --------------------------------
> #define P printf
> #define R return
>
> // origin has to came from malloc memory
> int tester(char* origin, char* whatSost, char* sost, char* expected)
> {char *p;
> unsigned len;

is seen this post?


Seebs

unread,
Feb 14, 2010, 3:17:25 AM2/14/10
to
On 2010-02-14, Richard Heathfield <r...@see.sig.invalid> wrote:
> Everybody makes stupid mistakes.

I make them more than most people. As a compensating tactic, I can be pretty
careful about working things out and testing them... But I tend not to when
posting to Usenet (although I always check my facts before posting nonsense
to Usenet!).

> When professionals make stupid mistakes (and
> yes, they do), they don't try to make the situation worse by denying or
> covering up the mistake.

In general, no. Someone pointed that one out, and I concede cheerfully that,
yes, that's a pretty stupid mistake. I make stupid mistakes a *lot*, so I'm
used to that. Note that I make them a lot less often on much more
complicated things than on simpler things; a neat quirk of brain chemistry
or something. And I don't just mean "less often, compared to other people"; I
mean less often in absolute terms. I'm much more likely to get something
trivial wrong than something interesting and challenging.

> Schildt's mistake, and it's one which he has
> yet to acknowledge as far as I am aware, is that he has failed to
> produce a comprehensive errata list for his C books.

I disagree. The problem is not the lack of an errata list; it's that he
still doesn't even *understand* how feof() works. He's written a series
of Pascal books which have been cleverly relabeled "C" and had some of the
punctuation altered, in effect. He got several of the "easy" mistakes that
were, say, posted on my page, fixed for the 4th edition. He didn't fix the
much more serious logic flaws introduced by his unwillingness to comprehend
how end-of-file conditions are handled in C.

And that's the thing. Errata would be one thing. But if every example I
read using feof() used it incorrectly, and multiple examples of how to do
input loops used feof() incorrectly, that suggests to me that these are not
merely "stupid mistakes" (fencepost errors, typos, etcetera), but a genuine
failure to comprehend something which I think can be reasonably regarded as
fairly basic.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net

spinoza1111

unread,
Feb 14, 2010, 3:23:55 AM2/14/10
to
On Feb 14, 3:36 pm, Walter Banks <wal...@bytecraft.com> wrote:
> spinoza1111wrote:

> > OK, I implemented and tested
> > the above-described solution to the "showstopper performance bug" that
> > Seebach more or less found.
>
> The change list does not reflect this statement.

Seebach didn't find the SPB: I did.
>
> w..
>
> --- news://freenews.netfront.net/ - complaints: n...@netfront.net ---

spinoza1111

unread,
Feb 14, 2010, 3:26:19 AM2/14/10
to
On Feb 14, 3:51 pm, "io_x" <a...@b.c.invalid> wrote:
> "spinoza1111" ha scritto nel messaggionews:06317ad6-cd11-48e7...@b9g2000pri.googlegroups.com...

> On Feb 13, 2:46 am,spinoza1111<spinoza1...@yahoo.com> wrote:
> ...code...
>
>     TESTER(ptrResult,
>            "a miracle a miraclesnirpKamunkle a Miraclea
> miracleamiracle",
>            "a miracle",
>            "",
>            " snirpKamunkle a Miracle",
>            4,
>            lngReplacements)
>
> i think it should be:
>
> TESTER(ptrResult,
>            "a miracle a miraclesnirpKamunkle a Miraclea
> miraclea miracle",
> ^^^^^^^^^^^^^^^^^^
>            "a miracle",
>            "",
>            " snirpKamunkle a Miracle",
>            4,
>            lngReplacements)
> For the problem; i wrote the routine for doing that
> in assembly using in that routine no string.h function

Thanks for your contributions, but:

(1) I am not qualified to read assembler (note that that's how a
gentlemen speaks when he is not qualified to read code: he doesn't
call the code unreadable)

(2) The problem was to be solved in C

It is loading more messages.
0 new messages