#include <stdlib.h>
Ben Bacarisse tested this code for finding aax in aaax and it failed.
I spent about ten minutes to discover that at the point where I need
to note the "character handle" address in the "master" string, I noted
it in the TARGET string. Oh gee, I am adhd mommie! But I'm rilly
great!
Seriously, that's why the code was submitted, to find and fix errors.
Please note that Seebach does not respond to error reports quickly or
at all, whereas a real programmer treats them as a challenge to fix
the error ... FAST. And, we're talking two months to mess up two case
statements. I still maintain that he's here for fixes and not to
participate in collective debugging, and I say this to avoid tu quoque
arguments.
I do not claim that this strstr is bug free. That awaits my finding
time to compose a correctness proof in natural language, based on
recursion on the length of the string in all probability.
Thanks again to Ben
Who finds so many errors
When I get mail from him
I am filled with nameless terrors
For he finds so much stuff
Which shows my code is a draft that is rough.
#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 *
// * *
// * 03 19 10 Nilges Version 1.11: bug: ptrMaster was *
// * incorrectly set one past the *
// * ptrHandle *
// * *
// * 03 20 10 Nilges Version 1.12 *
// * *
// * 1. Bug (reported by BB): *
// * assignment used in place of *
// * equality test *
// * *
// * 2. Bug: incorrect test for noting *
// * char handle goes all the way *
// * back to start of string *
// * *
// * 03 21 10 Nilges Version 1.13 *
// * *
// * 1. Boolean statement simplified *
// * per Morris Keesan. *
// * *
// * 2. Bug found by Ben Bacarisse: *
// * statement that records char *\
// * handle set it to target and not*
// * master. *
// * *
// * ----------------------------------------------------------- *
// * *
// * 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 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;
char *ptrMasterStart = 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;
ptrMasterStart = ptrMaster;
for (;
*ptrTarget
?
(*ptrMaster
?
*ptrMaster==*ptrTarget
:
FALSITY)
:
(booFound = TRUTH, FALSITY);
ptrMaster++, ptrTarget++)
{
if (ptrHandle == 0 // Rel 1.12
&&
ptrMaster > ptrMasterStart
&&
*ptrMaster == *strTarget)
ptrHandle = ptrMaster; // Rel. 1.13
}
if (booFound) return strMaster + *ptrIndex;
if (ptrHandle) ptrMaster = ptrHandle; // Rel. 1.11 bug fix
}
*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 Version 1.13\n\n");
printf("Expect 'aax': %s\n",
strstrWithIndex("aaax", "aax", &intIndex1));
printf("Expect 1: %d\n", intIndex1);
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;
}