Implementing strstr

S

Seebs

Good summary of Baldrick's personality disorders. And it would be nice
if he stopped posting his turgid "poetry" which is offensive to those of
us with English as a mother tongue, never mind everyone else.

Well-written doggerel can be a real pleasure to read. Sadly, working with
John Nash does not make you Ogden Nash.

-s
 
B

Ben Bacarisse

Seebs said:
Okay, this sounded fun. Here's a trivial test harness and a trivial strstr.
Feel free to find bugs.
<snip>

I did not look at the tester.
char *
my_strstr(const char *haystack, const char *needle) {
const char *found = 0;
const char *next_candidate = 0;
const char *h, *n;

/* an empty string is found immediately, even in an empty string */
if (!*needle)
found = haystack;
for (; !found && *haystack; ++haystack) {
if (*haystack == *needle) {
next_candidate = 0;
h = haystack;
n = needle;
/* stash the next spot matching the first
* character of the needle.
*/
while (*++n == *++h) {

Possible UB from running off the end of one or both strings here. If
the arrays have further characters after matching nulls, then you
don't get UB but the algorithm goes wrong.
if (*n == *haystack && !next_candidate)
next_candidate = h;
}
/* we reached the end of the needle, so
* we are done
*/
if (!*n) {
found = haystack;
} else {
if (next_candidate)
haystack = next_candidate - 1;
else
haystack = h - 1;
}
}
}

/* sorry, no way around it; we can't return a possibly-qualified
* pointer, so we have to drop const in case the original strings
* were not really const.
*/
return (char *) found;
}

<snip>
 
S

Seebs

Possible UB from running off the end of one or both strings here. If
the arrays have further characters after matching nulls, then you
don't get UB but the algorithm goes wrong.

D'oh! Good catch.

-s
 
T

Tim Streater

Nick said:
Well you could post thousands of lines a day to comp.lang.c about how
the world isn't structured exactly the way you want it to be, and about
how no-one else uses words in the same humpty-dumpty fashion you do, and
about bizarre industrial relations history of the 1970s and why that
means some programming languages follow paradigms invented by medieval
painters (I may have got the last of these a bit wrong). It seems to
work for at least one person.

Good summary of Baldrick's personality disorders. And it would be nice
if he stopped posting his turgid "poetry" which is offensive to those of
us with English as a mother tongue, never mind everyone else.
 
S

spinoza1111

Actually, I like it the way it is -- I get a filtered feed of an occasional
actual technical question, without the flood of irrelevant insults.

The guy's unambiguously a usenet kook, but his questions on technical

No, I'm not anything of the sort, and I'd appreciate it if you'd shove
it up your ass. I am a fellow Apress author, and I have complained to
Apress about your behavior and your bad habit of posting about C, in
which you repeatedly make simple mistakes and on which you are not
qualified to post opinions.
issues are occasionally interesting, for much the same reason that it
can be occasionally interesting to try to answer questions asked by
other novice-level programmers.  It's just not very rewarding to me

You are, yourself, an aging novice programmer who hasn't completed
enough academic work to post useful views. Sure, if you'd created a
significant piece of software as an autodidact, I would not make this
accusation, but you haven't as far as I can tell. Even in this case, I
would not raise this concern, but your behavior as regards Schildt and
myself constitutes libel.

to search through several-hundred line posts full of tinfoil hat nonsens
to find an occasional gem like his observation that there should be
a default case in a getopt() switch because someone could modify the
argument string but not remember to add the corresponding case.  That
was actually a good idea, I think.

**** you, you pretentious and patronizing little son of a bitch.
 
S

spinoza1111

Okay, this sounded fun.  Here's a trivial test harness and a trivialstrstr.
Feel free to find bugs.  The only one I caught in testing was that I had
the order of the two arguments reversed -- I did (needle, haystack) rather
than (haystack, needle).  Feel free to present broken cases; I have no
illusions that I'll have gotten this bug-free on the first try.

This program assumes that the librarystrstr() works.

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

char *my_strstr(const char *s1, const char *s2);

/* for test harness, not for implementation */
#define MAX_LEN 128

(Sigh) Incompetent programmers love "buffers" despite the fact that
"buffers" of ANY memory size are either bugs waiting to happen, or
memory hogs (there is no other alternative). People who take compsci
learn about links.
/* imagine that a large buffer is divided into five parts:
 * 1 2 3 4 5
 * test_strstr() copies the argument strings into slots 2 and 4, so
 * that results can be compared for relative position, not just equality,
 * because they're all in a single argument.
 */
void
test_strstr(char *haystack, char *needle) {
        size_t needle_len, haystack_len;
        char big_buffer[MAX_LEN * 5] = { 0 };
        char *store_needle = big_buffer + (MAX_LEN * 1);
        char *store_haystack = big_buffer + (MAX_LEN * 3);

        char *lib_return, *my_return;

        if (!needle || !haystack) {
                fprintf(stderr, "error: test_strstr() needs valid strings.\n");
                return;
        }
        needle_len = strlen(needle);
        haystack_len = strlen(haystack);
        if (needle_len > 128) {

ROTFLMFAO.

This is a junior programmer script kiddie newbie error! You define
MAX_LEN above as 128 because da big boys do so, ignorantly copying,
aping their style.

News flash, Dweebach: the big boys do so SO THE SYMBOL CAN BE LATER
USED IN TESTS AND CAN BE CHANGED IN ONE PLACE. We knew this even in
mainframe Cobol.

But you've hard-coded the limit value!

How dare you, how dare you attack Schildt! Every fucking scrap of code
you've submitted to this newsgroup contains, not just bugs, but
completely wrong code which demonstrates that you come here to steal
intellectual product in the form of fixes to code that a professional
programmer would be ashamed of.

* A %s search which failed because you used strchr and not string.h's
strstr
* A strlen with an off by one error
* switch() statements which use an unstructured and needlessly
misleading style
* Logic leaks in which you leave significant variables completely
uninitialized so that "the worst bug" can happen...everything seems to
work. But you give a ****, right?

And now this monstrosity.

Oh, this is going to be fun. I have to go to work at this time but I
look forward to a most amusing time with this code, Yet Another
Dweebach-o-rama.

                fprintf(stderr, "test_strstr: needle too long (limit %d)\n",
                        MAX_LEN);
                return;
        }
        if (haystack_len > 128) {

HA HA HA HA HA HA
                fprintf(stderr, "test_strstr: haystack too long (limit %d)\n",
                        MAX_LEN);

128! MAX_LEN! 128! MAX_LEN!
                return;
        }
        strcpy(store_needle, needle);
        strcpy(store_haystack, haystack);
        lib_return =strstr(store_haystack, store_needle);
        my_return = my_strstr(store_haystack, store_needle);

        printf("test: <%s> in <%s>: ",
                store_needle, store_haystack);
        if (lib_return == my_return) {
                if (lib_return)
                        printf("<%s> (offset %d).\n",
                                lib_return, lib_return - store_haystack);
                else
                        printf("No match.\n");
                return;
        }
        /* they don't match... what went wrong? */

Oh shit!
 
S

spinoza1111

The reason I break into verse
Is quite frankly that I could do far worse.
You're an ugly and horrid little man...
You don't even understand
That Blackadder is the bounder, the cad and the rotter
That was the intention of the director.
Baldrick is his better nature who oft had the cunning plan
In the credits, who is identified as the horrid little man?

Writing poetry attracts your envy
It's something you can never do
For like most Troglodytes today
You think, if that's the word,
In fits and starts
As the monkey farts,
And try to dignify your sloth and inattention
With the name of a fashionable disease and its medication.

I can see you clumsily trying to write a verse reply
Searching an online rhyming dictionar-eye
News flash, Dweebach, it ain't about rhyme,
It's about a stress and its music, and the iambic pantomime.
But don't waste your time swotting wikipedia
It's not as if your could learn it that way:
For you are a slave and a follower of rules...
That unto dusty failure and death have oft lighted fools.
You "learn" some rules in a half-understood book
For programming, but it's dollars to donuts you'll forget them:
Just as you remembered to symbolize a maximum length
But then did not have the brain strength, did you,
To consistently use the symbol
And art naught by sounding brass and clashing cymbal.

You can't program and you can't write poetry
You can't pay attention and you can't fight me
Without whining and losing and losing and whining
And besides a false "killfile" your fat ass be hiding.
You can't write above a low upper bound of complexity
All you can do is destroy, and all you can do is annoy:
And that is why I'm the target of your vile hatred and disgusting
envy.
 
P

Phil Carmody

Seebs said:
Well-written doggerel can be a real pleasure to read. Sadly, working with
John Nash does not make you Ogden Nash.

Do we even have evidence that he 'worked with' John Nash. If I were
to apply Bilge's levels of reliability and truthiness to what I post,
heck, I'd probably be able to say I taught Linus Torvalds how to
program. Being in the vicinity of does not equate to 'working with'.

Phil
 
S

spinoza1111

Well-written doggerel can be a real pleasure to read.  Sadly, working with
John Nash does not make you Ogden Nash.

Who said I wanted to be Ogden Nash? And if you can write poetic
responses, let's have them. You're already embarassing yourself with
incompetent code.

I'd love to see
Under the sea
What you consider
Good poetry.
 
S

spinoza1111

Okay, this sounded fun.  Here's a trivial test harness and a trivialstrstr.

Nearly two weeks I solved the problem...wow, that's almost as good as
the two months you needed to show us that you don't understand
structured-programming a switch() statement.
Feel free to find bugs.

Nyah ha ha...cue Dr. Evil laugh
 
The only one I caught in testing was that I had
the order of the two arguments reversed -- I did (needle, haystack) rather
than (haystack, needle).  Feel free to present broken cases; I have no
illusions that I'll have gotten this bug-free on the first try.

This program assumes that the librarystrstr() works.

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

char *my_strstr(const char *s1, const char *s2);

/* for test harness, not for implementation */
#define MAX_LEN 128

/* imagine that a large buffer is divided into five parts:
 * 1 2 3 4 5
 * test_strstr() copies the argument strings into slots 2 and 4, so
 * that results can be compared for relative position, not just equality,
 * because they're all in a single argument.
 */
void
test_strstr(char *haystack, char *needle) {
        size_t needle_len, haystack_len;
        char big_buffer[MAX_LEN * 5] = { 0 };
        char *store_needle = big_buffer + (MAX_LEN * 1);
        char *store_haystack = big_buffer + (MAX_LEN * 3);

        char *lib_return, *my_return;

        if (!needle || !haystack) {
                fprintf(stderr, "error: test_strstr() needs valid strings.\n");
                return;
        }
        needle_len = strlen(needle);
        haystack_len = strlen(haystack);
        if (needle_len > 128) {

Caught this boner in a previous post.
                fprintf(stderr, "test_strstr: needle too long (limit %d)\n",
                        MAX_LEN);

Unconscionably bad. strstr simply should not depend on having a string
length < N, any N. If N is too small, this strstr will fail, and
that's simply not acceptable behavior in a utility. If N is too large,
it will occupy a wasteful amount of space in 99% of cases.

You didn't even realize that you could have malloc'd five times the
size of the string if you insist on using a buffer!

Great programmers know how to minimize preconditions but you won't
learn. Whether or not you malloc(), you unnecessarily precondition the
success of your code on availability of storage. This is UNACCEPTABLE
in a general-purpose utility.

And spare me the Song, das Lied, of the Incompetent Programmer:

Oh it doesn't matter that it sucks
It's a fast and dirty solution
Just pay me the big bucks
And let others clean up my pollution.

What are you, academic?
Aw what the heck, why do you care?
You must be a queer, I fear, for giving a ****
About things about which think I don't dare!

Oh it doesn't matter that it sucks
It's a fast and a dirty sol-u-tion
Just wire me the money, ducks
I've such a studly reputation!

You've failed Computer Science 101 Using C, and I suggest you change
your major.
                return;
        }
        if (haystack_len > 128) {
                fprintf(stderr, "test_strstr: haystack too long (limit %d)\n",
                        MAX_LEN);
                return;
        }
        strcpy(store_needle, needle);

Incompetent, utterly so. Do you even realize that you're not only
either wasting space or failing to handle larger strings, and that you
not only fail to properly use the symbol you defined for maximum
length, you also unnecessarily conditioning the performance of the
strstr linearly on the length of the strings passed, and that byte
copying is slower? I thought not.

You have no aesthetic right to copy data for a strstr. You need to
minimize your visits to any one byte down to one visit because this is
formally all you need. Even if your code is not working in a deep
multitasking environment such that the precondition "bytes to the left
of the scan index will not change" is not met because your strstr is
in a coroutine relationship with another process guaranteed to follow
your strstr, you're a failure, since you waste computer time and
storage. Your storage waste is especially egregious since it is
unbounded.

Again: I would not ordinarily analyze another's work and condemn him
so roundly, but YOU are the one who tried to ruin Schildt's career,
and computers are not as important as people. YOU are the one who
turned aside my email when I tried to arrange a conference with you
and called me "insane" and a "moron" in an unprofessional way.
Therefore, your ass is going down. If you were a great programmer or
even an acceptable programmer I would address only the morality of
targeting people for an unreliability in published code that is
generalized and an artifact of capitalist production. But as it is,
you are far less competent than is Herb Schildt, and need to be forced
to eat your own dog food.

Please, go back to school.
 
I

Ike Naar

Do we even have evidence that he 'worked with' John Nash. If I were
to apply Bilge's levels of reliability and truthiness to what I post,
heck, I'd probably be able to say I taught Linus Torvalds how to
program. Being in the vicinity of does not equate to 'working with'.

Take your own advice, and "evolve the ability to use a killfile. Please."
 
S

spinoza1111

Okay, this sounded fun.  Here's a trivial test harness and a trivialstrstr.
Feel free to find bugs.  The only one I caught in testing was that I had
the order of the two arguments reversed -- I did (needle, haystack) rather
than (haystack, needle).  Feel free to present broken cases; I have no
illusions that I'll have gotten this bug-free on the first try.

OK, looking at the times on these posts you took thirty minutes.

That would explain trivial bugs, but:

1. Failure to consistently use a symbol YOU declared shows extreme
and unacceptable carelessness

2. In only thirty minutes, you decided on the wrong approach, which
was to make the workability of your solution dependent on have five
times the longest possible string's length of memory available.

It is true that some great programmers work FAST. Rob Pike, as Brian
Kernighan describes it in Beautiful Code, developed a fairly good
scanner (that wasn't in my book a regex) in an hour. My first program
was developed in a day; the previous manager had estimated six months.
However, I've always felt that speed of development to be overrated.

However, you get no points for fast slop, and that is what you have
posted. As I find time, I shall research in depth to show you just how
sloppy and uneducated you are.

But far more important, you come in here expecting CHARITY for not
having enough time and being ADHD which I and others would be all to
ready to give, save for the fact that you fail to extend this charity
to others. People are more important than machines, Dweebach. Get that
through your spoiled brat, Goth-sodden, media besot brain.
This program assumes that the librarystrstr() works.

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

char *my_strstr(const char *s1, const char *s2);

/* for test harness, not for implementation */
#define MAX_LEN 128

/* imagine that a large buffer is divided into five parts:
 * 1 2 3 4 5
 * test_strstr() copies the argument strings into slots 2 and 4, so
 * that results can be compared for relative position, not just equality,
 * because they're all in a single argument.
 */
void
test_strstr(char *haystack, char *needle) {
        size_t needle_len, haystack_len;
        char big_buffer[MAX_LEN * 5] = { 0 };
        char *store_needle = big_buffer + (MAX_LEN * 1);
        char *store_haystack = big_buffer + (MAX_LEN * 3);

        char *lib_return, *my_return;

        if (!needle || !haystack) {
                fprintf(stderr, "error: test_strstr() needs valid strings.\n");
                return;
        }
        needle_len = strlen(needle);
        haystack_len = strlen(haystack);
        if (needle_len > 128) {
                fprintf(stderr, "test_strstr: needle too long (limit %d)\n",
                        MAX_LEN);
                return;
        }
        if (haystack_len > 128) {
                fprintf(stderr, "test_strstr: haystack too long (limit %d)\n",
                        MAX_LEN);
                return;
        }
        strcpy(store_needle, needle);
        strcpy(store_haystack, haystack);
        lib_return =strstr(store_haystack, store_needle);
        my_return = my_strstr(store_haystack, store_needle);

        printf("test: <%s> in <%s>: ",
                store_needle, store_haystack);
        if (lib_return == my_return) {
                if (lib_return)
                        printf("<%s> (offset %d).\n",
                                lib_return, lib_return - store_haystack);
                else
                        printf("No match.\n");
                return;
        }
        /* they don't match... what went wrong? */
        if (!my_return) {
                printf("I found no match, lib found <%s> (offset %d).\n",
                        lib_return, lib_return - store_haystack);
                return;
        }
        if (my_return < store_haystack) {
                printf("return (%p) underruns haystack (%p - %p)?\n",
                        (void *) my_return, (void *) store_haystack,
                        (void *) (store_haystack + haystack_len));
                return;
        }
        if (my_return > store_haystack + haystack_len) {
                printf("return (%p) overruns haystack (%p - %p)?\n",
                        (void *) my_return, (void *) store_haystack,
                        (void *) (store_haystack + haystack_len));
                return;
        }
        /* so at this point, my_return is non-null and in the haystack */
        if (!lib_return) {
                printf("lib found no match, I found <%s> (offset %d).\n",
                        my_return, my_return - store_haystack);
        }
        printf("lib/my return mismatch:\n");
        printf("\tlib: <%s> at %d\n", lib_return, lib_return - store_haystack);
        printf("\tme:  <%s> at %d\n", my_return, my_return - store_haystack);

}

char *
my_strstr(const char *haystack, const char *needle) {
        const char *found = 0;
        const char *next_candidate = 0;
        const char *h, *n;

        /* an empty string is found immediately, even in an empty string */
        if (!*needle)
                found = haystack;
        for (; !found && *haystack; ++haystack) {
                if (*haystack == *needle) {
                        next_candidate = 0;
                        h = haystack;
                        n = needle;
                        /* stash the next spot matching the first
                         * character of the needle.
                         */
                        while (*++n == *++h) {
                                if (*n == *haystack && !next_candidate)
                                        next_candidate = h;
                        }
                        /* we reached the end of the needle, so
                         * we are done
                         */
                        if (!*n) {
                                found = haystack;
                        } else {
                                if (next_candidate)
                                        haystack = next_candidate - 1;
                                else
                                        haystack = h - 1;
                        }
                }
        }

        /* sorry, no way around it; we can't return a possibly-qualified
         * pointer, so we have to drop const in case the original strings
         * were not really const.
         */
        return (char *) found;

}

int
main(void) {
        test_strstr("foobar", "foo");
        test_strstr("foobar", "bar");
        test_strstr("foobar", "baz");
        test_strstr("banana", "na");
        test_strstr("bananas", "nas");
        test_strstr("iced tea", "a");
        test_strstr("blah", "");
        return 0;

}
 
S

spinoza1111

Sylvia Nasar, "A Beautiful Mind": look in the index under Nilges,
Edward G., or on p 354 of the mass market paperback edition.
Take your own advice, and "evolve the ability to use a killfile. Please."

Be nice if instead of recommending a mythical facility that no-one
here seems to know how to use, you did some simple homework (visiting
a public library) to prove the guy wrong. But in this toxic climate of
hatred and self-hatred, dweebs don't value reputations or
accountability as much they value programming languages they cannot
even use properly.
 
S

spinoza1111

You are not entitled to write lines that witty.  

Oh, I think we can cut him a break, since it's really not that witty.
That would be:

Nilges briefly worked with Nash
He thinks it's quite a smash
But then again, he ain't Ogden
Even tho he worked with a Nash

Like Cyrano, who came up extempore with fifty different ways to insult
his own nose, I can insult myself better than you can insult me. But
I'd rather insult Dweebach:

There is a sot named Dweebach
Whose Mommy gave him a Zweiback
Which he gummed and then some
That infantile sod named Dweebach

(5 seconds per limerick).

And what shall we do with Peter
Who thinks he can program a computer
But makes bonehead mistakes
And medication takes
That incompetent programmer, named Peter

There's an anonymous Internet coward
Is it Al? Is it Mickey? Is it Howard?
Nobody knows, and that's why he goes
On destroying reputations, the blowhard.

(Original. Now for pastiche.)

They seek him here, they seek him there
Those regulars seek him everywhere
Is he in Heaven? Or in Hell?
That damn'd elusive Nilges won't tell!
 
B

blmblm

("library strstr()". Grateful though I am that Google maintains
an archive of Usenet posts and makes it available, why oh why can't
they provide a posting interface without irritating glitches .... )
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *my_strstr(const char *s1, const char *s2);

/* for test harness, not for implementation */
#define MAX_LEN 128

(Sigh) Incompetent programmers love "buffers" despite the fact that
"buffers" of ANY memory size are either bugs waiting to happen, or
memory hogs (there is no other alternative). People who take compsci
learn about links.
/* imagine that a large buffer is divided into five parts:
* 1 2 3 4 5
* test_strstr() copies the argument strings into slots 2 and 4, so
* that results can be compared for relative position, not just equality,
* because they're all in a single argument.
*/
void
test_strstr(char *haystack, char *needle) {
size_t needle_len, haystack_len;
char big_buffer[MAX_LEN * 5] = { 0 };
char *store_needle = big_buffer + (MAX_LEN * 1);
char *store_haystack = big_buffer + (MAX_LEN * 3);

char *lib_return, *my_return;

if (!needle || !haystack) {
fprintf(stderr, "error: test_strstr() needs valid strings.\n");
return;
}
needle_len = strlen(needle);
haystack_len = strlen(haystack);
if (needle_len > 128) {

ROTFLMFAO.

This is a junior programmer script kiddie newbie error! You define
MAX_LEN above as 128 because da big boys do so, ignorantly copying,
aping their style.

Now this, I think, is a fair cop. Seebs, is this another case of
not getting the easy stuff right? though really, it's kind of hard
for me to imagine ....
News flash, Dweebach: the big boys do so SO THE SYMBOL CAN BE LATER
USED IN TESTS AND CAN BE CHANGED IN ONE PLACE. We knew this even in
mainframe Cobol.

But you've hard-coded the limit value!

How dare you, how dare you attack Schildt! Every fucking scrap of code
you've submitted to this newsgroup contains, not just bugs, but
completely wrong code which demonstrates that you come here to steal
intellectual product in the form of fixes to code that a professional
programmer would be ashamed of.

* A %s search which failed because you used strchr and not string.h's
strstr

Did it actually fail, in the context in which it was intended to be
used?
* A strlen with an off by one error
* switch() statements which use an unstructured and needlessly
misleading style
* Logic leaks in which you leave significant variables completely
uninitialized so that "the worst bug" can happen...everything seems to
work. But you give a ****, right?

And now this monstrosity.

Oh, this is going to be fun. I have to go to work at this time but I
look forward to a most amusing time with this code, Yet Another
Dweebach-o-rama.



HA HA HA HA HA HA


128! MAX_LEN! 128! MAX_LEN!

[ snip ]
 
B

blmblm

Okay, this sounded fun. Here's a trivial test harness and a trivialstrstr.

Nearly two weeks I solved the problem...wow, that's almost as good as
the two months you needed to show us that you don't understand
structured-programming a switch() statement.
Feel free to find bugs.

Nyah ha ha...cue Dr. Evil laugh
The only one I caught in testing was that I had
the order of the two arguments reversed -- I did (needle, haystack) rather
than (haystack, needle). Feel free to present broken cases; I have no
illusions that I'll have gotten this bug-free on the first try.

This program assumes that the librarystrstr() works.

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

char *my_strstr(const char *s1, const char *s2);

/* for test harness, not for implementation */
#define MAX_LEN 128

/* imagine that a large buffer is divided into five parts:
* 1 2 3 4 5
* test_strstr() copies the argument strings into slots 2 and 4, so
* that results can be compared for relative position, not just equality,
* because they're all in a single argument.
*/
void
test_strstr(char *haystack, char *needle) {
size_t needle_len, haystack_len;
char big_buffer[MAX_LEN * 5] = { 0 };
char *store_needle = big_buffer + (MAX_LEN * 1);
char *store_haystack = big_buffer + (MAX_LEN * 3);

char *lib_return, *my_return;

if (!needle || !haystack) {
fprintf(stderr, "error: test_strstr() needs valid strings.\n");
return;
}
needle_len = strlen(needle);
haystack_len = strlen(haystack);
if (needle_len > 128) {

Caught this boner in a previous post.
fprintf(stderr, "test_strstr: needle too long (limit %d)\n",
MAX_LEN);

Unconscionably bad. strstr simply should not depend on having a string
length < N, any N. If N is too small, this strstr will fail, and
that's simply not acceptable behavior in a utility. If N is too large,
it will occupy a wasteful amount of space in 99% of cases.

Um, not to spoil your fun, but as best I can tell the limitation applies
only to the test harness, not to the actual my_strstr function.
You didn't even realize that you could have malloc'd five times the
size of the string if you insist on using a buffer!

Great programmers know how to minimize preconditions but you won't
learn. Whether or not you malloc(), you unnecessarily precondition the
success of your code on availability of storage. This is UNACCEPTABLE
in a general-purpose utility.

See above.
And spare me the Song, das Lied, of the Incompetent Programmer:

Oh it doesn't matter that it sucks
It's a fast and dirty solution
Just pay me the big bucks
And let others clean up my pollution.

What are you, academic?
Aw what the heck, why do you care?
You must be a queer, I fear, for giving a ****
About things about which think I don't dare!

Oh it doesn't matter that it sucks
It's a fast and a dirty sol-u-tion
Just wire me the money, ducks
I've such a studly reputation!

You've failed Computer Science 101 Using C, and I suggest you change
your major.


Incompetent, utterly so. Do you even realize that you're not only
either wasting space or failing to handle larger strings, and that you
not only fail to properly use the symbol you defined for maximum
length, you also unnecessarily conditioning the performance of the
strstr linearly on the length of the strings passed, and that byte
copying is slower? I thought not.

Since the above code is part of the *test harness*, how does it affect
the performance of my_strstr?
 
S

spinoza1111

Most of the time (but not always), I test for every defined value
(usually excluding things like FOO_NONE or FOO_MAX) explicitly, and "default"
is there to handle the possibility that a value not in the defined range
at all will occur.

Which is fine. But in the case of ack and nak in queue.c, you
fallthrough over code which at the time you wrote it contains no valid
case handling, but could easily be changed by someone who doesn't
realize that ack and nak are invalid for the client, as you say you
state in the documentation. The implicit rule is that the maintainer
may NOT put actually valid cases under ack and nak!

The reason why we avoid unstructured code (which is what a fallthrough
switch() is, being irreducible to the Bohm Jacopini primitives unlike
other switch() statements but unnecessary for a Turing complete
language) is precisely to avoid these gotchas. Many programmers do not
read the documentation, not so much out of sloth, instead because the
documentation is so often out of date or wrong.

You've never learned to write for true readability, which is something
you have to learn by taking computer science classes for the most
part. This is because in a class, you have to hand in your work to an
instructor or graduate assistant who must grade it. Whereas many
corporate groups in my experience are designed by their own members
with the silent complicity of top management to avoid quality control
so as to meet deadlines, with code reading given at best lip service.

This means that I think you are lying when you claim that queue.c is a
group effort where you reviewed the code. I think that you're a script
kiddie who's not allowed to write code like a man because, as you
yourself concede, you get simple things wrong in a field where (news
flash) we build complex systems out of simple things, what Dijkstra
called a cloud of mosquitos humming in harmony. I don't think a
competent coworker would have stood for a Duff's device, or
fallthrough case, because they are legacy and idiomatic styles, and
unacceptable today.

You are the Sarah Palin of this newsgroup. I hope Palin is taking some
courses in American history and politics at her local junior college
if she plans to run for President on the Bonehead ticket in 2012. I
suggest you beat your ass on over to DeVry. The quality of the
instructors at DeVry varies (I was one, which threw the standard
deviation out of kilter) but the less able ones will stick to the
text, and force you to do the work, since private, for-profit
universities are under close supervision by state accreditation
boards. I worked all night at grading time to justify each grade in my
Visual Basic classics, which had 60 students since the students wanted
a competent instructor.

And it will help to overcome the racism implicit in your idiotic
statement about poetry you can't write, which I write when pushed
beyond prose by the savage idiocy of this newsgroup: that English must
not be my "mother tongue". This is the racism of white boys who have
been mollycoddled, and selected because of a white skin and a middle
class background for corporate programming jobs over better qualified
women, blacks, Hispanics and Asians: a racism also seen in the half-
literate signs of the Tea Baggers, which make elementary English
mistakes...in calling for an English "onlie" society.

This is also the racism of a newsgroup that has twice in the past year
attacked and disrespected mainland Chinese students who post here at
some risk, for their English, and the racism of calling people
"trolls" because the respondent has a Master's degree (or in your case
a BA in psychology) but reads at eighth grade level.
 
B

blmblm

OK, looking at the times on these posts you took thirty minutes.

That would explain trivial bugs, but:

1. Failure to consistently use a symbol YOU declared shows extreme
and unacceptable carelessness

2. In only thirty minutes, you decided on the wrong approach, which
was to make the workability of your solution dependent on have five
times the longest possible string's length of memory available.

You do know that the only part of the solution that has this
dependency is the test harness, right?
It is true that some great programmers work FAST. Rob Pike, as Brian
Kernighan describes it in Beautiful Code, developed a fairly good
scanner (that wasn't in my book a regex) in an hour. My first program
was developed in a day; the previous manager had estimated six months.
However, I've always felt that speed of development to be overrated.

However, you get no points for fast slop, and that is what you have
posted. As I find time, I shall research in depth to show you just how
sloppy and uneducated you are.

But far more important, you come in here expecting CHARITY for not
having enough time and being ADHD which I and others would be all to
ready to give, save for the fact that you fail to extend this charity
to others. People are more important than machines, Dweebach. Get that
through your spoiled brat, Goth-sodden, media besot brain.
This program assumes that the librarystrstr() works.

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

char *my_strstr(const char *s1, const char *s2);

/* for test harness, not for implementation */
#define MAX_LEN 128

/* imagine that a large buffer is divided into five parts:
* 1 2 3 4 5
* test_strstr() copies the argument strings into slots 2 and 4, so
* that results can be compared for relative position, not just equality,
* because they're all in a single argument.
*/
void
test_strstr(char *haystack, char *needle) {
size_t needle_len, haystack_len;
char big_buffer[MAX_LEN * 5] = { 0 };
char *store_needle = big_buffer + (MAX_LEN * 1);
char *store_haystack = big_buffer + (MAX_LEN * 3);

char *lib_return, *my_return;

if (!needle || !haystack) {
fprintf(stderr, "error: test_strstr() needs valid strings.\n");
return;
}
needle_len = strlen(needle);
haystack_len = strlen(haystack);
if (needle_len > 128) {
fprintf(stderr, "test_strstr: needle too long (limit %d)\n",
MAX_LEN);
return;
}
if (haystack_len > 128) {
fprintf(stderr, "test_strstr: haystack too long (limit %d)\n",
MAX_LEN);
return;
}
strcpy(store_needle, needle);
strcpy(store_haystack, haystack);
lib_return =strstr(store_haystack, store_needle);
my_return = my_strstr(store_haystack, store_needle);

printf("test: <%s> in <%s>: ",
store_needle, store_haystack);
if (lib_return == my_return) {
if (lib_return)
printf("<%s> (offset %d).\n",
lib_return, lib_return - store_haystack);
else
printf("No match.\n");
return;
}
/* they don't match... what went wrong? */
if (!my_return) {
printf("I found no match, lib found <%s> (offset %d).\n",
lib_return, lib_return - store_haystack);
return;
}
if (my_return < store_haystack) {
printf("return (%p) underruns haystack (%p - %p)?\n",
(void *) my_return, (void *) store_haystack,
(void *) (store_haystack + haystack_len));
return;
}
if (my_return > store_haystack + haystack_len) {
printf("return (%p) overruns haystack (%p - %p)?\n",
(void *) my_return, (void *) store_haystack,
(void *) (store_haystack + haystack_len));
return;
}
/* so at this point, my_return is non-null and in the haystack */
if (!lib_return) {
printf("lib found no match, I found <%s> (offset %d).\n",
my_return, my_return - store_haystack);
}
printf("lib/my return mismatch:\n");
printf("\tlib: <%s> at %d\n", lib_return, lib_return - store_haystack);
printf("\tme: <%s> at %d\n", my_return, my_return - store_haystack);

}

char *
my_strstr(const char *haystack, const char *needle) {
const char *found = 0;
const char *next_candidate = 0;
const char *h, *n;

/* an empty string is found immediately, even in an empty string */
if (!*needle)
found = haystack;
for (; !found && *haystack; ++haystack) {
if (*haystack == *needle) {
next_candidate = 0;
h = haystack;
n = needle;
/* stash the next spot matching the first
* character of the needle.
*/
while (*++n == *++h) {
if (*n == *haystack && !next_candidate)
next_candidate = h;
}
/* we reached the end of the needle, so
* we are done
*/
if (!*n) {
found = haystack;
} else {
if (next_candidate)
haystack = next_candidate - 1;
else
haystack = h - 1;
}
}
}

/* sorry, no way around it; we can't return a possibly-qualified
* pointer, so we have to drop const in case the original strings
* were not really const.
*/
return (char *) found;

}

int
main(void) {
test_strstr("foobar", "foo");
test_strstr("foobar", "bar");
test_strstr("foobar", "baz");
test_strstr("banana", "na");
test_strstr("bananas", "nas");
test_strstr("iced tea", "a");
test_strstr("blah", "");
return 0;

}

[ snip quoted sig ]
 
S

spinoza1111

("library strstr()".  Grateful though I am that Google maintains
an archive of Usenet posts and makes it available, why oh why can't
they provide a posting interface without irritating glitches .... )




(Sigh) Incompetent programmers love "buffers" despite the fact that
"buffers" of ANY memory size are either bugs waiting to happen, or
memory hogs (there is no other alternative). People who take compsci
learn about links.
/* imagine that a large buffer is divided into five parts:
 * 1 2 3 4 5
 * test_strstr() copies the argument strings into slots 2 and 4, so
 * that results can be compared for relative position, not just equality,
 * because they're all in a single argument.
 */
void
test_strstr(char *haystack, char *needle) {
        size_t needle_len, haystack_len;
        char big_buffer[MAX_LEN * 5] = { 0 };
        char *store_needle = big_buffer + (MAX_LEN * 1);
        char *store_haystack = big_buffer + (MAX_LEN * 3);
        char *lib_return, *my_return;
        if (!needle || !haystack) {
                fprintf(stderr, "error: test_strstr() needs valid strings.\n");
                return;
        }
        needle_len = strlen(needle);
        haystack_len = strlen(haystack);
        if (needle_len > 128) {
ROTFLMFAO.

This is a junior programmer script kiddie newbie error! You define
MAX_LEN above as 128 because da big boys do so, ignorantly copying,
aping their style.

Now this, I think, is a fair cop.  Seebs, is this another case of
not getting the easy stuff right?  though really, it's kind of hard
for me to imagine ....
News flash, Dweebach: the big boys do so SO THE SYMBOL CAN BE LATER
USED IN TESTS AND CAN BE CHANGED IN ONE PLACE. We knew this even in
mainframe Cobol.
But you've hard-coded the limit value!
How dare you, how dare you attack Schildt! Every fucking scrap of code
you've submitted to this newsgroup contains, not just bugs, but
completely wrong code which demonstrates that you come here to steal
intellectual product in the form of fixes to code that a professional
programmer would be ashamed of.
*  A %s search which failed because you used strchr and not string.h's
strstr

Did it actually fail, in the context in which it was intended to be
used?

Search me. In the context such a tool is intended to be used, you
don't use C. Instead, you use a scripting language with builtin string
handling such as Rexx for the IBM mainframe, Visual Basic .Net or
Visual Basic for Applications on Microsoft platforms, or awk or its
descendants on Linux and unix. The code was completely useless to
anyone here as opposed to the instructional utility of demonstrating
how to learn string handling from people like Willem and Ben (and me)
by discarding string.h. It was a vanity effort which I think Peter
meant to show that he was qualified to code C. As such, he
demonstrated to me that he's far less qualified than he thinks he is,
and far less qualified than Heathfield, who has a good grasp of the
trees but sometimes gets lost in the forest. This has been confirmed
in recent weeks by each code snippet and program he has posted.

But...he would merit my silent pity, and I would make no comment, save
for the Schildt canard, and his treatment, last January, of my
collegial request for an exchange of email about Schildt. As you will
recall, he discarded my email unread and proceeded to repeatedly call
me (a fellow Apress author) "insane", a "moron", and a "kook". I am
none of these things.

The worst type of bug is one that doesn't "actually fail", most of the
time, or even never, when, years later, a maintenance programmer makes
a small change (such as adding %t as a different type of pattern, and
not expecting it to be changed), only to have the new code fail.
Professional programmers produce, as I produce, tokens of a type or
set of alternative texts which meet a range of neighboring
possibilities in such a way that it's easy to change from one token to
the next.

[Peter claims to have fixed the %s/%t confusion but his fix did not
address the ontological heart of the matter: that %s and %t are
strings, and IF you include string.h, THEN you need to use strstr.]

This sounds like the ravings of a "crazy man" who caught schizophrenia
from Nash only to uneducated paraprogrammers, whether the truly
unwashed, or people who "washed" out of other fields and came, filled
with self-hatred, shame and anger, to programming. But the fact is
that like a number of older programmers (such as Richard Stallman), I
spent a number of summers yearning for a CPU and drycoding programs,
along with learning mathematics, logic and the foundations of
mathematics. I also studied theater and literature in that time so
that by the time I was a graduate student in CS, I'd learned that
people and ideas matter far more than machines and software.

I'm afraid that Peter never had this chance, nor the chance to solve
difficult problems on his own, but not on his own terms. He was
sitting in a university, presumably with Mommy and Daddy paying his
tuition, unlike my middle class black and female students at DeVry,
who staggered in exhausted from working two jobs to pay their
tuition.

If he was interested in computers, it seems reasonable that he would
have taken a class; I jumped at the chance, in 1970, to take the first
class in computer science at Roosevelt University in Chicago. I can
only conclude that he's developed a passive-aggressive style which is
better treated by traditional psychiatry and outdoor service work than
medication...but would caution you, saying that that diagnosis is
probably irresponsible, possibly as irresponsible as people who
diagnose me as schizo because they can't read worth dick.
*  A strlen with an off by one error
*  switch() statements which use an unstructured and needlessly
misleading style
*  Logic leaks in which you leave significant variables completely
uninitialized so that "the worst bug" can happen...everything seems to
work. But you give a ****, right?
And now this monstrosity.
Oh, this is going to be fun. I have to go to work at this time but I
look forward to a most amusing time with this code, Yet Another
Dweebach-o-rama.
HA HA HA HA HA HA
128! MAX_LEN! 128! MAX_LEN!

[ snip ]
 
B

blmblm

Which is fine. But in the case of ack and nak in queue.c, you
fallthrough over code which at the time you wrote it contains no valid
case handling, but could easily be changed by someone who doesn't
realize that ack and nak are invalid for the client, as you say you
state in the documentation. The implicit rule is that the maintainer
may NOT put actually valid cases under ack and nak!

The reason why we avoid unstructured code (which is what a fallthrough
switch() is, being irreducible to the Bohm Jacopini primitives unlike
other switch() statements

I must be misunderstanding something, because I thought the point of
those primitives was that any program could be expressed using them.
If that's the case, surely any program, even an ill-structured one [*],
can be so expressed? What does "irreducible" mean in context?

[*] Not that I necessarily think the code in question is ill-structured.
but unnecessary for a Turing complete
language) is precisely to avoid these gotchas. Many programmers do not
read the documentation, not so much out of sloth, instead because the
documentation is so often out of date or wrong.

You've never learned to write for true readability, which is something
you have to learn by taking computer science classes for the most
part. This is because in a class, you have to hand in your work to an
instructor or graduate assistant who must grade it. Whereas many
corporate groups in my experience are designed by their own members
with the silent complicity of top management to avoid quality control
so as to meet deadlines, with code reading given at best lip service.

This means that I think you are lying when you claim that queue.c is a
group effort where you reviewed the code. I think that you're a script
kiddie who's not allowed to write code like a man because, as you
yourself concede, you get simple things wrong in a field where (news
flash) we build complex systems out of simple things, what Dijkstra
called a cloud of mosquitos humming in harmony. I don't think a
competent coworker would have stood for a Duff's device, or
fallthrough case, because they are legacy and idiomatic styles, and
unacceptable today.

[ snip ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,102
Messages
2,570,645
Members
47,246
Latest member
TemekaLutz

Latest Threads

Top