Using a
size_t
for a boolean flag, and calling itflag
, is nearly an obfuscation. Useint
pre-C99 and call it something descriptive likesubstitute
.strlen()
is likely a waste, though it makes describing the algorithm easier. Try to do without the additional iteration.Getting the length of the longest common prefix looks like a well-defined task which can be extracted, and a useful building-block. Do so.
one_way
,one_away
, orone_microsoft_way
? Having a properly-spelled correctly-selected name is Always very important.Change to a single-traversal algorithm:
Remove hethe common prefix.
Measuring the common prefix without the first characters is quite instructive.
With `x` and `y` different from `a`, call `n = strlen_common(++a, ++b)`:
1. At most one substitution at the start:
xaaaabcde
yaaaabcde
Result n == 8, a[n] == b[n].
1. Deletion from the first:
xaaaabcde
aaaabcde
n == 3, strcmp(a + n, b + n - 1) != 0
1. Same way for deletion from second.
The modified code (also live on coliru):
size_t strlen_common(const char* a, const char* b) {
size_t r = 0;
while (*a && *a++ == *b++)
++r;
return r;
}
int one_away(const char* a, const char* b) {
size_t n = strlen_common(a, b);
a += n;
b += n;
if (!*a*a++)
return !*b || !b[1];
if (!*b*b++)
return !a[1];*a;
n = strlen_common(++aa, ++bb);
return a[n] == b[n]
|| !strcmp(a + n - 1, b + n)
|| !strcmp(a + n, b + n - 1);
}