On Mar 19, 9:19*pm, pete <pfil...@mindspring.com> wrote:
> spinoza1111 wrote:
>
> > In the replace() program of last month's flame festival, a little
> > program was trying to get out. Here it is: an implementation of strstr
> > including a call that returns the offset of the found substring. Two
> > hours including all comments and dedicatory ode, written for this
> > occasion.
> > * * printf("Expect 0: %d\n", strstr("", ""));
> > * * printf("Expect 0: %d\n", strstr("0123456789", ""));
>
> That's not what strstr is supposed to do.
> When the second argument to strstr points to an empty string,
> then strstr is supposed to return the first argument,
> which happens to be a non null pointer in the above cases.
Ill-defined. I don't choose to simulate mistakes, here. A null master
string is one in which a target string can never occur: a null target
could only occur in a null master string, but see rule one.
Perhaps I'm being narrow minded.
I suppose you could make a case, in a world biased towards left to
right, that all strings start with a magic invisible null string,
including a null master string.
So test for a null target, and if it is found, return the master
string's address and an index of 0 in strstrWithIndex().
Then, and only then, return 0 (not found) if the master string is
null.
You know what? Done.
#include <stdlib.h>
#include <stdio.h>
// ************************************************** *************
// * *
// * strstr *
// * *
// * This function (strstr) finds a string, probably as fast as *
// * possible without extra memory usage over and above brute *
// * force. *
// * *
// * In searching a Nul terminated string for a substring, there *
// * are logically three possibilities in a left to right *
// * traversal of the master string that (1) looks for the *
// * first character of the target and then (2) matches all the *
// * remaining characters: *
// * *
// * * (Erroneous): on the failure of a partial match, *
// * restart at the first nonmatching character. This is *
// * fast but wrong, since the matching string may *
// * overlap the partial match. *
// * *
// * * (Too slow): on the failure of a partial match, start*
// * one past the first character (of the partial match) *
// * *
// * * (Just right): while matching characters, note the *
// * leftmost character in the searched string, to the *
// * right of the first matched character, that matches *
// * both that character and, of course, the first *
// * character of the target. *
// * *
// * C H A N G E R E C O R D --------------------------------- *
// * DATE PROGRAMMER DESCRIPTION OF CHANGE *
// * -------- ---------- --------------------------------- *
// * 03 18 10 Nilges Version 1.0 *
// * *
// * 03 19 10 Nilges Version 1.1 *
// * *
// * 1. Incorporates Pete's suggestion*
// * that a null target string is *
// * always found at the start of *
// * the master string. *
// * *
// * 2. Results display enhanced *
// * *
// * 3. Poem corrected (doth NOT *
// * match) *
// * *
// * ----------------------------------------------------------- *
// * *
// * To find a string, oh Muse! I sing, inside another String! *
// * Alternatives to me come in Three, ah, that's the thing: *
// * For the one thing for which the Wise must watch is mayhap, *
// * Partial occurences that most melancholy, overlap. *
// * The first is base, mechanical, low, and tragicomical: *
// * It's to restart from the previous beginning plus but One *
// * Oh what Mayhem to true Programming is thereby, done! *
// * But the job it will do, as did Hercules, *
// * His Labors for the Goddess cruel in Seneca's tragedies: *
// * Arduously and ignobly like unto the meanest Hind *
// * That knoweth not his Elbow from his Behind. *
// * The second is worse, a boner, a solecism, and a Seebach: *
// * The second restarts at the character that doth not match! *
// * Oh muse! Such hellish Sights before me yawn: *
// * But be assur'd, 'tis darkest just before the Dawn. *
// * Shout for Victory, oh Thrace, and smite the Harp, and Grin: *
// * For lo, we start at the leftmost "handle" of the string *
// * When it occureth in *
// * The tragic partial match that hath failed us. *
// * If no such handle exists, then we can restart *
// * At the point of match failure: no, 'tis not a brain fart. *
// * Now we spy our magic bus: *
// * For this is the best Al Gore ithm *
// * That we can hope for in C, a language without Rhyme, or *
// * for that matter, Oh Muse! rhythm. *
// * *
// ************************************************** *************
#define TRUTH -1
#define FALSITY 0
#define NULLITY 0
char * strstrWithIndex(char *strMaster,
char *strTarget,
int *ptrIndex)
{
char *ptrMaster = NULLITY;
char *ptrTarget = NULLITY;
char *ptrHandle = NULLITY;
int booFound = FALSITY;
*ptrIndex = 0; // Rel. 1.1
if (!*strTarget) return strMaster; // Rel. 1.1
if (!*strMaster) return 0; // Rel. 1.1
for (ptrMaster = strMaster; *ptrMaster

{
for (;
*ptrMaster && *ptrMaster != *strTarget;
ptrMaster++);
ptrTarget = strTarget;
*ptrIndex = ptrMaster - strMaster;
ptrHandle = 0;
for (;
*ptrTarget
?
(*ptrMaster
?
(*ptrMaster==*ptrTarget ? TRUTH : FALSITY)
:
FALSITY)
:
(booFound = TRUTH, FALSITY);
ptrMaster++, ptrTarget++)
{
if (ptrHandle = 0
&&
ptrMaster > strMaster
&&
*ptrMaster == *strTarget)
ptrHandle = ptrTarget;
}
if (booFound) return strMaster + *ptrIndex;
if (ptrHandle) ptrMaster = ptrHandle + 1;
}
*ptrIndex = 0;
return 0;
}
char * strstr(char *strMaster, char *strTarget)
{
int ptrIndex = 0;
return strstrWithIndex(strMaster, strTarget, &ptrIndex);
}
int main(void)
{
char *ptrIndex1 = NULLITY;
int intIndex1 = 0;
printf("strstr\n\n");
printf("Expect 0: %x\n", *strstr("", ""));
printf("Expect '0': '%c'\n", *strstr("0123456789", ""));
printf("Expect 0: %d\n", strstr("", "0"));
printf("Expect 0: %d\n", strstr("Here", "There"));
ptrIndex1 = strstrWithIndex("There", "here", &intIndex1);
printf("Expect 1: %d\n", intIndex1);
ptrIndex1 = strstrWithIndex("They seek him here",
"here",
&intIndex1);
printf("Expect 14: %d\n", intIndex1);
ptrIndex1 = strstrWithIndex("They seek him there",
"here",
&intIndex1);
printf("Expect 15: %d\n", intIndex1);
ptrIndex1 = strstrWithIndex
("The clc regs seek him everywhere",
"here",
&intIndex1);
printf("Expect 28: %d\n", intIndex1);
printf("Expect 'h': '%c'\n", *ptrIndex1);
ptrIndex1 = strstrWithIndex
("Is he in Heaven? Or in Hell?",
"?",
&intIndex1);
printf("Expect 15: %d\n", intIndex1);
printf("Expect '?': '%c'\n", *ptrIndex1);
ptrIndex1 = strstrWithIndex
("That damn'd elusive Spinoza won't tell!",
"Spinoza",
&intIndex1);
printf("Expect 20: %d\n", intIndex1);
printf("Expect 'p': '%c'\n", *(ptrIndex1+1));
printf("Expect '0': '%c'\n", *strstr("0123456789", "0"));
printf("Expect '1': '%c'\n", *strstr("0123456789", "1"));
printf("Expect '0': '%c'\n", *strstr("0123456789", "0"));
printf("Expect '9': '%c'\n", *strstr("0123456789", "9"));
printf("Expect '5': '%c'\n",
*strstr("0123456789", "345") + 2);
printf("Expect '8': '%c'\n", *strstr("0123456789", "89"));
ptrIndex1 = strstrWithIndex("0123456789A89AB",
"89AB",
&intIndex1);
printf("Expect 11: %d\n", intIndex1);
return 0;
}
>
> #include <stddef.h>
>
> char *str_str(const char *s1, const char *s2);
> size_t str_len(const char *s);
> char *str_chr(const char *s, int c);
> int str_ncmp(const char *s1, const char *s2, size_t n);
>
> char *str_str(const char *s1, const char *s2)
> {
> * * const int c = *s2++;
>
> * * if (c != '\0') {
> * * * * const size_t n = str_len(s2);
>
> * * * * s1 = str_chr(s1, c);
> * * * * while (s1 != NULL && str_ncmp(s1 + 1, s2, n) != 0) {
> * * * * * * s1 = str_chr(s1 + 1, c);
> * * * * }
> * * }
> * * return (char *)s1;
>
> }
>
> size_t str_len(const char *s)
> {
> * * size_t n;
>
> * * for (n = 0; *s != '\0'; ++s) {
> * * * * ++n;
> * * }
> * * return n;
>
> }
>
> char *str_chr(const char *s, int c)
> {
> * * while (*s != (char)c) {
> * * * * if (*s == '\0') {
> * * * * * * return NULL;
> * * * * }
> * * * * ++s;
> * * }
> * * return (char *)s;
>
> }
>
> int str_ncmp(const char *s1, const char *s2, size_t n)
> { * *
> * * const unsigned char *p1 = (const unsigned char *)s1;
> * * const unsigned char *p2 = (const unsigned char *)s2;
>
> * * for (;
{
> * * * * if (n-- == 0) {
> * * * * * * return 0;
> * * * * }
> * * * * if (*p1 != *p2) {
> * * * * * * return *p2 > *p1 ? -1 : 1;
> * * * * }
> * * * * if (*p1 == '\0') {
> * * * * * * return 0;
> * * * * } * * * *
> * * * * ++p1;
> * * * * ++p2;
> * * }
>
> }
>
> --
> pete